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

Added S3 user management #127

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

UtkarshBhatthere
Copy link
Contributor

@UtkarshBhatthere UtkarshBhatthere commented May 9, 2023

Added CLI to Create, Delete, List and Get S3 users for rgw

ubuntu@microcephtest:~$ sudo microceph s3 list
+---+-------------+
| # |    NAME     |
+---+-------------+
| 1 | test4       |
+---+-------------+
| 2 | testUser100 |
+---+-------------+
| 3 | test        |
+---+-------------+
| 4 | test2       |
+---+-------------+
| 5 | test5       |
+---+-------------+
ubuntu@microcephtest:~$ sudo microceph s3 get testUser100
+-------------+----------------------+------------------------------------------+
|    NAME     |      ACCESS KEY      |                  SECRET                  |
+-------------+----------------------+------------------------------------------+
| testUser100 | 9YI4KEEEZ333ES6Z5PST | iNPJDugy2l1GlnA8TWCWNguncQcb0f6glIjaj1Wu |
+-------------+----------------------+------------------------------------------+
ubuntu@microcephtest:~$ sudo microceph s3 create utkarsh --access-key=yo --secret=doesitwork?
+---------+------------+-------------+
|  NAME   | ACCESS KEY |   SECRET    |
+---------+------------+-------------+
| utkarsh | yo         | doesitwork? |
+---------+------------+-------------+
ubuntu@microcephtest:~$ sudo microceph s3 delete utkarsh
ubuntu@microcephtest:~$ sudo microceph s3 list
+---+-------------+
| # |    NAME     |
+---+-------------+
| 1 | test4       |
+---+-------------+
| 2 | testUser100 |
+---+-------------+
| 3 | test        |
+---+-------------+
| 4 | test2       |
+---+-------------+
| 5 | test5       |
+---+-------------+

@UtkarshBhatthere UtkarshBhatthere marked this pull request as draft May 9, 2023 14:14
@UtkarshBhatthere UtkarshBhatthere self-assigned this May 9, 2023
@UtkarshBhatthere
Copy link
Contributor Author

Added implementation, will add tests for the same.

@UtkarshBhatthere UtkarshBhatthere force-pushed the s3Interface branch 4 times, most recently from 0feaf24 to 6e91346 Compare May 12, 2023 08:15
@UtkarshBhatthere UtkarshBhatthere marked this pull request as ready for review May 26, 2023 11:25
@UtkarshBhatthere UtkarshBhatthere marked this pull request as draft May 26, 2023 12:03
@UtkarshBhatthere
Copy link
Contributor Author

The PR lacks test, will remove from drafts once I have added them.

@UtkarshBhatthere UtkarshBhatthere force-pushed the s3Interface branch 5 times, most recently from 6633df4 to 933e165 Compare July 11, 2023 11:35
@UtkarshBhatthere UtkarshBhatthere force-pushed the s3Interface branch 8 times, most recently from 4bb0de4 to d0b881b Compare July 12, 2023 09:07
@UtkarshBhatthere UtkarshBhatthere marked this pull request as ready for review July 12, 2023 09:33
Copy link
Collaborator

@sabaini sabaini left a comment

Choose a reason for hiding this comment

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

Heya,

this looks very useful.

Some comments after a first quick look:

User interface: we talked about this a bit but jftr. -- think the microceph s3 [create|delete|...] ... might be a bit confusing as it's not clear that this is about creating or deleting users. Maybe could do another subcommand e.g. microceph s3 user [create|delete|...] ... or rename the subcommand to something like microceph s3-user [create|delete|...] ...

REST API: it's recommended to give every entity in a REST api their own URI, and have the REST verbs (GET/PUT/DELETE/...) act on those entities

For this API the entities would be users. It's a convention (though not required by REST) to have directories map to collections of entities.

A mapping to URIs could therefore look something like this, with an example user fooUser

GET /s3/users # list user collection
POST /s3/users # create a new user in collection with data from the req. body

GET /s3/users/fooUser # get details for fooUser (no data required)
PUT /s3/users/fooUser # update fooUser with data from req. body
DELETE /s3/users/fooUser # delete fooUser (no data required)

Note there's no POST /s3/users/fooUser as POST is for creating new entities.

Thanks!

@UtkarshBhatthere UtkarshBhatthere force-pushed the s3Interface branch 3 times, most recently from 3aa3465 to 88f45a5 Compare July 13, 2023 09:14
@UtkarshBhatthere UtkarshBhatthere force-pushed the s3Interface branch 2 times, most recently from 51da731 to e1374d6 Compare July 28, 2023 14:07
@UtkarshBhatthere
Copy link
Contributor Author

@sabaini I have modified the APIs to be using ""services/rgw/user"".

Copy link
Collaborator

@sabaini sabaini left a comment

Choose a reason for hiding this comment

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

Heya Utkarsh, thanks for the update, added a comment about REST API structure

Get: rest.EndpointAction{Handler: cmdS3Get, ProxyTarget: true},
Put: rest.EndpointAction{Handler: cmdS3Put, ProxyTarget: true},
Delete: rest.EndpointAction{Handler: cmdS3Delete, ProxyTarget: true},
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

