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

Authorization model #544

Closed
wants to merge 12 commits into from

Conversation

naamashoresh
Copy link
Contributor

A new PR instead of #435 with fixes according to comments by @mitchell852

Copy link
Member

@mitchell852 mitchell852 left a comment

Choose a reason for hiding this comment

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

Some more comments for you. thanks!


|

**GET /api/1.2/api_capabilities/capability/:name**
Copy link
Member

Choose a reason for hiding this comment

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

usually when filtering a result set, query params are used instead of route params. i.e. GET /api/1.2/api_capabilities?capName=ds-read

that way you don't have to create 2 routes and 2 documentation snippets, etc:

GET /api/1.2/api_capabilities
GET /api/1.2/api_capabilities/capability/:name

^^ no need for 2 routes. only this one is required:

GET /api/1.2/api_capabilities

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed, thanks

+-------------------+--------+--------------------------------------------------+
| Parameter | Type | Description |
+===================+========+==================================================+
| ``httpMethod`` | enum | One of: 'GET', 'POST', 'PUT', 'PATCH', 'DELETE'. |
Copy link
Member

Choose a reason for hiding this comment

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

if you want your documentation to be perfect :) you could add a column for "required" with yes | no

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

**Request Route Parameters**

+-------------------+----------+------------------------------------------------+
| Name | Type | Description |
Copy link
Member

Choose a reason for hiding this comment

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

I think you meant this column header to say "Required" and not type

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed, thanks

+-----------------+----------+------------------------------------------------+
| Name | Required | Description |
+=================+==========+================================================+
| ``id`` | yes | Mapping id. |
Copy link
Member

Choose a reason for hiding this comment

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

make sure you get these pipes in the right place or the docs won't build.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

**Request Parameters**

+-------------------+--------+-------------------------------------------------+
| Parameter | Type | Description |
Copy link
Member

Choose a reason for hiding this comment

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

can you add a required column here too?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

my $name = $self->param('name');

my $rs_data = $self->db->resultset("Capability")->search( 'me.name' => $name );
my @data = ();
Copy link
Member

Choose a reason for hiding this comment

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

you might want to do this

if ( !defined($rs_data) ) { return $self->not_found(); }

so they get back a 404 instead of an empty result set if id is invalid

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

my $description = $params->{description} if defined( $params->{description} );

