Skip to content

Commit

Permalink
Allow space application supporter access to events endpoints
Browse files Browse the repository at this point in the history
* Refactored v3 Events permissions checks to be in the permissions
queryer because we believe that to be the desired pattern + easier to
follow.
* Updated documentation.

[#2216]

Co-authored-by: Carson Long <[email protected]>
Co-authored-by: Mona Mohebbi <[email protected]>
  • Loading branch information
ctlong and monamohebbi committed Jun 9, 2021
1 parent 9591e85 commit c68c3c9
Show file tree
Hide file tree
Showing 8 changed files with 100 additions and 13 deletions.
8 changes: 2 additions & 6 deletions app/controllers/v3/events_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ def index
message = EventsListMessage.from_params(query_params)
invalid_param!(message.errors.full_messages) unless message.valid?

dataset = EventListFetcher.fetch_all(message, readable_event_dataset)
dataset = EventListFetcher.fetch_all(message, permission_queryer.readable_event_dataset)

render status: :ok, json: Presenters::V3::PaginatedListPresenter.new(
presenter: Presenters::V3::EventPresenter,
Expand All @@ -18,7 +18,7 @@ def index
end

def show
event = readable_event_dataset.first(guid: hashed_params[:guid])
event = permission_queryer.readable_event_dataset.first(guid: hashed_params[:guid])
event_not_found! unless event

render status: :ok, json: Presenters::V3::EventPresenter.new(event)
Expand All @@ -29,8 +29,4 @@ def show
def event_not_found!
resource_not_found!(:event)
end

def readable_event_dataset
Event.user_visible(current_user, permission_queryer.can_read_globally?)
end
end
1 change: 1 addition & 0 deletions docs/v3/source/includes/resources/audit_events/_get.md.erb
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ Role | Notes
Admin |
Admin Read-Only |
Global Auditor |
Space Application Supporter | Experimental; Cannot see events which occurred in spaces that the user does not belong to
Space Auditor | Cannot see events which occurred in spaces that the user does not belong to
Space Developer | Cannot see events which occurred in spaces that the user does not belong to
Org Auditor | Cannot see events which occurred in orgs that the user does not belong to
3 changes: 2 additions & 1 deletion docs/v3/source/includes/resources/audit_events/_list.md.erb
Original file line number Diff line number Diff line change
Expand Up @@ -41,13 +41,14 @@ Name | Type | Description
**updated_ats** (*experimental*)| _[timestamp](#timestamps)_ | Timestamp to filter by. When filtering on equality, several comma-delimited timestamps may be passed. Also supports filtering with [relational operators](#relational-operators-experimental)

#### Permitted roles
|
Role | Notes
--- | ---
Admin |
Admin Read-Only |
Global Auditor |
Org Auditor |
Org Manager |
Space Application Supporter | Experimental |
Space Auditor |
Space Developer |
Space Manager |
2 changes: 1 addition & 1 deletion docs/v3/source/includes/resources/users/_list.md.erb
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@ Name | Type | Description
#### Permitted roles
Roles | Notes
--- | ---
Admin Read-Only |
Admin |
Admin Read-Only |
Global Auditor |
Org Auditor | Can only view users affiliated with their org
Org Billing Manager | Can only view users affiliated with their org
Expand Down
19 changes: 18 additions & 1 deletion lib/cloud_controller/permissions.rb
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,12 @@ class VCAP::CloudController::Permissions
VCAP::CloudController::Membership::SPACE_APPLICATION_SUPPORTER,
]).freeze

SPACE_ROLES_FOR_EVENTS ||= [
VCAP::CloudController::Membership::SPACE_AUDITOR,
VCAP::CloudController::Membership::SPACE_DEVELOPER,
VCAP::CloudController::Membership::SPACE_APPLICATION_SUPPORTER
].freeze

ROLES_FOR_SPACE_SECRETS_READING ||= [
VCAP::CloudController::Membership::SPACE_DEVELOPER,
].freeze
Expand Down Expand Up @@ -249,10 +255,21 @@ def can_update_build_state?
can_write_globally? || roles.build_state_updater?
end

def readable_event_dataset
return VCAP::CloudController::Event.dataset if can_read_globally?

spaces_with_permitted_roles = membership.space_guids_for_roles(SPACE_ROLES_FOR_EVENTS)
orgs_with_permitted_roles = membership.org_guids_for_roles(VCAP::CloudController::Membership::ORG_AUDITOR)
VCAP::CloudController::Event.dataset.filter(Sequel.or([
[:space_guid, spaces_with_permitted_roles],
[:organization_guid, orgs_with_permitted_roles]
]))
end

private

def membership
VCAP::CloudController::Membership.new(@user)
@membership ||= VCAP::CloudController::Membership.new(@user)
end

def roles
Expand Down
11 changes: 11 additions & 0 deletions lib/cloud_controller/permissions/queryer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,17 @@ def readable_security_group_guids
end
end

def readable_event_dataset
science 'readable_security_group_guids' do |e|
e.use { db_permissions.readable_event_dataset }
e.try { perm_permissions.readable_event_dataset }

e.compare { |a, b| compare_arrays(a, b) }

e.run_if { !db_permissions.can_read_globally? }
end
end

def can_update_build_state?
db_permissions.can_update_build_state?
end
Expand Down
14 changes: 10 additions & 4 deletions spec/request/events_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -115,13 +115,14 @@

h['space_auditor'] = { code: 200, response_objects: [space_scoped_event_json] }
h['space_developer'] = { code: 200, response_objects: [space_scoped_event_json] }
h['space_application_supporter'] = { code: 200, response_objects: [space_scoped_event_json] }

h['org_auditor'] = { code: 200, response_objects: [org_scoped_event_json, space_scoped_event_json] }

h
end

it_behaves_like 'permissions for list endpoint', ALL_PERMISSIONS
it_behaves_like 'permissions for list endpoint', ALL_PERMISSIONS + ['space_application_supporter']
end

context 'filtering by type' do
Expand Down Expand Up @@ -271,11 +272,12 @@
org_auditor
space_auditor
space_developer
space_application_supporter
)
)
end

