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

RHCLOUD-37536 | refactor: kessel auth handlers #3294

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

import com.redhat.cloud.notifications.Constants;
import com.redhat.cloud.notifications.auth.ConsoleIdentityProvider;
import com.redhat.cloud.notifications.auth.annotation.Authorization;
import com.redhat.cloud.notifications.auth.annotation.IntegrationId;
import com.redhat.cloud.notifications.auth.kessel.permission.IntegrationPermission;
import com.redhat.cloud.notifications.db.Query;
import com.redhat.cloud.notifications.models.NotificationHistory;
Expand All @@ -12,9 +14,9 @@
import com.redhat.cloud.notifications.routers.models.Page;
import com.redhat.cloud.notifications.routers.models.PageLinksBuilder;
import io.quarkus.logging.Log;
import jakarta.annotation.security.RolesAllowed;
import jakarta.validation.Valid;
import jakarta.ws.rs.BeanParam;
import jakarta.ws.rs.ForbiddenException;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.NotFoundException;
import jakarta.ws.rs.Path;
Expand Down Expand Up @@ -68,33 +70,19 @@ public class EndpointResourceV2 extends EndpointResource {
)
}
)
@Authorization(legacyRBACRole = ConsoleIdentityProvider.RBAC_READ_INTEGRATIONS_ENDPOINTS, integrationPermissions = {IntegrationPermission.VIEW_HISTORY})
public Page<NotificationHistoryDTO> getEndpointHistory(
@Context SecurityContext sec,
@Context UriInfo uriInfo,
@PathParam("id") UUID id,
@IntegrationId @PathParam("id") UUID id,
@QueryParam("includeDetail") Boolean includeDetail,
@BeanParam Query query
@Valid @BeanParam Query query
) {
if (this.backendConfig.isKesselRelationsEnabled(getOrgId(sec))) {
this.kesselAuthorization.hasPermissionOnIntegration(sec, IntegrationPermission.VIEW_HISTORY, id);

return this.internalGetEndpointHistory(sec, uriInfo, id, includeDetail, query);
} else {
return this.legacyRBACGetEndpointHistory(sec, uriInfo, id, includeDetail, query);
}
}

@RolesAllowed(ConsoleIdentityProvider.RBAC_READ_INTEGRATIONS_ENDPOINTS)
protected Page<NotificationHistoryDTO> legacyRBACGetEndpointHistory(final SecurityContext securityContext, final UriInfo uriInfo, final UUID id, final Boolean includeDetail, final Query query) {
return this.internalGetEndpointHistory(securityContext, uriInfo, id, includeDetail, query);
}

