@PUT @Timed @Path("/{sidecarId}") @RequiresPermissions(SidecarRestPermissions.SIDECARS_UPDATE) @ApiOperation(value = "Set a collector action") @ApiResponses(value = {@ApiResponse(code = 400, message = "The supplied action is not valid.")}) @AuditEvent(type = SidecarAuditEventTypes.ACTION_UPDATE) public Response setAction(@ApiParam(name = "sidecarId", value = "The id this Sidecar is registering as.", required = true) @PathParam("sidecarId") @NotEmpty String sidecarId, @ApiParam(name = "JSON body", required = true) @Valid @NotNull List<CollectorAction> request) { final CollectorActions collectorActions = actionService.fromRequest(sidecarId, request); actionService.saveAction(collectorActions); return Response.accepted().build(); } }
@POST @Timed @ApiOperation(value = "Shutdown this node gracefully.", notes = "Attempts to process all buffered and cached messages before exiting, " + "shuts down inputs first to make sure that no new messages are accepted.") @Path("/shutdown") @AuditEvent(type = AuditEventTypes.NODE_SHUTDOWN_INITIATE) public Response shutdown() { checkPermission(RestPermissions.NODE_SHUTDOWN, serverStatus.getNodeId().toString()); new Thread(gracefulShutdown).start(); return accepted().build(); } }
@POST @Path("/{id}/{name}") @RequiresPermissions({SidecarRestPermissions.CONFIGURATIONS_READ, SidecarRestPermissions.CONFIGURATIONS_CREATE}) @ApiOperation(value = "Copy a configuration") @AuditEvent(type = SidecarAuditEventTypes.CONFIGURATION_CLONE) public Response copyConfiguration(@ApiParam(name = "id", required = true) @PathParam("id") String id, @PathParam("name") String name) throws NotFoundException { final Configuration configuration = configurationService.copyConfiguration(id, name); final ValidationResult validationResult = validate(configuration); if (validationResult.failed()) { return Response.status(Response.Status.BAD_REQUEST).entity(validationResult).build(); } configurationService.save(configuration); return Response.accepted().build(); }
@POST @Timed @Path("/rebuild") @RequiresPermissions(RestPermissions.INDEXRANGES_REBUILD) @ApiOperation(value = "Rebuild/sync index range information.", notes = "This triggers a systemjob that scans every index and stores meta information " + "about what indices contain messages in what timeranges. It atomically overwrites " + "already existing meta information.") @ApiResponses(value = { @ApiResponse(code = 202, message = "Rebuild/sync systemjob triggered.") }) @Produces(MediaType.APPLICATION_JSON) @AuditEvent(type = AuditEventTypes.ES_INDEX_RANGE_UPDATE_JOB) public Response rebuild() { submitIndexRangesJob(indexSetRegistry.getAll()); return Response.accepted().build(); }
@POST @Path("/{id}/{name}") @RequiresPermissions({SidecarRestPermissions.COLLECTORS_READ, SidecarRestPermissions.COLLECTORS_CREATE}) @ApiOperation(value = "Copy a collector") @AuditEvent(type = SidecarAuditEventTypes.COLLECTOR_CLONE) public Response copyCollector(@ApiParam(name = "id", required = true) @PathParam("id") String id, @ApiParam(name = "name", required = true) @PathParam("name") String name) throws NotFoundException, BadRequestException { final Collector collector = collectorService.copy(id, name); final ValidationResult validationResult = validate(collector); if (validationResult.failed()) { return Response.status(Response.Status.BAD_REQUEST).entity(validationResult).build(); } etagService.invalidateAll(); collectorService.save(collector); return Response.accepted().build(); }
@POST @Timed @Path("/index_set/{indexSetId}/rebuild") @RequiresPermissions(RestPermissions.INDEXRANGES_REBUILD) @ApiOperation(value = "Rebuild/sync index range information for the given index set.", notes = "This triggers a systemjob that scans every index in the given index set and stores meta information " + "about what indices contain messages in what timeranges. It atomically overwrites " + "already existing meta information.") @ApiResponses(value = { @ApiResponse(code = 202, message = "Rebuild/sync systemjob triggered.") }) @Produces(MediaType.APPLICATION_JSON) @AuditEvent(type = AuditEventTypes.ES_INDEX_RANGE_UPDATE_JOB) public Response rebuildIndexSet(@ApiParam(name = "indexSetId") @PathParam("indexSetId") @NotBlank final String indexSetId) { final IndexSet indexSet = indexSetRegistry.get(indexSetId) .orElseThrow(() -> new javax.ws.rs.NotFoundException("Index set <" + indexSetId + "> not found!")); submitIndexRangesJob(Collections.singleton(indexSet)); return Response.accepted().build(); }
return Response.ok().build(); case ACCEPTED: return Response.accepted().build(); case NO_CONTENT: return Response.noContent().build();
@DELETE @Path("/{id}") @RequiresPermissions(SidecarRestPermissions.COLLECTORS_DELETE) @Produces(MediaType.APPLICATION_JSON) @ApiOperation(value = "Delete a collector") @AuditEvent(type = SidecarAuditEventTypes.COLLECTOR_DELETE) public Response deleteCollector(@ApiParam(name = "id", required = true) @PathParam("id") String id) { final long configurationsForCollector = configurationService.all().stream() .filter(configuration -> configuration.collectorId().equals(id)) .count(); if (configurationsForCollector > 0) { throw new BadRequestException("Collector still in use, cannot delete."); } int deleted = collectorService.delete(id); if (deleted == 0) { return Response.notModified().build(); } etagService.invalidateAll(); return Response.accepted().build(); }
@DELETE @Path("/{id}") @RequiresPermissions(SidecarRestPermissions.CONFIGURATIONS_DELETE) @Produces(MediaType.APPLICATION_JSON) @ApiOperation(value = "Delete a configuration") @AuditEvent(type = SidecarAuditEventTypes.CONFIGURATION_DELETE) public Response deleteConfiguration(@ApiParam(name = "id", required = true) @PathParam("id") String id) { if (isConfigurationInUse(id)) { throw new BadRequestException("Configuration still in use, cannot delete."); } int deleted = configurationService.delete(id); if (deleted == 0) { return Response.notModified().build(); } etagService.invalidateAll(); return Response.accepted().build(); }
@PUT @Timed @Path("/action") @RequiresPermissions(SidecarRestPermissions.SIDECARS_UPDATE) @ApiOperation(value = "Set collector actions in bulk") @ApiResponses(value = {@ApiResponse(code = 400, message = "The supplied action is not valid.")}) @AuditEvent(type = SidecarAuditEventTypes.ACTION_UPDATE) public Response setAction(@ApiParam(name = "JSON body", required = true) @Valid @NotNull BulkActionsRequest request) { for (BulkActionRequest bulkActionRequest : request.collectors()) { final List<CollectorAction> actions = bulkActionRequest.collectorIds().stream() .map(collectorId -> CollectorAction.create(collectorId, request.action())) .collect(Collectors.toList()); final CollectorActions collectorActions = actionService.fromRequest(bulkActionRequest.sidecarId(), actions); actionService.saveAction(collectorActions); } return Response.accepted().build(); }
@DELETE @Path("/{id}") @RequiresPermissions(SidecarRestPermissions.CONFIGURATIONS_UPDATE) @Produces(MediaType.APPLICATION_JSON) @ApiOperation(value = "Delete a configuration variable") @AuditEvent(type = SidecarAuditEventTypes.CONFIGURATION_VARIABLE_DELETE) public Response deleteConfigurationVariable(@ApiParam(name = "id", required = true) @PathParam("id") String id) { final ConfigurationVariable configurationVariable = findVariableOrFail(id); final List<Configuration> configurations = this.configurationService.findByConfigurationVariable(configurationVariable); if (!configurations.isEmpty()) { final ValidationResult validationResult = new ValidationResult(); validationResult.addError("name", "Variable is still used in the following configurations: " + configurations.stream().map(c -> c.name()).collect(Collectors.joining(", "))); return Response.status(Response.Status.BAD_REQUEST).entity(validationResult).build(); } int deleted = configurationVariableService.delete(id); if (deleted == 0) { return Response.notModified().build(); } etagService.invalidateAll(); return Response.accepted().build(); }
@POST @Consumes(MediaType.TEXT_PLAIN) @Timed @ApiOperation("Add a list of new patterns") @AuditEvent(type = AuditEventTypes.GROK_PATTERN_IMPORT_CREATE) public Response bulkUpdatePatternsFromTextFile(@ApiParam(name = "patterns", required = true) @NotNull InputStream patternsFile, @ApiParam(name = "replace", value = "Replace all patterns with the new ones.") @QueryParam("replace") @DefaultValue("false") boolean replace) throws ValidationException, IOException { checkPermission(RestPermissions.INPUTS_CREATE); final List<GrokPattern> grokPatterns = readGrokPatterns(patternsFile); if (!grokPatterns.isEmpty()) { try { if (!grokPatternService.validateAll(grokPatterns)) { throw new ValidationException("Invalid pattern contained. Did not save any patterns."); } } catch (GrokException | IllegalArgumentException e) { throw new ValidationException("Invalid pattern. Did not save any patterns\n" + e.getMessage()); } grokPatternService.saveAll(grokPatterns, replace); } return Response.accepted().build(); }
@PUT @Timed @Path("/configurations") @ApiOperation(value = "Assign configurations to sidecars") @RequiresPermissions(SidecarRestPermissions.SIDECARS_UPDATE) @AuditEvent(type = SidecarAuditEventTypes.SIDECAR_UPDATE) public Response assignConfiguration(@ApiParam(name = "JSON body", required = true) @Valid @NotNull NodeConfigurationRequest request) throws NotFoundException { List<String> nodeIdList = request.nodes().stream() .filter(distinctByKey(NodeConfiguration::nodeId)) .map(NodeConfiguration::nodeId) .collect(Collectors.toList()); for (String nodeId : nodeIdList) { List<ConfigurationAssignment> nodeRelations = request.nodes().stream() .filter(a -> a.nodeId().equals(nodeId)) .flatMap(a -> a.assignments().stream()) .collect(Collectors.toList()); try { Sidecar sidecar = sidecarService.assignConfiguration(nodeId, nodeRelations); sidecarService.save(sidecar); } catch (org.graylog2.database.NotFoundException e) { throw new NotFoundException(e.getMessage()); } } return Response.accepted().build(); }
@PUT @Timed @ApiOperation("Add a list of new patterns") @AuditEvent(type = AuditEventTypes.GROK_PATTERN_IMPORT_CREATE) public Response bulkUpdatePatterns(@ApiParam(name = "patterns", required = true) @NotNull GrokPatternList patternList, @ApiParam(name = "replace", value = "Replace all patterns with the new ones.") @QueryParam("replace") @DefaultValue("false") boolean replace) throws ValidationException { checkPermission(RestPermissions.INPUTS_CREATE); try { if (!grokPatternService.validateAll(patternList.patterns())) { throw new ValidationException("Invalid pattern contained. Did not save any patterns."); } } catch (GrokException | IllegalArgumentException e) { throw new ValidationException("Invalid pattern. Did not save any patterns\n" + e.getMessage()); } grokPatternService.saveAll(patternList.patterns(), replace); return Response.accepted().build(); }
@POST @Timed @ApiOperation(value = "Trigger new job") @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) @ApiResponses(value = { @ApiResponse(code = 202, message = "Job accepted."), @ApiResponse(code = 400, message = "There is no such systemjob type."), @ApiResponse(code = 403, message = "Maximum concurrency level of this systemjob type reached.") }) @AuditEvent(type = AuditEventTypes.SYSTEM_JOB_START) public Response trigger(@ApiParam(name = "JSON body", required = true) @Valid @NotNull TriggerRequest tr) { // TODO cleanup jobId vs jobName checking in permissions checkPermission(RestPermissions.SYSTEMJOBS_CREATE, tr.jobName()); SystemJob job; try { job = systemJobFactory.build(tr.jobName()); } catch (NoSuchJobException e) { LOG.error("Such a system job type does not exist. Returning HTTP 400."); throw new BadRequestException(e); } try { systemJobManager.submit(job); } catch (SystemJobConcurrencyException e) { LOG.error("Maximum concurrency level of this job reached. ", e); throw new ForbiddenException("Maximum concurrency level of this job reached", e); } return Response.accepted().entity(ImmutableMap.of("system_job_id", job.getId())).build(); }
@POST @Timed @ApiOperation(value = "Associate outputs with a stream") @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) @ApiResponses(value = { @ApiResponse(code = 400, message = "Invalid output specification in input.") }) @AuditEvent(type = AuditEventTypes.STREAM_OUTPUT_ASSIGNMENT_CREATE) public Response add(@ApiParam(name = "streamid", value = "The id of the stream whose outputs we want.", required = true) @PathParam("streamid") String streamid, @ApiParam(name = "JSON body", required = true) @Valid @NotNull AddOutputRequest aor) throws NotFoundException { checkPermission(RestPermissions.STREAMS_EDIT, streamid); checkPermission(RestPermissions.STREAM_OUTPUTS_CREATE); // Check if stream exists streamService.load(streamid); final Set<String> outputs = aor.outputs(); final ImmutableSet.Builder<ObjectId> outputIds = ImmutableSet.builderWithExpectedSize(outputs.size()); for (String outputId : outputs) { // Check if output exists outputService.load(outputId); outputIds.add(new ObjectId(outputId)); } streamService.addOutputs(new ObjectId(streamid), outputIds.build()); return Response.accepted().build(); }
return Response.accepted(o).build();
@POST @Timed @Path("/{index: [a-z_0-9-]+}/rebuild") @ApiOperation(value = "Rebuild/sync index range information.", notes = "This triggers a system job that scans an index and stores meta information " + "about what indices contain messages in what time ranges. It atomically overwrites " + "already existing meta information.") @ApiResponses(value = { @ApiResponse(code = 202, message = "Rebuild/sync system job triggered.") }) @Produces(MediaType.APPLICATION_JSON) @AuditEvent(type = AuditEventTypes.ES_INDEX_RANGE_UPDATE_JOB) public Response rebuildIndex( @ApiParam(name = "index", value = "The name of the Graylog-managed Elasticsearch index", required = true) @PathParam("index") @NotEmpty String index) { if (!indexSetRegistry.isManagedIndex(index)) { throw new BadRequestException(index + " is not a Graylog-managed Elasticsearch index."); } checkPermission(RestPermissions.INDEXRANGES_REBUILD, index); final SystemJob rebuildJob = singleIndexRangeJobFactory.create(indexSetRegistry.getAll(), index); try { this.systemJobManager.submit(rebuildJob); } catch (SystemJobConcurrencyException e) { final String msg = "Concurrency level of this job reached: " + e.getMessage(); LOG.error(msg); throw new ForbiddenException(msg, e); } return Response.accepted().build(); }
collectorAction, assignments); return Response.accepted(sidecarRegistrationResponse).build();
@POST @Path("send") public Response send(Command entity) throws Exception { Context.getPermissionsManager().checkReadonly(getUserId()); long deviceId = entity.getDeviceId(); long id = entity.getId(); Context.getPermissionsManager().checkDevice(getUserId(), deviceId); if (id != 0) { Context.getPermissionsManager().checkPermission(Command.class, getUserId(), id); Context.getPermissionsManager().checkUserDeviceCommand(getUserId(), deviceId, id); } else { Context.getPermissionsManager().checkLimitCommands(getUserId()); } if (!Context.getCommandsManager().sendCommand(entity)) { return Response.accepted(entity).build(); } return Response.ok(entity).build(); }