Beispiel #1
0
export function initStatusApi(server: Server) {
  server.route({
    method: 'GET',
    path: `${ROOT}/server`,
    options: {
      validate: {
        query: Joi.object().keys({
          _debug: Joi.bool()
        })
      }
    },
    handler: req => {
      const setup = setupRequest(req);
      return getServerStatus({ setup }).catch(defaultErrorHandler);
    }
  });

  server.route({
    method: 'GET',
    path: `${ROOT}/agent`,
    options: {
      validate: {
        query: Joi.object().keys({
          _debug: Joi.bool()
        })
      }
    },
    handler: req => {
      const setup = setupRequest(req);
      return getAgentStatus({ setup }).catch(defaultErrorHandler);
    }
  });
}
Beispiel #2
0
export const createBeatUpdateRoute = (libs: CMServerLibs) => ({
  method: 'PUT',
  path: '/api/beats/agent/{beatId}',
  licenseRequired: true,
  config: {
    auth: {
      mode: 'optional',
    },
    validate: {
      headers: Joi.object({
        'kbn-beats-access-token': Joi.string(),
      }).options({
        allowUnknown: true,
      }),
      params: Joi.object({
        beatId: Joi.string(),
      }),
      payload: Joi.object({
        active: Joi.bool(),
        ephemeral_id: Joi.string(),
        host_name: Joi.string(),
        local_configuration_yml: Joi.string(),
        metadata: Joi.object(),
        name: Joi.string(),
        type: Joi.string(),
        version: Joi.string(),
      }),
    },
  },
  handler: async (request: FrameworkRequest, reply: any) => {
    const { beatId } = request.params;
    const accessToken = request.headers['kbn-beats-access-token'];
    const remoteAddress = request.info.remoteAddress;
    const userOrToken = accessToken || request.user;

    if (request.user.kind === 'unauthenticated' && request.payload.active !== undefined) {
      return reply({ message: 'access-token is not a valid auth type to change beat status' }).code(
        401
      );
    }

    try {
      const status = await libs.beats.update(userOrToken, beatId, {
        ...request.payload,
        host_ip: remoteAddress,
      });

      switch (status) {
        case 'beat-not-found':
          return reply({ message: 'Beat not found', success: false }).code(404);
        case 'invalid-access-token':
          return reply({ message: 'Invalid access token', success: false }).code(401);
      }

      reply({ success: true }).code(204);
    } catch (err) {
      return reply(wrapEsError(err));
    }
  },
});
Beispiel #3
0
export const createTagRemovalsRoute = (libs: CMServerLibs) => ({
  method: 'POST',
  path: '/api/beats/agents_tags/removals',
  licenseRequired: true,
  config: {
    validate: {
      payload: Joi.object({
        removals: Joi.array().items(
          Joi.object({
            beatId: Joi.string().required(),
            tag: Joi.string().required(),
          })
        ),
      }).required(),
    },
  },
  handler: async (request: FrameworkRequest, reply: any) => {
    const { removals } = request.payload;

    try {
      const response = await libs.beats.removeTagsFromBeats(request.user, removals);
      reply(response);
    } catch (err) {
      // TODO move this to kibana route thing in adapter
      return reply(wrapEsError(err));
    }
  },
});
Beispiel #4
0
export const createSetTagRoute = (libs: CMServerLibs) => ({
  method: 'PUT',
  path: '/api/beats/tag/{tagId}',
  licenseRequired: REQUIRED_LICENSES,
  requiredRoles: ['beats_admin'],
  config: {
    validate: {
      params: Joi.object({
        tagId: Joi.string(),
      }),
      payload: Joi.object({
        color: Joi.string(),
        name: Joi.string(),
      }),
    },
  },
  handler: async (request: FrameworkRequest) => {
    const defaultConfig = {
      id: request.params.tagId,
      name: request.params.tagId,
      color: '#DD0A73',
      hasConfigurationBlocksTypes: [],
    };
    const config = { ...defaultConfig, ...get(request, 'payload', {}) };

    try {
      const id = await libs.tags.upsertTag(request.user, config);

      return { success: true, id };
    } catch (err) {
      // TODO move this to kibana route thing in adapter
      return wrapEsError(err);
    }
  },
});
Beispiel #5
0
export const registerCapabilitiesRoute = (
  server: Server,
  defaultCapabilities: Capabilities,
  modifiers: CapabilitiesModifier[]
) => {
  server.route({
    path: '/api/capabilities',
    method: 'POST',
    options: {
      validate: {
        payload: Joi.object({
          capabilities: Joi.object().required(),
        }).required(),
      },
    },
    async handler(request) {
      const { capabilities } = request.payload as { capabilities: Capabilities };
      return {
        capabilities: await resolveCapabilities(
          request,
          modifiers,
          defaultCapabilities,
          capabilities
        ),
      };
    },
  });
};
Beispiel #6
0
export const createListTagsRoute = (libs: CMServerLibs) => ({
  method: 'GET',
  path: '/api/beats/tags',
  validate: {
    headers: Joi.object({
      'kbn-beats-enrollment-token': Joi.string().required(),
    }).options({
      allowUnknown: true,
    }),
    query: Joi.object({
      ESQuery: Joi.string(),
    }),
  },
  licenseRequired: true,
  handler: async (request: any, reply: any) => {
    let tags: BeatTag[];
    try {
      tags = await libs.tags.getAll(
        request.user
        // request.query ? JSON.parse(request.query.ESQuery) : undefined
      );
    } catch (err) {
      return reply(wrapEsError(err));
    }

    reply(tags);
  },
});
Beispiel #7
0
export const createSetTagRoute = (libs: CMServerLibs) => ({
  method: 'PUT',
  path: '/api/beats/tag/{tagId}',
  licenseRequired: REQUIRED_LICENSES,
  requiredRoles: ['beats_admin'],
  config: {
    validate: {
      params: Joi.object({
        tagId: Joi.string(),
      }),
      payload: Joi.object({
        color: Joi.string(),
        name: Joi.string(),
      }),
    },
  },
  handler: async (request: FrameworkRequest): Promise<ReturnTypeUpsert<BeatTag>> => {
    const defaultConfig = {
      id: request.params.tagId,
      name: request.params.tagId,
      color: '#DD0A73',
      hasConfigurationBlocksTypes: [],
    };
    const config = { ...defaultConfig, ...get(request, 'payload', {}) };

    const id = await libs.tags.upsertTag(request.user, config);
    const tag = await libs.tags.getWithIds(request.user, [id]);

    // TODO the action needs to be surfaced
    return { success: true, item: tag[0], action: 'created' };
  },
});
Beispiel #8
0
export const createListTagsRoute = (libs: CMServerLibs) => ({
  method: 'GET',
  path: '/api/beats/tags',
  requiredRoles: ['beats_admin'],
  licenseRequired: REQUIRED_LICENSES,
  validate: {
    headers: Joi.object({
      'kbn-beats-enrollment-token': Joi.string().required(),
    }).options({
      allowUnknown: true,
    }),
    query: Joi.object({
      ESQuery: Joi.string(),
    }),
  },
  handler: async (request: FrameworkRequest): Promise<ReturnTypeList<BeatTag>> => {
    let tags: BeatTag[];
    tags = await libs.tags.getAll(
      request.user,
      request.query && request.query.ESQuery ? JSON.parse(request.query.ESQuery) : undefined
    );

    return { list: tags, success: true, page: -1, total: -1 };
  },
});
export const createTagAssignmentsRoute = (libs: CMServerLibs) => ({
  method: 'POST',
  path: '/api/beats/agents_tags/assignments',
  licenseRequired: REQUIRED_LICENSES,
  requiredRoles: ['beats_admin'],
  config: {
    validate: {
      payload: Joi.object({
        assignments: Joi.array().items(
          Joi.object({
            beatId: Joi.string().required(),
            tag: Joi.string().required(),
          })
        ),
      }).required(),
    },
  },
  handler: async (request: FrameworkRequest) => {
    const { assignments }: { assignments: BeatsTagAssignment[] } = request.payload;

    try {
      const response = await libs.beats.assignTagsToBeats(request.user, assignments);
      return response;
    } catch (err) {
      // TODO move this to kibana route thing in adapter
      return wrapEsError(err);
    }
  },
});
Beispiel #10
0
export const createResolveImportErrorsRoute = (prereqs: Prerequisites, server: Hapi.Server) => ({
  path: '/api/saved_objects/_resolve_import_errors',
  method: 'POST',
  config: {
    pre: [prereqs.getSavedObjectsClient],
    payload: {
      maxBytes: server.config().get('savedObjects.maxImportPayloadBytes'),
      output: 'stream',
      allow: 'multipart/form-data',
    },
    validate: {
      payload: Joi.object({
        file: Joi.object().required(),
        overwrites: Joi.array()
          .items(
            Joi.object({
              type: Joi.string().required(),
              id: Joi.string().required(),
            })
          )
          .default([]),
        replaceReferences: Joi.array()
          .items(
            Joi.object({
              type: Joi.string().required(),
              from: Joi.string().required(),
              to: Joi.string().required(),
            })
          )
          .default([]),
        skips: Joi.array()
          .items(
            Joi.object({
              type: Joi.string().required(),
              id: Joi.string().required(),
            })
          )
          .default([]),
      }).default(),
    },
  },
  async handler(request: ImportRequest) {
    const { savedObjectsClient } = request.pre;
    const { filename } = request.payload.file.hapi;
    const fileExtension = extname(filename).toLowerCase();
    if (fileExtension !== '.ndjson') {
      return Boom.badRequest(`Invalid file extension ${fileExtension}`);
    }
    return await resolveImportErrors({
      savedObjectsClient,
      readStream: request.payload.file,
      objectLimit: request.server.config().get('savedObjects.maxImportExportSize'),
      skips: request.payload.skips,
      overwrites: request.payload.overwrites,
      replaceReferences: request.payload.replaceReferences,
    });
  },
});