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

Commit

Permalink
Adding local user ingestion.
Browse files Browse the repository at this point in the history
  • Loading branch information
adam-in-ict committed Sep 6, 2023
1 parent 71170e5 commit 0be1ffd
Show file tree
Hide file tree
Showing 7 changed files with 199 additions and 0 deletions.
2 changes: 2 additions & 0 deletions docs/jupiterone.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ The following entities are created:
| Application | `microsoft_configuration_manager_application` | `Application` |
| Device | `microsoft_configuration_manager_device` | `Device` |
| Device Collection | `microsoft_configuration_manager_device_collection` | `Group` |
| Local User | `microsoft_configuration_manager_local_user` | `User` |

### Relationships

Expand All @@ -110,6 +111,7 @@ The following relationships are created:
| --------------------------------------------------- | --------------------- | --------------------------------------------- |
| `microsoft_configuration_manager_account` | **HAS** | `microsoft_configuration_manager_device` |
| `microsoft_configuration_manager_device_collection` | **HAS** | `microsoft_configuration_manager_device` |
| `microsoft_configuration_manager_device` | **HAS** | `microsoft_configuration_manager_local_user` |
| `microsoft_configuration_manager_device` | **INSTALLED** | `microsoft_configuration_manager_application` |

<!--
Expand Down
2 changes: 2 additions & 0 deletions src/steps/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export const Steps: Record<
| 'FETCH_COLLECTIONS'
| 'FETCH_DEVICES'
| 'FETCH_LEGACY_APPLICATIONS'
| 'FETCH_LOCAL_USERS'
| 'BUILD_APPLICATION_RELATIONSHIPS'
| 'BUILD_COLLECTION_RELATIONSHIPS',
string
Expand All @@ -19,6 +20,7 @@ export const Steps: Record<
FETCH_COLLECTIONS: 'fetch-collections',
FETCH_DEVICES: 'fetch-devices',
FETCH_LEGACY_APPLICATIONS: 'fetch-legacy-applications',
FETCH_LOCAL_USERS: 'fetch-local-users',
BUILD_APPLICATION_RELATIONSHIPS: 'build-application-relationships',
BUILD_COLLECTION_RELATIONSHIPS: 'build-collection-relationships',
};
Expand Down
2 changes: 2 additions & 0 deletions src/steps/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@ import { fetchAccountSteps } from './account';
import { fetchApplicationsSteps } from './applications';
import { fetchCollectionsSteps } from './collections';
import { fetchDevicesSteps } from './devices';
import { fetchLocalUserSteps } from './localUsers';

const integrationSteps = [
...fetchAccountSteps,
...fetchApplicationsSteps,
...fetchCollectionsSteps,
...fetchDevicesSteps,
...fetchLocalUserSteps,
];

export { integrationSteps };
44 changes: 44 additions & 0 deletions src/steps/localUsers/converters.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import {
createDirectRelationship,
createIntegrationEntity,
Entity,
parseTimePropertyValue,
Relationship,
RelationshipClass,
} from '@jupiterone/integration-sdk-core';

import { Entities } from '../constants';

export function createLocalUserKey(id: string) {
return `${Entities.LOCAL_USER._type}:${id}`;
}

export function createLocalUserEntity(user: any): Entity {
const id = user.SID0?.toString();
return createIntegrationEntity({
entityData: {
source: user,
assign: {
_key: createLocalUserKey(id),
_type: Entities.LOCAL_USER._type,
_class: Entities.LOCAL_USER._class,
id: id,
name: id,
displayName: id,
localPath: user.LocalPath0,
createdOn: parseTimePropertyValue(user.TimeStamp),
},
},
});
}

export function createDeviceLocalUserRelationship(
device: Entity,
user: Entity,
): Relationship {
return createDirectRelationship({
_class: RelationshipClass.HAS,
from: device,
to: user,
});
}
29 changes: 29 additions & 0 deletions src/steps/localUsers/index.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { executeStepWithDependencies } from '@jupiterone/integration-sdk-testing';
import { buildStepTestConfigForStep } from '../../../test/config';
import { Steps } from '../constants';
import sql from 'mssql';
import { deviceRecords, localUserRecords } from '../../../test/mockData';