protected Page<NotificationHistoryDTO> internalGetEndpointHistory(final SecurityContext securityContext, final UriInfo uriInfo, final UUID id, final Boolean includeDetail, @Valid final Query query) {
if (!this.endpointRepository.existsByUuidAndOrgId(id, getOrgId(securityContext))) {
if (!this.endpointRepository.existsByUuidAndOrgId(id, getOrgId(sec))) {
throw new NotFoundException("Endpoint not found");
}

String orgId = getOrgId(securityContext);
String orgId = getOrgId(sec);
boolean doDetail = includeDetail != null && includeDetail;

final List<NotificationHistory> notificationHistory = this.notificationRepository.getNotificationHistory(orgId, id, doDetail, query);
Expand All @@ -111,14 +99,9 @@ protected Page<NotificationHistoryDTO> internalGetEndpointHistory(final Security
@Path("/{id}")
@Produces(APPLICATION_JSON)
@Operation(summary = "Retrieve an endpoint", description = "Retrieves the public information associated with an endpoint such as its description, name, and properties.")
public EndpointDTO getEndpoint(@Context SecurityContext sec, @PathParam("id") UUID id) {
if (this.backendConfig.isKesselRelationsEnabled(getOrgId(sec))) {
this.kesselAuthorization.hasPermissionOnIntegration(sec, IntegrationPermission.VIEW, id);

return this.internalGetEndpoint(sec, id, true);
} else {
return legacyGetEndpoint(sec, id, true);
}
@Authorization(legacyRBACRole = ConsoleIdentityProvider.RBAC_READ_INTEGRATIONS_ENDPOINTS, integrationPermissions = {IntegrationPermission.VIEW})
public EndpointDTO getEndpoint(@Context SecurityContext sec, @IntegrationId @PathParam("id") UUID id) {
return internalGetEndpoint(sec, id, true);
}

@GET
Expand Down Expand Up @@ -147,18 +130,23 @@ public EndpointPage getEndpoints(
@QueryParam("active") Boolean activeOnly,
@QueryParam("name") String name
) {
Set<UUID> authorizedIds = null;
if (this.backendConfig.isKesselRelationsEnabled(getOrgId(sec))) {
// Fetch the set of integration IDs the user is authorized to view.
final Set<UUID> authorizedIds = this.kesselAuthorization.lookupAuthorizedIntegrations(sec, IntegrationPermission.VIEW);
authorizedIds = this.kesselAuthorization.lookupAuthorizedIntegrations(sec, IntegrationPermission.VIEW);
if (authorizedIds.isEmpty()) {
Log.infof("[org_id: %s][username: %s] Kessel did not return any integration IDs for the request", getOrgId(sec), getUsername(sec));

return new EndpointPage(new ArrayList<>(), new HashMap<>(), new Meta(0L));
}

return internalGetEndpoints(sec, query, targetType, activeOnly, name, authorizedIds, true);
} else {
// Legacy RBAC permission checking. The permission will have been
// prefetched and processed by the "ConsoleIdentityProvider".
if (!sec.isUserInRole(ConsoleIdentityProvider.RBAC_READ_INTEGRATIONS_ENDPOINTS)) {
throw new ForbiddenException();
}
}

return getEndpointsLegacyRBACRoles(sec, query, targetType, activeOnly, name, true);
return internalGetEndpoints(sec, query, targetType, activeOnly, name, authorizedIds, true);
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.redhat.cloud.notifications.routers.handlers.event;

import com.redhat.cloud.notifications.auth.ConsoleIdentityProvider;
import com.redhat.cloud.notifications.auth.annotation.Authorization;
import com.redhat.cloud.notifications.auth.kessel.KesselAuthorization;
import com.redhat.cloud.notifications.auth.kessel.permission.WorkspacePermission;
import com.redhat.cloud.notifications.auth.rbac.workspace.WorkspaceUtils;
Expand All @@ -17,7 +19,6 @@
import com.redhat.cloud.notifications.routers.models.Page;
import com.redhat.cloud.notifications.routers.models.PageLinksBuilder;
import io.quarkus.logging.Log;
import jakarta.annotation.security.RolesAllowed;
import jakarta.inject.Inject;
import jakarta.validation.Valid;
import jakarta.ws.rs.BadRequestException;
Expand All @@ -43,7 +44,6 @@
import java.util.stream.Collectors;

import static com.redhat.cloud.notifications.Constants.API_NOTIFICATIONS_V_1_0;
import static com.redhat.cloud.notifications.auth.ConsoleIdentityProvider.RBAC_READ_NOTIFICATIONS_EVENTS;
import static com.redhat.cloud.notifications.routers.SecurityContextUtil.getOrgId;
import static jakarta.ws.rs.core.MediaType.APPLICATION_JSON;

Expand All @@ -65,31 +65,14 @@ public class EventResource {
@Produces(APPLICATION_JSON)
@Operation(summary = "Retrieve the event log entries", description = "Retrieves the event log entries. Use this endpoint to review a full history of the events related to the tenant. You can sort by the bundle, application, event, and created fields. You can specify the sort order by appending :asc or :desc to the field, for example bundle:desc. Sorting defaults to desc for the created field and to asc for all other fields."
)
@Authorization(legacyRBACRole = ConsoleIdentityProvider.RBAC_READ_NOTIFICATIONS_EVENTS, workspacePermissions = {WorkspacePermission.EVENT_LOG_VIEW})
public Page<EventLogEntry> getEvents(@Context SecurityContext securityContext, @Context UriInfo uriInfo,
@RestQuery Set<UUID> bundleIds, @RestQuery Set<UUID> appIds,
@RestQuery String eventTypeDisplayName, @RestQuery LocalDate startDate, @RestQuery LocalDate endDate,
@RestQuery Set<String> endpointTypes, @RestQuery Set<Boolean> invocationResults,
@RestQuery Set<EventLogEntryActionStatus> status,
@BeanParam @Valid Query query,
@RestQuery boolean includeDetails, @RestQuery boolean includePayload, @RestQuery boolean includeActions) {
if (this.backendConfig.isKesselRelationsEnabled(getOrgId(securityContext))) {
final UUID workspaceId = this.workspaceUtils.getDefaultWorkspaceId(getOrgId(securityContext));

this.kesselAuthorization.hasPermissionOnWorkspace(securityContext, WorkspacePermission.EVENT_LOG_VIEW, workspaceId);

return this.getInternalEvents(securityContext, uriInfo, bundleIds, appIds, eventTypeDisplayName, startDate, endDate, endpointTypes, invocationResults, status, query, includeDetails, includePayload, includeActions);
} else {
return this.getEventsLegacyRBACRoles(securityContext, uriInfo, bundleIds, appIds, eventTypeDisplayName, startDate, endDate, endpointTypes, invocationResults, status, query, includeDetails, includePayload, includeActions);
}

}

@RolesAllowed(RBAC_READ_NOTIFICATIONS_EVENTS)
public Page<EventLogEntry> getEventsLegacyRBACRoles(final SecurityContext securityContext, final UriInfo uriInfo, final Set<UUID> bundleIds, final Set<UUID> appIds, final String eventTypeDisplayName, final LocalDate startDate, final LocalDate endDate, final Set<String> endpointTypes, final Set<Boolean> invocationResults, final Set<EventLogEntryActionStatus> status, final Query query, final boolean includeDetails, final boolean includePayload, final boolean includeActions) {
return this.getInternalEvents(securityContext, uriInfo, bundleIds, appIds, eventTypeDisplayName, startDate, endDate, endpointTypes, invocationResults, status, query, includeDetails, includePayload, includeActions);
}

public Page<EventLogEntry> getInternalEvents(final SecurityContext securityContext, final UriInfo uriInfo, final Set<UUID> bundleIds, final Set<UUID> appIds, final String eventTypeDisplayName, final LocalDate startDate, final LocalDate endDate, final Set<String> endpointTypes, final Set<Boolean> invocationResults, final Set<EventLogEntryActionStatus> status, final Query query, final boolean includeDetails, final boolean includePayload, final boolean includeActions) {
Set<EndpointType> basicTypes = Collections.emptySet();
Set<CompositeEndpointType> compositeTypes = Collections.emptySet();
Set<NotificationStatus> notificationStatusSet = status == null ? Set.of() : toNotificationStatus(status);
Expand Down
Loading
Loading