For optimal RESTy-ness I'd like to suggest an API structure like this:

GET /services/rgw/user # returns a list of users
GET /services/rgw/user/{uid} # returns info about a specific user

POST /services/rgw/user # create a new user

PUT /services/rgw/user/{name} # update existing user

DELETE /services/rgw/user/{name} # delete user

Something like this can be used to specify a path with a {uid} var:

var s3Cmd = rest.Endpoint{
	Path:   "services/rgw/user/{name}",
	Get:    rest.EndpointAction{Handler: cmdS3GetSingle, ProxyTarget: true},
        Put: 
...

func cmdS3GetSingle(s *state.State, r *http.Request) response.Response {
	var err error
	var name string
	name, err = url.PathUnescape(mux.Vars(r)["name"])
	if err != nil {
		return response.BadRequest(err)
	}
	// do something with user name
	user = ceph.GetS3User(name)
...

defer cancel()

ret := ""
err := c.Query(queryCtx, "GET", api.NewURL().Path("services", "rgw", "user"), user, &ret)
Copy link
Collaborator

Choose a reason for hiding this comment

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

With the API structure change I've suggested above the URL would be built with something like

err = c.Query(queryCtx, "GET", api.NewURL().Path("services", "rgw", "user", strconv.FormatInt(user.name, 10)), nil, nil)

@UtkarshBhatthere UtkarshBhatthere marked this pull request as draft September 4, 2023 07:55
@UtkarshBhatthere
Copy link
Contributor Author

Thanks for the detailed review @sabaini 🙏🏼 . I will implement your RESTy suggestions in and make the PR ready.

@UtkarshBhatthere UtkarshBhatthere force-pushed the s3Interface branch 12 times, most recently from d693ae0 to 99ce437 Compare December 13, 2023 05:25
Signed-off-by: Utkarsh Bhatt <utkarsh.bhatt@canonical.com>
Signed-off-by: Utkarsh Bhatt <utkarsh.bhatt@canonical.com>
Signed-off-by: Utkarsh Bhatt <utkarsh.bhatt@canonical.com>
Copy link
Collaborator

@sabaini sabaini left a comment

Choose a reason for hiding this comment

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

Hey @UtkarshBhatthere did a quick once over, added some suggestions mostly around API RESTfulness

@@ -50,7 +54,7 @@ jobs:
run: ~/actionutils.sh headexec enable_rgw

- name: Exercise RGW
run: ~/actionutils.sh headexec testrgw
run: ~/actionutils.sh headexec testrgw_old
Copy link
Collaborator

Choose a reason for hiding this comment

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

Naming nit: maybe a more descriptive name instead of testrgw_old

# boto3 for appS3 test script.
sudo python -m pip install --upgrade pip
sudo pip install boto3
~/actionutils.sh setup_lxd
Copy link
Collaborator

Choose a reason for hiding this comment

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

I see these lines being repeated
Maybe could refactor the actionutils.sh a bit to have a setup_host function instead of setup_lxd that handles all deps

Manage S3 users on MicroCeph
=============================

MicroCeph provides an easy to use interface for creating, viewing and deleting s3 users for interfacing with the RGW endpoint.
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggest: capitalize S3 here and below (proper noun)

=============================

MicroCeph provides an easy to use interface for creating, viewing and deleting s3 users for interfacing with the RGW endpoint.
This enables smooth and easy access to Object Storage.
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggest: s/Object Storage/object storage/

| 2 | testUser |
+---+-------------+

3. Get details of a an s3 user (optionally use --json flag to get complete details):
Copy link
Collaborator

Choose a reason for hiding this comment

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

Typo, s/a an/an/

"github.com/canonical/microcluster/state"
)

// /1.0/resources endpoint.
Copy link
Collaborator

Choose a reason for hiding this comment

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

Copy/paste error :-)

}
}

func cmdClientS3Put(s *state.State, r *http.Request) response.Response {
Copy link
Collaborator

Choose a reason for hiding this comment

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

For maximum RESTfulness we should be using a POST to the /client/s3 url to create a user

Delete: rest.EndpointAction{Handler: cmdClientS3Delete, ProxyTarget: true},
}

func cmdClientS3Get(s *state.State, r *http.Request) response.Response {
Copy link
Collaborator

Choose a reason for hiding this comment

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

RESTfulness:

  • retrieving a list of users should be a GET to /client/s3
  • retrieving a single user should be a GET to /client/s3/{userid}

See the /disks/{osdid} handler in microceph/api/disks.go for an example on how to implement a handler for a path variable i.e. {userid}

return response.SyncResponse(true, output)
}

func cmdClientS3Delete(s *state.State, r *http.Request) response.Response {
Copy link
Collaborator

Choose a reason for hiding this comment

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

RESTfulness: this should be using a DELETE against /client/s3/{userid} (also cf. above for getting users)

@@ -0,0 +1 @@
package main
Copy link
Collaborator

Choose a reason for hiding this comment

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

I guess this is not actually used?

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