test('fetch-local-users', async () => {
jest.mock('mssql');
sql.connect = jest
.fn()
.mockResolvedValueOnce({
query: jest.fn().mockResolvedValue({
recordset: deviceRecords,
recordsets: [0, 0],
}),
close: jest.fn(),
})
.mockReturnValueOnce({
query: jest.fn().mockResolvedValue({
recordset: localUserRecords,
recordsets: [0, 0],
}),
close: jest.fn(),
});

const stepConfig = buildStepTestConfigForStep(Steps.FETCH_LOCAL_USERS);
const stepResult = await executeStepWithDependencies(stepConfig);
expect(stepResult).toMatchStepMetadata(stepConfig);
});
48 changes: 48 additions & 0 deletions src/steps/localUsers/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import {
IntegrationStep,
IntegrationStepExecutionContext,
} from '@jupiterone/integration-sdk-core';

import { IntegrationConfig } from '../../config';
import { Steps, Entities, Relationships } from '../constants';
import { createMicrosoftConfigurationManagerClient } from '../../configuration-manager';
import {
createDeviceLocalUserRelationship,
createLocalUserEntity,
} from './converters';
import { createDeviceKey } from '../devices/converters';

export const fetchLocalUserSteps: IntegrationStep<IntegrationConfig>[] = [
{
id: Steps.FETCH_LOCAL_USERS,
name: 'Fetch-Local-Users',
entities: [Entities.LOCAL_USER],
relationships: [Relationships.DEVICE_HAS_LOCAL_USER],
dependsOn: [Steps.FETCH_DEVICES],
executionHandler: fetchLocalUsers,
},
];

export async function fetchLocalUsers({
instance: { config },
jobState,
logger,
}: IntegrationStepExecutionContext<IntegrationConfig>) {
const client = await createMicrosoftConfigurationManagerClient(
config,
logger,
);

await client.listLocalUsers(async (user: any) => {
const userEntity = await jobState.addEntity(createLocalUserEntity(user));

const deviceEntity = await jobState.findEntity(
createDeviceKey(user.ResourceID),
);
if (deviceEntity) {
await jobState.addRelationship(
createDeviceLocalUserRelationship(deviceEntity, userEntity),
);
}
});
}
72 changes: 72 additions & 0 deletions test/mockData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -587,3 +587,75 @@ export const collectionRecords = [
IncrementalEvaluationLastRefreshTime: '2023-09-04T21:57:52.357Z',
},
];

export const localUserRecords = [
{
ResourceID: 16777219,
GroupID: 1,
RevisionID: 1,
AgentID: 1,
TimeStamp: '2023-06-16T23:24:48.000Z',
HealthStatus0: 3,
LastAttemptedProfileDownload0: null,
LastAttemptedProfileUploadTi0: null,
LastBackgroundRegistryUpload0: null,
LastDownloadTime0: null,
LastUploadTime0: null,
LastUseTime0: null,
Loaded0: null,
LocalPath0: 'C:\\Windows\\ServiceProfiles\\NetworkService',
RefCount0: null,
RoamingConfigured0: 0,
RoamingPath0: null,
RoamingPreference0: null,
SID0: 'S-1-5-20',
Special0: 1,
Status0: 0,
},
{
ResourceID: 16777219,
GroupID: 2,
RevisionID: 1,
AgentID: 1,
TimeStamp: '2023-06-16T23:24:48.000Z',
HealthStatus0: 3,
LastAttemptedProfileDownload0: null,
LastAttemptedProfileUploadTi0: null,
LastBackgroundRegistryUpload0: null,
LastDownloadTime0: null,
LastUploadTime0: null,
LastUseTime0: null,
Loaded0: null,
LocalPath0: 'C:\\Windows\\ServiceProfiles\\LocalService',
RefCount0: null,
RoamingConfigured0: 0,
RoamingPath0: null,
RoamingPreference0: null,
SID0: 'S-1-5-19',
Special0: 1,
Status0: 0,
},
{
ResourceID: 16777219,
GroupID: 3,
RevisionID: 1,
AgentID: 1,
TimeStamp: '2023-06-16T23:24:48.000Z',
HealthStatus0: 3,
LastAttemptedProfileDownload0: null,
LastAttemptedProfileUploadTi0: null,
LastBackgroundRegistryUpload0: null,
LastDownloadTime0: null,
LastUploadTime0: null,
LastUseTime0: null,
Loaded0: null,
LocalPath0: 'C:\\Windows\\system32\\config\\systemprofile',
RefCount0: null,
RoamingConfigured0: 0,
RoamingPath0: null,
RoamingPreference0: null,
SID0: 'S-1-5-18',
Special0: 1,
Status0: 0,
},
];

0 comments on commit 0be1ffd

Please sign in to comment.