diff --git a/src/plugins/kibana_usage_collection/server/collectors/cloud/detector/aws.test.ts b/src/plugins/kibana_usage_collection/server/collectors/cloud/detector/aws.test.ts index e959d60fd8929..0eb0983f21b40 100644 --- a/src/plugins/kibana_usage_collection/server/collectors/cloud/detector/aws.test.ts +++ b/src/plugins/kibana_usage_collection/server/collectors/cloud/detector/aws.test.ts @@ -13,13 +13,13 @@ import { AWS, AWSCloudService, AWSResponse } from './aws'; type Callback = (err: unknown, res: unknown) => void; describe('AWS', () => { - const expectedFilename = '/sys/hypervisor/uuid'; + const expectedFilenames = ['/sys/hypervisor/uuid', '/sys/devices/virtual/dmi/id/product_uuid']; const expectedEncoding = 'utf8'; // mixed case to ensure we check for ec2 after lowercasing const ec2Uuid = 'eC2abcdef-ghijk\n'; const ec2FileSystem = { readFile: (filename: string, encoding: string, callback: Callback) => { - expect(filename).toEqual(expectedFilename); + expect(expectedFilenames).toContain(filename); expect(encoding).toEqual(expectedEncoding); callback(null, ec2Uuid); @@ -177,29 +177,64 @@ describe('AWS', () => { }); describe('_tryToDetectUuid', () => { - it('checks the file system for UUID if not Windows', async () => { - const awsCheckedFileSystem = new AWSCloudService({ - _fs: ec2FileSystem, - _isWindows: false, + describe('checks the file system for UUID if not Windows', () => { + it('checks /sys/hypervisor/uuid', async () => { + const awsCheckedFileSystem = new AWSCloudService({ + _fs: { + readFile: (filename: string, encoding: string, callback: Callback) => { + expect(expectedFilenames).toContain(filename); + expect(encoding).toEqual(expectedEncoding); + + callback(null, ec2Uuid); + }, + } as typeof fs, + _isWindows: false, + }); + + const response = await awsCheckedFileSystem._tryToDetectUuid(); + + expect(response.isConfirmed()).toEqual(true); + expect(response.toJSON()).toEqual({ + name: AWS.getName(), + id: ec2Uuid.trim().toLowerCase(), + region: undefined, + zone: undefined, + vm_type: undefined, + metadata: undefined, + }); }); - const response = await awsCheckedFileSystem._tryToDetectUuid(); - - expect(response.isConfirmed()).toEqual(true); - expect(response.toJSON()).toEqual({ - name: AWS.getName(), - id: ec2Uuid.trim().toLowerCase(), - region: undefined, - zone: undefined, - vm_type: undefined, - metadata: undefined, + it('checks /sys/devices/virtual/dmi/id/product_uuid', async () => { + const awsCheckedFileSystem = new AWSCloudService({ + _fs: { + readFile: (filename: string, encoding: string, callback: Callback) => { + expect(expectedFilenames).toContain(filename); + expect(encoding).toEqual(expectedEncoding); + + callback(null, ec2Uuid); + }, + } as typeof fs, + _isWindows: false, + }); + + const response = await awsCheckedFileSystem._tryToDetectUuid(); + + expect(response.isConfirmed()).toEqual(true); + expect(response.toJSON()).toEqual({ + name: AWS.getName(), + id: ec2Uuid.trim().toLowerCase(), + region: undefined, + zone: undefined, + vm_type: undefined, + metadata: undefined, + }); }); }); it('ignores UUID if it does not start with ec2', async () => { const notEC2FileSystem = { readFile: (filename: string, encoding: string, callback: Callback) => { - expect(filename).toEqual(expectedFilename); + expect(expectedFilenames).toContain(filename); expect(encoding).toEqual(expectedEncoding); callback(null, 'notEC2'); @@ -240,7 +275,7 @@ describe('AWS', () => { expect(async () => { await awsFailedFileSystem._tryToDetectUuid(); - }).rejects.toThrowError(fileDNE); + }).rejects.toThrow(fileDNE); }); }); }); diff --git a/src/plugins/kibana_usage_collection/server/collectors/cloud/detector/aws.ts b/src/plugins/kibana_usage_collection/server/collectors/cloud/detector/aws.ts index 17fda9ecea810..06e7f5f309680 100644 --- a/src/plugins/kibana_usage_collection/server/collectors/cloud/detector/aws.ts +++ b/src/plugins/kibana_usage_collection/server/collectors/cloud/detector/aws.ts @@ -127,13 +127,20 @@ export class AWSCloudService extends CloudService { _tryToDetectUuid() { // Windows does not have an easy way to check if (!this._isWindows) { - return promisify(this._fs.readFile)('/sys/hypervisor/uuid', 'utf8').then((uuid) => { - if (isString(uuid)) { - // Some AWS APIs return it lowercase (like the file did in testing), while others return it uppercase - uuid = uuid.trim().toLowerCase(); - - if (uuid.startsWith('ec2')) { - return new CloudServiceResponse(this._name, true, { id: uuid }); + const pathsToCheck = ['/sys/hypervisor/uuid', '/sys/devices/virtual/dmi/id/product_uuid']; + const promises = pathsToCheck.map((path) => promisify(this._fs.readFile)(path, 'utf8')); + + return Promise.all(promises).then((uuids) => { + for (let uuid of uuids) { + if (isString(uuid)) { + // Some AWS APIs return it lowercase (like the file did in testing), while others return it uppercase + uuid = uuid.trim().toLowerCase(); + + // There is a small chance of a false positive here in the unlikely event that a uuid which doesn't + // belong to ec2 happens to be generated with `ec2` as the first three characters. + if (uuid.startsWith('ec2')) { + return new CloudServiceResponse(this._name, true, { id: uuid }); + } } }