TenantUtils - tenant resource tenancy test
Project: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/commit/2eb94bff Tree: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/tree/2eb94bff Diff: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/diff/2eb94bff Branch: refs/heads/master Commit: 2eb94bff31f038d4755c42491b447e3766a8e840 Parents: 731ceb1 Author: nir-sopher <[email protected]> Authored: Thu Jun 1 16:46:30 2017 +0300 Committer: Jeremy Mitchell <[email protected]> Committed: Tue Jul 18 12:12:31 2017 -0600 ---------------------------------------------------------------------- traffic_ops/app/lib/API/Tenant.pm | 69 +++++++++++++++++++------- traffic_ops/app/lib/UI/TenantUtils.pm | 79 ++++++++++++++++++++++++++++++ 2 files changed, 130 insertions(+), 18 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/2eb94bff/traffic_ops/app/lib/API/Tenant.pm ---------------------------------------------------------------------- diff --git a/traffic_ops/app/lib/API/Tenant.pm b/traffic_ops/app/lib/API/Tenant.pm index 265aad5..ca67365 100644 --- a/traffic_ops/app/lib/API/Tenant.pm +++ b/traffic_ops/app/lib/API/Tenant.pm @@ -45,15 +45,17 @@ sub index { my $tenantUtils = UI::TenantUtils->new($self); my @tenants_list = $tenantUtils->get_hierarchic_tenants_list(); foreach my $row (@tenants_list) { - push( - @data, { - "id" => $row->id, - "name" => $row->name, - "active" => \$row->active, - "parentId" => $row->parent_id, - "parentName" => ( defined $row->parent_id ) ? $idnames{ $row->parent_id } : undef, - } - ); + if ($tenantUtils->is_tenant_resource_readable($row->id)) { + push( + @data, { + "id" => $row->id, + "name" => $row->name, + "active" => \$row->active, + "parentId" => $row->parent_id, + "parentName" => ( defined $row->parent_id ) ? $idnames{ $row->parent_id } : undef, + } + ); + } } $self->success( \@data ); } @@ -71,17 +73,20 @@ sub show { $idnames{ $row->id } = $row->name; } + my $tenantUtils = UI::TenantUtils->new($self); my $rs_data = $self->db->resultset("Tenant")->search( { 'me.id' => $id }); while ( my $row = $rs_data->next ) { - push( - @data, { - "id" => $row->id, - "name" => $row->name, - "active" => \$row->active, - "parentId" => $row->parent_id, - "parentName" => ( defined $row->parent_id ) ? $idnames{ $row->parent_id } : undef, - } - ); + if ($tenantUtils->is_tenant_resource_readable($row->id)) { + push( + @data, { + "id" => $row->id, + "name" => $row->name, + "active" => \$row->active, + "parentId" => $row->parent_id, + "parentName" => ( defined $row->parent_id ) ? $idnames{ $row->parent_id } : undef, + } + ); + } } $self->success( \@data ); } @@ -134,6 +139,22 @@ sub update { return $self->alert("Root tenant cannot be in-active."); } + #this is a write operation, allowed only by parents of the tenant (which are the owners of the resource of type tenant) + my $current_resource_tenancy = $self->db->resultset('Tenant')->search( { id => $id } )->get_column('parent_id')->single(); + if (!defined($current_resource_tenancy)) { + #no parent - the tenant is its-own owner + $current_resource_tenancy = $id; + } + + if (!$tenantUtils->is_tenant_resource_writeable($current_resource_tenancy)) { + return $self->alert("Current owning tenant is not under user's tenancy."); + } + + if (!$tenantUtils->is_tenant_resource_writeable($params->{parentId})) { + return $self->alert("Parent tenant to be set is not under user's tenancy."); + } + + #operation my $values = { name => $params->{name}, @@ -186,6 +207,11 @@ sub create { if ( !defined($parent_id) ) { return $self->alert("Parent Id is required."); } + + my $tenantUtils = UI::TenantUtils->new($self); + if (!$tenantUtils->is_tenant_resource_writeable($params->{parentId})) { + return $self->alert("Parent tenant to be set is not under user's tenancy."); + } my $existing = $self->db->resultset('Tenant')->search( { name => $name } )->get_column('name')->single(); if ($existing) { @@ -246,6 +272,13 @@ sub delete { return $self->not_found(); } + my $parent_tenant = $tenant->parent_id; + + my $tenantUtils = UI::TenantUtils->new($self); + if (!$tenantUtils->is_tenant_resource_writeable($parent_tenant)) { + return $self->alert("Parent tenant is not under user's tenancy."); + } + my $name = $tenant->name; my $existing_child = $self->db->resultset('Tenant')->search( { parent_id => $id }, {order_by => 'me.name' } )->get_column('name')->first(); http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/2eb94bff/traffic_ops/app/lib/UI/TenantUtils.pm ---------------------------------------------------------------------- diff --git a/traffic_ops/app/lib/UI/TenantUtils.pm b/traffic_ops/app/lib/UI/TenantUtils.pm index 44a7f17..a7a33e4 100644 --- a/traffic_ops/app/lib/UI/TenantUtils.pm +++ b/traffic_ops/app/lib/UI/TenantUtils.pm @@ -80,6 +80,21 @@ sub is_root_tenant { return !defined($self->{context}->db->resultset('Tenant')->search( { id => $tenant_id } )->get_column('parent_id')->single()); } +sub is_tenant_resource_readable { + my $self = shift; + my $resource_tenancy = shift; + + return _is_resource_accessable ($self, $resource_tenancy, "r"); +} + +sub is_tenant_resource_writeable { + my $self = shift; + my $resource_tenancy = shift; + + return _is_resource_accessable ($self, $resource_tenancy, "w"); +} + + ############################################################## @@ -119,4 +134,68 @@ sub _init_tenants_if_needed { } } +sub _max_tenancy_heirarchy { + my $self = shift; + return 100; +} + +sub _is_resource_accessable { + my $self = shift; + my $resource_tenant = shift; + my $operation = shift; + + if (!defined($resource_tenant)) { + #the object has no tenancy - opened for all + return 1; + } + + if (&is_ldap($self->{context})) { + if ($operation eq "r") { + #ldap user, can read all tenants - temporary for now as an LDAP user as no tenant and is part of the TC operator. + # should be removed when LDAP is gone + return 1; + } + #ldap user, has no tenancy, cannot write anything + return 0; + } + + my $user_tenant = current_user_tenant($self); + if (!defined($user_tenant)) { + #the user has no tenancy, - cannot approach items with tenancy + return 0; + } + + $self->_init_tenants_if_needed(); + my $tenant_record = $self->{tenants_dict}->{$user_tenant}; + my $is_active_tenant = $tenant_record->{row}->active; + if (! $is_active_tenant) { + #user tenant is in-active - cannot do any operation + return 0; + } + + if ($user_tenant == $resource_tenant) { + #resource has same tenancy of the user, operations are allowed + return 1; + } + + #checking if the user tenant is an ancestor of the resource tenant + for (my $depth = 0; $depth < $self->_max_tenancy_heirarchy(); $depth++) { + + if (!defined($resource_tenant)){ + #reached top tenant, resource is not under the user tenancy + return 0; + } + + if ($user_tenant == $resource_tenant) { + #resource has child tenancy of the user, operations are allowed + return 1; + } + + $resource_tenant = $self->{tenants_dict}->{$resource_tenant}->{parent}; + }; + + #not found - recursion limit, give only access to root tenant + return $self->is_root_tenant(current_user_tenant($self)); +} + 1;
