Skip to content
This repository has been archived by the owner on Sep 3, 2024. It is now read-only.

Commit

Permalink
Merge pull request #72 from JupiterOne/APP-15542
Browse files Browse the repository at this point in the history
APP-15542 - Update to use createIntegrationHelpers
  • Loading branch information
jzolo22 authored Jul 16, 2024
2 parents 196a795 + fc3dcf4 commit 0a90333
Show file tree
Hide file tree
Showing 14 changed files with 511 additions and 264 deletions.
10 changes: 9 additions & 1 deletion husky.config.js
Original file line number Diff line number Diff line change
@@ -1 +1,9 @@
module.exports = require('@jupiterone/integration-sdk-dev-tools/config/husky');
module.exports = {
...require('@jupiterone/integration-sdk-dev-tools/config/husky'),
// TODO: This override is to make sure the hooks use yarn. It can be removed once this integration is using npm.
hooks: {
'pre-commit':
'yarn j1-integration document && git add docs/jupiterone.md && lint-staged',
'pre-push': 'yarn prepush',
},
};
10 changes: 5 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@jupiterone/graph-airwatch",
"version": "0.6.7",
"version": "0.6.8",
"description": "A graph conversion tool for https://www.air-watch.com/.",
"repository": {
"type": "git",
Expand Down Expand Up @@ -28,12 +28,12 @@
"prepack": "yarn build"
},
"peerDependencies": {
"@jupiterone/integration-sdk-core": "^11.1.0"
"@jupiterone/integration-sdk-core": "^13.2.0"
},
"devDependencies": {
"@jupiterone/integration-sdk-core": "^11.1.0",
"@jupiterone/integration-sdk-dev-tools": "^11.1.0",
"@jupiterone/integration-sdk-testing": "^11.1.0",
"@jupiterone/integration-sdk-core": "^13.2.0",
"@jupiterone/integration-sdk-dev-tools": "^13.2.0",
"@jupiterone/integration-sdk-testing": "^13.2.0",
"@types/node-fetch": "^2.5.7"
},
"dependencies": {
Expand Down
12 changes: 12 additions & 0 deletions src/client/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,14 @@ export interface AirWatchAdmin {
firstName: string;
lastName: string;
email: string;
LocationGroup: string;
LocationGroupId: string;
LastLoginTimeStamp: string;
timeZone: string;
locale: string;
messageTemplateId: string;
messageTemplateUuid: string;
initialLandingPage: string;
}

export interface AirWatchDevice {
Expand Down Expand Up @@ -65,6 +73,10 @@ export interface AirWatchOrganizationGroup {
Country: string;
WebLink: string;
CreatedOn: string;
Locale: string;
Users: number;
Admins: number;
Devices: number;

/**
* Organization groups that refer to this group as their
Expand Down
154 changes: 154 additions & 0 deletions src/entities.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
import { SchemaType } from '@jupiterone/integration-sdk-core';
import {
createEntityType,
createEntityMetadata,
createMultiClassEntityMetadata,
} from './helpers';
import { typeboxClassSchemaMap } from '@jupiterone/data-model';

type PlatformValues =
| 'other'
| 'darwin'
| 'linux'
| 'unix'
| 'windows'
| 'android'
| 'ios'
| 'embedded';

// https://resources.workspaceone.com/view/zv5cgwjrcv972rd6fmml/en --> chapter 17 for platform values
// Will not use until cutover strategy is defined
export const platformConverter = (apiPlatformValue: string): PlatformValues => {
const lowerCasePlatform = apiPlatformValue.toLowerCase();
if (lowerCasePlatform.includes('android')) {
return 'android';
} else if (lowerCasePlatform === 'apple') {
return 'ios';
} else if (lowerCasePlatform.includes('windows')) {
return 'windows';
} else {
return 'other';
}
};

export const [AccountEntityMetadata, createAccountAssignEntity] =
createEntityMetadata({
resourceName: 'Account',
_class: ['Account'],
_type: createEntityType('account'),
description: 'Airwatch Account',
schema: SchemaType.Object({
name: SchemaType.String(),
}),
});

export const [AdminEntityMetadata, createAdminAssignEntity] =
createEntityMetadata({
resourceName: 'Admin',
_class: ['User'],
_type: createEntityType('user'),
description: 'Airwatch Admin',
schema: SchemaType.Object({
admin: SchemaType.Boolean(),
uuid: SchemaType.Optional(SchemaType.String()),
organizationGroupUuid: SchemaType.Optional(SchemaType.String()),
username: SchemaType.Optional(SchemaType.String()),
firstName: SchemaType.Optional(SchemaType.String()),
lastName: SchemaType.Optional(SchemaType.String()),
email: SchemaType.Optional(SchemaType.String()),
initialLandingPage: SchemaType.Optional(SchemaType.String()),
lastLoginTimeStamp: SchemaType.Optional(SchemaType.Number()),
locale: SchemaType.Optional(SchemaType.String()),
locationGroup: SchemaType.Optional(SchemaType.String()),
locationGroupId: SchemaType.Optional(SchemaType.String()),
messageTemplateId: SchemaType.Optional(SchemaType.String()),
messageTemplateUuid: SchemaType.Optional(SchemaType.String()),
timeZone: SchemaType.Optional(SchemaType.String()),
}),
});

export const [
OrganizationGroupEntityMetadata,
createOrganizationGroupAssignEntity,
] = createMultiClassEntityMetadata({
resourceName: 'Organization Group',
_class: [typeboxClassSchemaMap['Group'], typeboxClassSchemaMap['UserGroup']],
_type: createEntityType('group'),
description: 'Airwatch Group',
schema: SchemaType.Object({
uuid: SchemaType.Optional(SchemaType.String()),
groupId: SchemaType.Optional(SchemaType.String()),
locationGroupType: SchemaType.Optional(
SchemaType.String({
description: 'Type of organization group',
examples: ['Global', 'Customer', 'Partner'],
}),
),
country: SchemaType.Optional(SchemaType.String()),
admins: SchemaType.Optional(
SchemaType.Number({
description: 'Number of console admin users in the organization group',
}),
),
devices: SchemaType.Optional(
SchemaType.Number({
description:
'Number of enrolled/unenrolled devices present in the organization group',
}),
),
users: SchemaType.Optional(
SchemaType.Number({
description: 'Number of enrollment users in the organization group',
}),
),
locale: SchemaType.Optional(SchemaType.String()),
}),
});

export const [UserEndpointEntityMetadata, createUserEndpointAssignEntity] =
createMultiClassEntityMetadata({
resourceName: 'Device',
_class: [typeboxClassSchemaMap['Host'], typeboxClassSchemaMap['Device']],
_type: 'user_endpoint',
description: 'Airwatch User Endpoint',
schema: SchemaType.Object({
username: SchemaType.Optional(SchemaType.String()),
email: SchemaType.Optional(SchemaType.String()),
uuid: SchemaType.Optional(SchemaType.String()),
serialNumber: SchemaType.Optional(SchemaType.String()),
imei: SchemaType.Optional(SchemaType.String()),
deviceFriendlyName: SchemaType.Optional(SchemaType.String()),
ownerId: SchemaType.Optional(SchemaType.String()),
assetNumber: SchemaType.Optional(SchemaType.String()),
hostName: SchemaType.Optional(SchemaType.String()),
wifiSsid: SchemaType.Optional(SchemaType.String()),
isSupervised: SchemaType.Optional(SchemaType.Boolean()),
userEmailAddress: SchemaType.Optional(SchemaType.String()),
airwatchPlatform: SchemaType.Optional(SchemaType.String()),
operatingSystem: SchemaType.Optional(SchemaType.String()),
}),
});

export const [DeviceUserEntityMetadata, createDeviceUserAssignEntity] =
createEntityMetadata({
resourceName: 'Device User',
_class: ['User'],
_type: 'device_user',
description: 'Airwatch Device User',
schema: SchemaType.Object({
uuid: SchemaType.Optional(SchemaType.String()),
}),
});

export const [ProfileEntityMetadata, createProfileAssignEntity] =
createEntityMetadata({
resourceName: 'Profile',
_class: ['Configuration'],
_type: createEntityType('profile'),
description: 'Airwatch Profile',
schema: SchemaType.Object({
platform: SchemaType.Optional(SchemaType.String()),
managedBy: SchemaType.Optional(SchemaType.String()),
payloads: SchemaType.Optional(SchemaType.Array(SchemaType.String())),
}),
});
11 changes: 11 additions & 0 deletions src/helpers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { createIntegrationHelpers } from '@jupiterone/integration-sdk-core';
import { typeboxClassSchemaMap } from '@jupiterone/data-model';

export const {
createEntityType,
createEntityMetadata,
createMultiClassEntityMetadata,
} = createIntegrationHelpers({
integrationName: 'airwatch',
classSchemaMap: typeboxClassSchemaMap,
});
12 changes: 6 additions & 6 deletions src/steps/__snapshots__/index.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ exports[`should collect data 1`] = `
"createdOn": undefined,
"displayName": "as1985.awmdm.com",
"name": "as1985.awmdm.com",
"vendor": "AirWatch",
"webLink": "https://as1985.awmdm.com",
},
{
Expand Down Expand Up @@ -50,18 +51,17 @@ exports[`should collect data 1`] = `
},
],
"_type": "airwatch_group",
"admins": "4",
"admins": 4,
"country": "Argentina",
"createdOn": 1698375953,
"devices": "0",
"devices": 0,
"displayName": "M104252336",
"groupId": "M1044590",
"id": "1112",
"lgLevel": 0,
"locale": "English (United States)",
"locationGroupType": "Customer",
"name": "M104252336",
"users": "2",
"users": 2,
"uuid": "71b1202a-fc21-4239-bacb-5e74e35a820e",
"webLink": "https://as1985.awmdm.com/AirWatch/#/AirWatch/OrganizationGroup/Details/Index/1112",
},
Expand Down Expand Up @@ -109,7 +109,7 @@ exports[`should collect data 1`] = `
"email": "erica.nagle@jupiterone.com",
"firstName": "Erica",
"initialLandingPage": "/Device/Dashboard",
"lastLoginTimeStamp": "2023-10-27T19:33:33.163",
"lastLoginTimeStamp": 1698435213163,
"lastName": "Nagle",
"locale": "en-US",
"locationGroup": "M104252336",
Expand Down Expand Up @@ -167,7 +167,7 @@ exports[`should collect data 1`] = `
"email": "J1@J1.com",
"firstName": "J1",
"initialLandingPage": "/Device/Dashboard",
"lastLoginTimeStamp": "2023-10-27T18:06:03.293",
"lastLoginTimeStamp": 1698429963293,
"lastName": "J1",
"locale": "en-US",
"locationGroup": "M104252336",
Expand Down
8 changes: 4 additions & 4 deletions src/steps/access.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,14 @@ import {
ACCOUNT_ORGANIZATION_GROUP_RELATIONSHIP_CLASS,
Entities,
ORGANIZATION_GROUP_ADMIN_RELATIONSHIP_CLASS,
ORGANIZATION_GROUP_ENTITY_TYPE,
ORGANIZATION_GROUP_RELATIONSHIP_CLASS,
Relationships,
STEP_FETCH_ACCOUNT,
STEP_FETCH_ADMINS,
STEP_FETCH_ORGANIZATION_GROUPS,
} from './constants';
import { createAdminEntity, createOrganizationGroupEntity } from './converters';
import { OrganizationGroupEntityMetadata } from '../entities';

export async function fetchOrganizationGroups({
instance,
Expand Down Expand Up @@ -51,7 +51,7 @@ export async function fetchOrganizationGroups({
});

await jobState.iterateEntities(
{ _type: ORGANIZATION_GROUP_ENTITY_TYPE },
{ _type: OrganizationGroupEntityMetadata._type },
async (groupEntity) => {
const groupData = getRawData(groupEntity) as AirWatchOrganizationGroup;
for (const childGroup of groupData?.Children || []) {
Expand All @@ -60,9 +60,9 @@ export async function fetchOrganizationGroups({
await jobState.addRelationship(
createDirectRelationship({
_class: ORGANIZATION_GROUP_RELATIONSHIP_CLASS,
fromType: ORGANIZATION_GROUP_ENTITY_TYPE,
fromType: OrganizationGroupEntityMetadata._type,
fromKey: groupEntity._key,
toType: ORGANIZATION_GROUP_ENTITY_TYPE,
toType: OrganizationGroupEntityMetadata._type,
toKey: childEntityKey,
}),
);
Expand Down
23 changes: 7 additions & 16 deletions src/steps/account.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,8 @@ import {
} from '@jupiterone/integration-sdk-core';

import { IntegrationConfig } from '../types';
import {
ACCOUNT_ENTITY_CLASS,
ACCOUNT_ENTITY_TYPE,
STEP_FETCH_ACCOUNT,
} from './constants';
import { Entities, STEP_FETCH_ACCOUNT } from './constants';
import { createAccountAssignEntity } from '../entities';

export const ACCOUNT_ENTITY_KEY = 'entity:account';

Expand All @@ -24,13 +21,13 @@ export async function fetchAccountDetails({
host: instance.config.airwatchHost,
username: instance.config.airwatchUsername,
},
assign: {
_class: ACCOUNT_ENTITY_CLASS,
_type: ACCOUNT_ENTITY_TYPE,
assign: createAccountAssignEntity({
_key: `airwatch-${instance.id}`,
name: instance.config.airwatchHost,
displayName: instance.config.airwatchHost,
webLink: `https://${instance.config.airwatchHost}`,
},
vendor: 'AirWatch',
}),
},
}),
);
Expand All @@ -42,13 +39,7 @@ export const accountSteps: IntegrationStep<IntegrationConfig>[] = [
{
id: STEP_FETCH_ACCOUNT,
name: 'Fetch Account Details',
entities: [
{
resourceName: 'Account',
_type: ACCOUNT_ENTITY_TYPE,
_class: ACCOUNT_ENTITY_CLASS,
},
],
entities: [Entities.ACCOUNT],
relationships: [],
dependsOn: [],
executionHandler: fetchAccountDetails,
Expand Down
Loading

0 comments on commit 0a90333

Please sign in to comment.