my $capability = $self->db->resultset('Capability')->find( { name => $name } );
if ( !defined($capability) or $capability eq "" ) {
Copy link
Member

Choose a reason for hiding this comment

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

i'm not sure this is needed:

or $capability eq ""

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Right, done.

$r->put("/api/$version/api_capabilities/:id")->over( authenticated => 1 )->to( 'ApiCapability#update', namespace => $namespace );
$r->post("/api/$version/api_capabilities")->over( authenticated => 1 )->to( 'ApiCapability#create', namespace => $namespace );
$r->delete("/api/$version/api_capabilities/:id")->over( authenticated => 1 )->to( 'ApiCapability#delete', namespace => $namespace );

Copy link
Member

Choose a reason for hiding this comment

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

do you plan to create apis for associating capabilities with roles?

my $dbh = Schema->database_handle;
my $t = Test::Mojo->new('TrafficOps');

my $false = 0;
Copy link
Member

Choose a reason for hiding this comment

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

I don't see where you are using these variables. plus, per our resident perl expert, @dangogh, this is not a good idea.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Removed, thanks.

my $dbh = Schema->database_handle;
my $t = Test::Mojo->new('TrafficOps');

my $false = 0;
Copy link
Member

Choose a reason for hiding this comment

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

again, i don't think you need these.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Right. Removed.

Copy link
Member

@mitchell852 mitchell852 left a comment

Choose a reason for hiding this comment

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

and a few more comments...

@@ -81,10 +81,260 @@ insert into role (name, description, priv_level) values ('steering', 'Role for S
insert into role (name, description, priv_level) values ('read-only user', 'Read-Only user', 10) ON CONFLICT (name) DO NOTHING;
insert into role (name, description, priv_level) values ('portal', 'Portal User', 2) ON CONFLICT (name) DO NOTHING;
insert into role (name, description, priv_level) values ('disallowed', 'Block all access', 0) ON CONFLICT (name) DO NOTHING;
insert into role (name, description, priv_level) values ('root', 'Role for full capabilities - super-user ', 30) ON CONFLICT DO NOTHING;
Copy link
Member

Choose a reason for hiding this comment

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

i still don't think this is needed as we already have the "admin" user which has always been the "super user".

insert into capability (name, description) values ('user-write', 'Create, edit or delete user configuration') ON CONFLICT (name) DO NOTHING;

-- roles_capabilities
insert into role_capability (role_id, cap_name) values ((select id from role where name='root'), 'all-read') ON CONFLICT (role_id, cap_name) DO NOTHING;
Copy link
Member

Choose a reason for hiding this comment

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

again, unless you really feel strongly about creating a 2nd "super user" called root (in addition to admin), i'd change this to

insert into role_capability (role_id, cap_name) values ((select id from role where name='admin'), 'all-read') ON CONFLICT (role_id, cap_name) DO NOTHING;
insert into role_capability (role_id, cap_name) values ((select id from role where name='admin'), 'all-write') ON CONFLICT (role_id, cap_name) DO NOTHING;

I think having 2 super users will only create unnecessary confusion.

insert into role_capability (role_id, cap_name) values ((select id from role where name='root'), 'all-write') ON CONFLICT (role_id, cap_name) DO NOTHING;

-- api_capabilities
insert into api_capability (http_method, route, capability) values ('GET', '/', 'all-read') ON CONFLICT (http_method, route, capability) DO NOTHING;
Copy link
Member

Choose a reason for hiding this comment

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

I feel like these should be /api as this authorization model is used by the api gateway and therefore only applicable to /api. However, I understand that there are a few that start with /internal but my understanding is that those that start with /internal should NOT be exposed thru the api.

insert into api_capability (http_method, route, capability) values ('PUT', '/api/*/asns/*', 'asn-write') ON CONFLICT (http_method, route, capability) DO NOTHING; -- 7
insert into api_capability (http_method, route, capability) values ('DELETE', '/api/*/asns/*', 'asn-write') ON CONFLICT (http_method, route, capability) DO NOTHING; -- 8
insert into api_capability (http_method, route, capability) values ('GET', '/api/*/cache_stats', 'cache-stats-read') ON CONFLICT (http_method, route, capability) DO NOTHING; -- 11
insert into api_capability (http_method, route, capability) values ('GET', '/internal/api/*/daily_summary', 'cache-stats-read') ON CONFLICT (http_method, route, capability) DO NOTHING; -- 12
Copy link
Member

Choose a reason for hiding this comment

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

I would take out the /internal ones

Copy link
Member

Choose a reason for hiding this comment

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

We should probably bring this up in an email to the dev list. I'm not 100% familiar with the behavior of the api gateway but I assumed because of its name it handles /api requests. For example, if a request came in to traffic-ops.domain.com/foo.jpg then foo.jpg would be served and the api gateway would not be concerned. however, if a call to traffic-ops.domain.com/api/whatever came in that request would go thru the api gateway where roles/capabilites would be checked for the route. Therefore, this would mean the /internal ones would not go thru the api gateway.

So, my advice would be to duplicate the "authenticated" /internal routes in TrafficOpsRoutes.pm and add those to your seeds file. for example, in trafficopsroutes.pm you'll find this:

$r->get("/internal/api/$version/steering")->over( authenticated => 1 )->to( 'Steering#index', namespace => 'API::DeliveryService' );

I would create a clone like this in trafficopsroutes.pm:

$r->get("/api/$version/steering")->over( authenticated => 1 )->to( 'Steering#index', namespace => 'API::DeliveryService' );

^^ and that is the one I'd add to your seeds file.

I think I created an email a little while ago to address /internal routes. I can see if I can get that email thread started again.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Since the first implementation of the API gateway reads the mapping from a file, and not from the DB table, I tend to either leave it as is, or remove everything from this table, for now, until the discussion yields some conclusions. What do you say?

Copy link
Member

Choose a reason for hiding this comment

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

ok, let's leave the /internal ones in as I have not been able to get any conclusions on the matter.

insert into api_capability (http_method, route, capability) values ('DELETE', '/api/*/types/*', 'type-write') ON CONFLICT (http_method, route, capability) DO NOTHING; -- 283
insert into api_capability (http_method, route, capability) values ('GET', '/api/*/users', 'user-read') ON CONFLICT (http_method, route, capability) DO NOTHING; -- 289
insert into api_capability (http_method, route, capability) values ('GET', '/api/*/users/*', 'user-read') ON CONFLICT (http_method, route, capability) DO NOTHING; -- 290
insert into api_capability (http_method, route, capability) values ('PUT', '/api/*/users/*', 'user-write') ON CONFLICT (http_method, route, capability) DO NOTHING; -- 292
Copy link
Member

Choose a reason for hiding this comment

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

you might want to do a quick check against the TrafficOpsRoutes.pm file to make sure you got everything. I'm sure some new routes have been added since the PR was first submitted.

Also, what about the new routes you created in this PR. are they in this seeds file?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Same here. Will give it another look once we decide about the way this data is used by the API gateway.

@mitchell852
Copy link
Member

I'm ready to merge this PR however it says "This branch cannot be rebased safely". To be honest I'm not really sure what that means but it doesn't sound great. So here's what I'd suggest:

  1. update your master branch
  2. git checkout authorization_model
  3. git rebase master

if all goes smoothly:

  1. git push origin authorization_model --force (which will update your PR)

if all doesn't go smoothly:

  1. resolve conflicts (this is the tricky part of course do a git status to see where the conflicts are)
  2. git rebase --continue (i think. it will tell you on the command line)
  3. git push origin authorization_model --force (which will update your PR)

of course if that doesn't work you can always do:

git rebase --abort

and we'll sync up and see what the issue is...

Adding tables: capability (list of available capabilities), api_capability mapping, role_capability mapping & user_role.
Seeding capability & api_capability tables. Also seeding root role.

(cherry picked from commit 4879a2c)
Added "capability" as a query parameter to the api_capabilities API as a filter, and removed the dedicated API
Updated the documentation and UT accordingly.
@naamashoresh
Copy link
Contributor Author

Branch rebased, PR updated. I believe it can be merged now.
Thanks

@asfgit asfgit closed this in 95c1f38 May 24, 2017
@mitchell852 mitchell852 self-assigned this Jan 19, 2018
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.

None yet

2 participants