it_behaves_like 'permissions for single object endpoint', ALL_PERMISSIONS
it_behaves_like 'permissions for single object endpoint', ALL_PERMISSIONS + ['space_application_supporter']

context 'and the space has been deleted' do
before do
Expand Down Expand Up @@ -355,6 +357,10 @@
code: 404,
response_object: []
}
h['space_application_supporter'] = {
code: 404,
response_object: []
}
h['space_manager'] = {
code: 404,
response_object: []
Expand All @@ -374,7 +380,7 @@
h.freeze
end

it_behaves_like 'permissions for single object endpoint', ALL_PERMISSIONS
it_behaves_like 'permissions for single object endpoint', ALL_PERMISSIONS + ['space_application_supporter']

context 'and the org has been deleted' do
before do
Expand Down Expand Up @@ -452,7 +458,7 @@
h.freeze
end

it_behaves_like 'permissions for single object endpoint', ALL_PERMISSIONS
it_behaves_like 'permissions for single object endpoint', ALL_PERMISSIONS + ['space_application_supporter']
end
end

Expand Down
55 changes: 55 additions & 0 deletions spec/unit/lib/cloud_controller/permissions_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -864,6 +864,61 @@ module VCAP::CloudController
end
end

describe '#readable_event_dataset' do
let!(:unscoped_event) { VCAP::CloudController::Event.make(actee: 'dir/key', type: 'blob.remove_orphan', organization_guid: '') }
let!(:org_scoped_event) { VCAP::CloudController::Event.make(created_at: Time.now + 100, type: 'audit.organization.create', actee: org_guid, organization_guid: org_guid) }
let!(:space_scoped_event) { VCAP::CloudController::Event.make(space_guid: space_guid, actee: space_guid, type: 'audit.app.restart') }

it 'returns all events for admins' do
user = set_current_user_as_admin
event_guids = Permissions.new(user).readable_event_dataset.map(&:guid)

expect(event_guids).to contain_exactly(unscoped_event.guid, org_scoped_event.guid, space_scoped_event.guid)
end

it 'returns all events for read-only admins' do
user = set_current_user_as_admin_read_only
event_guids = Permissions.new(user).readable_event_dataset.map(&:guid)

expect(event_guids).to contain_exactly(unscoped_event.guid, org_scoped_event.guid, space_scoped_event.guid)
end

it 'returns all events for global auditors' do
user = set_current_user_as_global_auditor
event_guids = Permissions.new(user).readable_event_dataset.map(&:guid)

expect(event_guids).to contain_exactly(unscoped_event.guid, org_scoped_event.guid, space_scoped_event.guid)
end

it 'returns event datasets from space membership' do
membership = instance_double(Membership)
expect(Membership).to receive(:new).with(user).and_return(membership)
expect(membership).to receive(:space_guids_for_roles).
with(VCAP::CloudController::Permissions::SPACE_ROLES_FOR_EVENTS).
and_return([space_guid])
expect(membership).to receive(:org_guids_for_roles).
with(VCAP::CloudController::Membership::ORG_AUDITOR).
and_return([])
event_guids = Permissions.new(user).readable_event_dataset.map(&:guid)

expect(event_guids).to contain_exactly(space_scoped_event.guid)
end

it 'returns event datasets from org membership' do
membership = instance_double(Membership)
expect(Membership).to receive(:new).with(user).and_return(membership)
expect(membership).to receive(:space_guids_for_roles).
with(VCAP::CloudController::Permissions::SPACE_ROLES_FOR_EVENTS).
and_return([])
expect(membership).to receive(:org_guids_for_roles).
with(VCAP::CloudController::Membership::ORG_AUDITOR).
and_return(org_guid)
event_guids = Permissions.new(user).readable_event_dataset.map(&:guid)

expect(event_guids).to contain_exactly(org_scoped_event.guid)
end
end

describe '#can_read_from_isolation_segment?' do
let(:isolation_segment) { IsolationSegmentModel.make }
let(:assigner) { IsolationSegmentAssign.new }
Expand Down

0 comments on commit c68c3c9

Please sign in to comment.