ownerlens 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +183 -0
- package/README.md +209 -0
- package/bin/ownerlens.js +92 -0
- package/dist/assets/index-B9aAYpVl.css +1 -0
- package/dist/assets/index-BcwLk2bx.js +10 -0
- package/dist/index.html +13 -0
- package/package.json +73 -0
- package/src/App.tsx +18 -0
- package/src/components/azure/AzureComponent.test.tsx +625 -0
- package/src/components/azure/AzureComponent.tsx +189 -0
- package/src/components/azure/AzureRbacComponent.tsx +104 -0
- package/src/components/azure/ClosableAzureTab.tsx +42 -0
- package/src/components/azure/EntraPermissionsComponent.tsx +194 -0
- package/src/components/azure/ManagedIdentityComponent.test.tsx +324 -0
- package/src/components/azure/ManagedIdentityComponent.tsx +141 -0
- package/src/components/azure/ResourceGroupComponent.tsx +157 -0
- package/src/components/azure/ServicePrincipalComponent.test.tsx +457 -0
- package/src/components/azure/ServicePrincipalComponent.tsx +155 -0
- package/src/components/azure/ServicePrincipalFieldRenderers.tsx +140 -0
- package/src/components/azure/ZtaComponent.test.tsx +267 -0
- package/src/components/azure/ZtaComponent.tsx +276 -0
- package/src/components/azure/ZtaRemediationBadge.tsx +70 -0
- package/src/components/azure/api.ts +216 -0
- package/src/components/azure/azureReportConfig.ts +247 -0
- package/src/core/azure/azureRbac.ts +70 -0
- package/src/core/azure/entra/index.ts +1 -0
- package/src/core/azure/entra/managedIdentity.ts +21 -0
- package/src/core/azure/entra/servicePrincipal.ts +34 -0
- package/src/core/azure/entra/types.ts +56 -0
- package/src/core/azure/identityEnrichment.ts +65 -0
- package/src/core/azure/resources.ts +141 -0
- package/src/core/azure/ztaReport.ts +58 -0
- package/src/core/config.ts +39 -0
- package/src/core/ownership/OwnershipTarget.ts +32 -0
- package/src/core/ownership/resolveOwner.ts +5 -0
- package/src/core/ownership/types.ts +14 -0
- package/src/core/risk/types.ts +1 -0
- package/src/core/runtime/index.ts +1 -0
- package/src/core/runtime/localSnapshotFiles.ts +74 -0
- package/src/core/runtime/rest.ts +61 -0
- package/src/lib/searchFilterUtils.ts +17 -0
- package/src/lib/utils.ts +48 -0
- package/src/main.tsx +10 -0
- package/src/providers/azure/identities/azureIdentityTypes.ts +1 -0
- package/src/providers/azure/identities/buildAzureManagedIdentityAssignmentIndex.test.ts +32 -0
- package/src/providers/azure/identities/buildAzureManagedIdentityAssignmentIndex.ts +35 -0
- package/src/providers/azure/identities/userAssignedIdentityAssignments.ts +52 -0
- package/src/providers/azure/inputTransferObject/entra/EntraAppRoleAssignment.ts +10 -0
- package/src/providers/azure/inputTransferObject/entra/EntraApplication.ts +27 -0
- package/src/providers/azure/inputTransferObject/entra/EntraOAuth2PermissionGrant.ts +8 -0
- package/src/providers/azure/inputTransferObject/entra/EntraServicePrincipal.ts +43 -0
- package/src/providers/azure/inputTransferObject/entra/EntraSnapshot.ts +13 -0
- package/src/providers/azure/inputTransferObject/entra/EntraSnapshotMeta.ts +12 -0
- package/src/providers/azure/inputTransferObject/resources/AzureActivityLog.ts +1 -0
- package/src/providers/azure/inputTransferObject/resources/AzureResource.ts +1 -0
- package/src/providers/azure/inputTransferObject/resources/AzureResourceGroup.ts +1 -0
- package/src/providers/azure/inputTransferObject/resources/AzureRoleAssignment.ts +1 -0
- package/src/providers/azure/inputTransferObject/resources/AzureSnapshot.ts +1 -0
- package/src/providers/azure/inputTransferObject/resources/AzureSnapshotMeta.ts +1 -0
- package/src/providers/azure/inputTransferObject/resources/AzureSubscription.ts +1 -0
- package/src/providers/azure/inputTransferObject/resources/AzureUserAssignedManagedIdentity.ts +1 -0
- package/src/providers/azure/ownership/azureActivityOwnershipEvidence.ts +60 -0
- package/src/providers/azure/ownership/azureOwnerReportTypes.ts +13 -0
- package/src/providers/azure/ownership/azureOwnershipConfig.ts +21 -0
- package/src/providers/azure/ownership/azureOwnershipTypes.ts +46 -0
- package/src/providers/azure/ownership/buildAzureOwnershipReport.test.ts +99 -0
- package/src/providers/azure/ownership/buildAzureOwnershipReport.ts +90 -0
- package/src/providers/azure/ownership/buildAzureOwnershipTargets.test.ts +87 -0
- package/src/providers/azure/ownership/buildAzureOwnershipTargets.ts +42 -0
- package/src/providers/azure/ownership/resolveAzureOwner.ts +146 -0
- package/src/providers/azure/runtime/DisabledEvidenceStore.ts +34 -0
- package/src/providers/azure/runtime/EnrichmentService.ts +35 -0
- package/src/providers/azure/runtime/LocalReportRuntime.test.ts +2318 -0
- package/src/providers/azure/runtime/LocalReportRuntime.ts +302 -0
- package/src/providers/azure/runtime/RuntimeHost.ts +60 -0
- package/src/providers/azure/runtime/SnapshotImporter.ts +44 -0
- package/src/providers/azure/runtime/enrichment/azureIdentityEnrichment.ts +523 -0
- package/src/providers/azure/runtime/enrichment/azureScopeClassifier.ts +30 -0
- package/src/providers/azure/runtime/enrichment/evaluateAzureRoleAssignmentRisk.ts +88 -0
- package/src/providers/azure/runtime/entra/EntraCollectionQueryService.ts +307 -0
- package/src/providers/azure/runtime/entra/LocalEntraReportRuntime.ts +227 -0
- package/src/providers/azure/runtime/entra/appRoleAssignmentsTable.ts +52 -0
- package/src/providers/azure/runtime/entra/applicationsTable.ts +175 -0
- package/src/providers/azure/runtime/entra/entraServicePrincipalMapper.ts +63 -0
- package/src/providers/azure/runtime/entra/localReportRuntimeRest.ts +41 -0
- package/src/providers/azure/runtime/entra/oauth2PermissionGrantsTable.ts +48 -0
- package/src/providers/azure/runtime/entra/principalProjection.ts +173 -0
- package/src/providers/azure/runtime/entra/servicePrincipalsTable.ts +149 -0
- package/src/providers/azure/runtime/entra/snapshotMetadataTable.ts +18 -0
- package/src/providers/azure/runtime/entra/snapshotStore.ts +102 -0
- package/src/providers/azure/runtime/localReportCollections.ts +101 -0
- package/src/providers/azure/runtime/localReportRuntimeRest.ts +71 -0
- package/src/providers/azure/runtime/resources/AzureResourcesCollectionQueryService.ts +145 -0
- package/src/providers/azure/runtime/resources/LocalAzureResourcesReportRuntime.ts +114 -0
- package/src/providers/azure/runtime/resources/disabledOwnerEvidenceTable.ts +60 -0
- package/src/providers/azure/runtime/resources/localReportRuntimeRest.ts +81 -0
- package/src/providers/azure/runtime/resources/resourceGroupOwnership.ts +90 -0
- package/src/providers/azure/runtime/resources/snapshotMetadataTable.ts +19 -0
- package/src/providers/azure/runtime/resources/snapshotStore.ts +128 -0
- package/src/providers/azure/runtime/resources/tables.ts +441 -0
- package/src/providers/azure/runtime/runtimeRestQuery.ts +46 -0
- package/src/providers/azure/runtime/runtimeSqlSchema.ts +357 -0
- package/src/providers/azure/runtime/zta/Discovery.ts +141 -0
- package/src/providers/azure/runtime/zta/LocalZeroTrustAssessmentReportRuntime.ts +86 -0
- package/src/providers/azure/runtime/zta/ZeroTrustAssessmentQueryService.ts +124 -0
- package/src/providers/azure/runtime/zta/localReportRuntimeRest.ts +15 -0
- package/src/providers/azure/runtime/zta/snapshotMetadataTable.ts +77 -0
- package/src/providers/azure/runtime/zta/snapshotStore.ts +112 -0
- package/src/providers/azure/runtime/zta/tables.ts +361 -0
- package/src/providers/azure/runtime/zta/types.ts +7 -0
- package/src/providers/azure/runtime/zta/ztaReportMapper.ts +12 -0
- package/src/report/applyCollectionControls.ts +289 -0
- package/src/report/buildCollectionColumns.tsx +38 -0
- package/src/report/components/ConfidenceBadge.tsx +10 -0
- package/src/report/components/EvidenceList.test.ts +25 -0
- package/src/report/components/EvidenceList.tsx +52 -0
- package/src/report/components/GenericTable.tsx +373 -0
- package/src/report/components/PermissionRiskBadge.tsx +19 -0
- package/src/report/components/reportTableControls.test.ts +175 -0
- package/src/report/components/reportTableControls.tsx +483 -0
- package/src/report/components/ui/badge.tsx +35 -0
- package/src/report/components/ui/button.tsx +38 -0
- package/src/report/components/ui/card.tsx +23 -0
- package/src/report/components/ui/input.tsx +15 -0
- package/src/report/components/ui/table.tsx +44 -0
- package/src/report/components/ui/tabs.tsx +29 -0
- package/src/report/export/csv.ts +34 -0
- package/src/report/ownerManualPrecheck.test.ts +137 -0
- package/src/report/ownerManualPrecheck.ts +132 -0
- package/src/report/reportArchitecture.test.ts +125 -0
- package/src/report/reportTypes.ts +54 -0
- package/src/report/reportValueRenderers.tsx +54 -0
- package/src/report/runtimeCollectionQuery.ts +23 -0
- package/src/report/types.ts +14 -0
- package/src/styles.css +43 -0
- package/tools/README.md +108 -0
- package/tools/azure-activity-check.ps1 +164 -0
- package/tools/collect-azure.ps1 +54 -0
- package/tools/collect-entra.ps1 +47 -0
- package/tools/collect-scripts.test.ts +22 -0
- package/tools/prepare-entra-snapshot.ps1 +403 -0
- package/tools/prepare-entra-snapshot.test.ts +14 -0
- package/tools/prepare-resource-snapshot.ps1 +345 -0
- package/vite.config.ts +23 -0
|
@@ -0,0 +1,302 @@
|
|
|
1
|
+
import type { DuckDBConnection } from "@duckdb/node-api";
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
listLocalSnapshotFiles,
|
|
5
|
+
pathExists,
|
|
6
|
+
readLocalSnapshotFile,
|
|
7
|
+
validateSnapshotFileName,
|
|
8
|
+
type LocalSnapshotData,
|
|
9
|
+
type LocalSnapshotFile
|
|
10
|
+
} from "../../../core/runtime/localSnapshotFiles";
|
|
11
|
+
import type { ManagedIdentity } from "../../../core/azure/entra/managedIdentity";
|
|
12
|
+
import type { ServicePrincipal } from "../../../core/azure/entra/servicePrincipal";
|
|
13
|
+
import type { ZtaReport, ZtaReportTest } from "../../../core/azure/ztaReport";
|
|
14
|
+
import type { AzureIdentityEnrichmentStatus } from "./enrichment/azureIdentityEnrichment";
|
|
15
|
+
import { EntraCollectionQueryService } from "./entra/EntraCollectionQueryService";
|
|
16
|
+
import {
|
|
17
|
+
LocalEntraReportRuntime,
|
|
18
|
+
type EntraPrincipalPermissions,
|
|
19
|
+
type LocalEntraReportCollectionId
|
|
20
|
+
} from "./entra/LocalEntraReportRuntime";
|
|
21
|
+
import type { EntraDuckDbImportStatus } from "./entra/snapshotStore";
|
|
22
|
+
import {
|
|
23
|
+
AzureResourcesCollectionQueryService,
|
|
24
|
+
type LocalAzureResourcesExtendedCollectionId
|
|
25
|
+
} from "./resources/AzureResourcesCollectionQueryService";
|
|
26
|
+
import { LocalAzureResourcesReportRuntime } from "./resources/LocalAzureResourcesReportRuntime";
|
|
27
|
+
import type { AzureResourcesDuckDbImportStatus } from "./resources/snapshotStore";
|
|
28
|
+
import { LocalZeroTrustAssessmentReportRuntime } from "./zta/LocalZeroTrustAssessmentReportRuntime";
|
|
29
|
+
import type { ZeroTrustAssessmentDuckDbImportStatus } from "./zta/snapshotStore";
|
|
30
|
+
import {
|
|
31
|
+
ZeroTrustAssessmentQueryService,
|
|
32
|
+
type LocalZeroTrustAssessmentReportCollectionId
|
|
33
|
+
} from "./zta/ZeroTrustAssessmentQueryService";
|
|
34
|
+
import {
|
|
35
|
+
type LocalReportCollectionQueryOptions,
|
|
36
|
+
type LocalReportPaginatedCollection
|
|
37
|
+
} from "./localReportCollections";
|
|
38
|
+
import { RuntimeHost } from "./RuntimeHost";
|
|
39
|
+
import { SnapshotImporter } from "./SnapshotImporter";
|
|
40
|
+
import { EnrichmentService } from "./EnrichmentService";
|
|
41
|
+
import { DisabledEvidenceStore, type DisabledOwnerKey } from "./DisabledEvidenceStore";
|
|
42
|
+
import { prepareRuntimeSqlSchema } from "./runtimeSqlSchema";
|
|
43
|
+
|
|
44
|
+
export type LocalReportRuntimeOptions = {
|
|
45
|
+
dataDir: string;
|
|
46
|
+
databasePath?: string;
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
export type LocalReportRuntimeStatus = {
|
|
50
|
+
initialized: boolean;
|
|
51
|
+
databasePath: string;
|
|
52
|
+
entra: EntraDuckDbImportStatus;
|
|
53
|
+
azureResources: AzureResourcesDuckDbImportStatus;
|
|
54
|
+
zeroTrustAssessment: ZeroTrustAssessmentDuckDbImportStatus;
|
|
55
|
+
enrichment: AzureIdentityEnrichmentStatus;
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
export type LocalReportCollectionId =
|
|
59
|
+
| LocalEntraReportCollectionId
|
|
60
|
+
| LocalAzureResourcesExtendedCollectionId
|
|
61
|
+
| LocalZeroTrustAssessmentReportCollectionId;
|
|
62
|
+
|
|
63
|
+
export class LocalReportRuntime {
|
|
64
|
+
private readonly dataDir: string;
|
|
65
|
+
private readonly host: RuntimeHost;
|
|
66
|
+
private readonly entra: LocalEntraReportRuntime;
|
|
67
|
+
private readonly azureResources: LocalAzureResourcesReportRuntime;
|
|
68
|
+
private readonly zeroTrustAssessment: LocalZeroTrustAssessmentReportRuntime;
|
|
69
|
+
private readonly zeroTrustAssessmentQueries: ZeroTrustAssessmentQueryService;
|
|
70
|
+
private readonly azureResourcesQueries: AzureResourcesCollectionQueryService;
|
|
71
|
+
private readonly entraQueries: EntraCollectionQueryService;
|
|
72
|
+
private readonly snapshotImporter: SnapshotImporter;
|
|
73
|
+
private readonly enrichmentService: EnrichmentService;
|
|
74
|
+
private readonly disabledEvidenceStore: DisabledEvidenceStore;
|
|
75
|
+
private initializePromise: Promise<void> | null = null;
|
|
76
|
+
|
|
77
|
+
constructor(options: LocalReportRuntimeOptions) {
|
|
78
|
+
this.dataDir = options.dataDir;
|
|
79
|
+
this.host = new RuntimeHost({ databasePath: options.databasePath ?? ":memory:" });
|
|
80
|
+
this.entra = new LocalEntraReportRuntime({
|
|
81
|
+
dataDir: this.dataDir,
|
|
82
|
+
getConnection: () => this.requireConnection()
|
|
83
|
+
});
|
|
84
|
+
this.azureResources = new LocalAzureResourcesReportRuntime({
|
|
85
|
+
dataDir: this.dataDir,
|
|
86
|
+
getConnection: () => this.requireConnection()
|
|
87
|
+
});
|
|
88
|
+
this.zeroTrustAssessment = new LocalZeroTrustAssessmentReportRuntime({
|
|
89
|
+
dataDir: this.dataDir,
|
|
90
|
+
getConnection: () => this.requireConnection()
|
|
91
|
+
});
|
|
92
|
+
this.zeroTrustAssessmentQueries = new ZeroTrustAssessmentQueryService({
|
|
93
|
+
zeroTrustAssessment: this.zeroTrustAssessment
|
|
94
|
+
});
|
|
95
|
+
this.snapshotImporter = new SnapshotImporter({
|
|
96
|
+
entra: this.entra,
|
|
97
|
+
azureResources: this.azureResources,
|
|
98
|
+
zeroTrustAssessment: this.zeroTrustAssessment
|
|
99
|
+
});
|
|
100
|
+
this.enrichmentService = new EnrichmentService(() => this.requireConnection());
|
|
101
|
+
this.disabledEvidenceStore = new DisabledEvidenceStore(() => this.requireConnection());
|
|
102
|
+
this.azureResourcesQueries = new AzureResourcesCollectionQueryService({
|
|
103
|
+
entra: this.entra,
|
|
104
|
+
azureResources: this.azureResources,
|
|
105
|
+
disabledEvidenceStore: this.disabledEvidenceStore
|
|
106
|
+
});
|
|
107
|
+
this.entraQueries = new EntraCollectionQueryService({
|
|
108
|
+
entra: this.entra,
|
|
109
|
+
azureResources: this.azureResources,
|
|
110
|
+
azureResourcesQueries: this.azureResourcesQueries,
|
|
111
|
+
zeroTrustAssessmentQueries: this.zeroTrustAssessmentQueries
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
initialize(): Promise<void> {
|
|
116
|
+
this.initializePromise ??= this.initializeInternal();
|
|
117
|
+
return this.initializePromise;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
async listSnapshots(): Promise<{ files: LocalSnapshotFile[]; error?: string }> {
|
|
121
|
+
await this.initialize();
|
|
122
|
+
|
|
123
|
+
if (!(await pathExists(this.dataDir))) {
|
|
124
|
+
return {
|
|
125
|
+
files: [],
|
|
126
|
+
error:
|
|
127
|
+
"Snapshot directory ./data was not found. Run the snapshot scripts to create ./data/snapshot.json and ./data/entra-snapshot.json."
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
return { files: await listLocalSnapshotFiles(this.dataDir) };
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
async readSnapshot(name: string): Promise<LocalSnapshotData> {
|
|
135
|
+
await this.initialize();
|
|
136
|
+
validateSnapshotFileName(name);
|
|
137
|
+
|
|
138
|
+
if (this.entra.canReadSnapshot(name)) {
|
|
139
|
+
return this.entra.readSnapshot();
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
if (this.azureResources.canReadSnapshot(name)) {
|
|
143
|
+
return this.azureResources.readSnapshot();
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
return readLocalSnapshotFile(this.dataDir, name);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
getStatus(): LocalReportRuntimeStatus {
|
|
150
|
+
const importStatus = this.snapshotImporter.getStatus();
|
|
151
|
+
|
|
152
|
+
return {
|
|
153
|
+
initialized: this.host.isInitialized(),
|
|
154
|
+
databasePath: this.host.getDatabasePath(),
|
|
155
|
+
entra: importStatus.entra,
|
|
156
|
+
azureResources: importStatus.azureResources,
|
|
157
|
+
zeroTrustAssessment: importStatus.zeroTrustAssessment,
|
|
158
|
+
enrichment: this.enrichmentService.getStatus()
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
async readServicePrincipals(): Promise<ServicePrincipal[]> {
|
|
163
|
+
await this.initialize();
|
|
164
|
+
return this.entra.readServicePrincipals();
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
async readManagedIdentities(): Promise<ManagedIdentity[]> {
|
|
168
|
+
await this.initialize();
|
|
169
|
+
return this.entra.readManagedIdentities();
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
async readZeroTrustAssessmentReport(): Promise<ZtaReport> {
|
|
173
|
+
await this.initialize();
|
|
174
|
+
return this.zeroTrustAssessmentQueries.readReport();
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
async recalculateEnrichment(): Promise<void> {
|
|
178
|
+
await this.initialize();
|
|
179
|
+
await this.enrichmentService.recalculate();
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
async setOwnerEvidenceDisabled(key: DisabledOwnerKey, disabled: boolean): Promise<number> {
|
|
183
|
+
await this.initialize();
|
|
184
|
+
return this.disabledEvidenceStore.setDisabled(key, disabled);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
async queryEntraServicePrincipals(
|
|
188
|
+
options: LocalReportCollectionQueryOptions
|
|
189
|
+
): Promise<LocalReportPaginatedCollection<"entra.servicePrincipals">> {
|
|
190
|
+
await this.initialize();
|
|
191
|
+
return this.entraQueries.queryServicePrincipals(options);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
async queryEntraManagedIdentities(
|
|
195
|
+
options: LocalReportCollectionQueryOptions
|
|
196
|
+
): Promise<LocalReportPaginatedCollection<"entra.managedIdentities">> {
|
|
197
|
+
await this.initialize();
|
|
198
|
+
return this.entraQueries.queryManagedIdentities(options);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
async queryEntraOAuth2PermissionGrants(
|
|
202
|
+
options: LocalReportCollectionQueryOptions
|
|
203
|
+
): Promise<LocalReportPaginatedCollection<"entra.oauth2PermissionGrants">> {
|
|
204
|
+
await this.initialize();
|
|
205
|
+
return this.entraQueries.queryOAuth2PermissionGrants(options);
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
async queryEntraAppRoleAssignments(
|
|
209
|
+
options: LocalReportCollectionQueryOptions
|
|
210
|
+
): Promise<LocalReportPaginatedCollection<"entra.appRoleAssignments">> {
|
|
211
|
+
await this.initialize();
|
|
212
|
+
return this.entraQueries.queryAppRoleAssignments(options);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
async readEntraPrincipalPermissions(principalId: string): Promise<EntraPrincipalPermissions> {
|
|
216
|
+
await this.initialize();
|
|
217
|
+
return this.entra.readEntraPrincipalPermissions(principalId);
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
async queryAzureSubscriptions(
|
|
221
|
+
options: LocalReportCollectionQueryOptions
|
|
222
|
+
): Promise<LocalReportPaginatedCollection<"azureResources.subscriptions">> {
|
|
223
|
+
await this.initialize();
|
|
224
|
+
return this.azureResourcesQueries.querySubscriptions(options);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
async queryAzureResourceGroups(
|
|
228
|
+
options: LocalReportCollectionQueryOptions
|
|
229
|
+
): Promise<LocalReportPaginatedCollection<"azureResources.resourceGroups">> {
|
|
230
|
+
await this.initialize();
|
|
231
|
+
return this.azureResourcesQueries.queryResourceGroups(options);
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
async queryAzureResourceGroupOwnership(
|
|
235
|
+
options: LocalReportCollectionQueryOptions
|
|
236
|
+
): Promise<LocalReportPaginatedCollection<"azureResources.resourceGroupOwnership">> {
|
|
237
|
+
await this.initialize();
|
|
238
|
+
return this.azureResourcesQueries.queryResourceGroupOwnership(options);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
async queryAzureResources(
|
|
242
|
+
options: LocalReportCollectionQueryOptions
|
|
243
|
+
): Promise<LocalReportPaginatedCollection<"azureResources.resources">> {
|
|
244
|
+
await this.initialize();
|
|
245
|
+
return this.azureResourcesQueries.queryResources(options);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
async queryAzureUserAssignedManagedIdentities(
|
|
249
|
+
options: LocalReportCollectionQueryOptions
|
|
250
|
+
): Promise<LocalReportPaginatedCollection<"azureResources.userAssignedManagedIdentities">> {
|
|
251
|
+
await this.initialize();
|
|
252
|
+
return this.azureResourcesQueries.queryUserAssignedManagedIdentities(options);
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
async queryAzureRoleAssignments(
|
|
256
|
+
options: LocalReportCollectionQueryOptions
|
|
257
|
+
): Promise<LocalReportPaginatedCollection<"azureResources.roleAssignments">> {
|
|
258
|
+
await this.initialize();
|
|
259
|
+
return this.azureResourcesQueries.queryRoleAssignments(options);
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
async queryAzureRbac(
|
|
263
|
+
servicePrincipalId: string,
|
|
264
|
+
options: LocalReportCollectionQueryOptions
|
|
265
|
+
): Promise<LocalReportPaginatedCollection<"azureRbac">> {
|
|
266
|
+
await this.initialize();
|
|
267
|
+
return this.azureResourcesQueries.queryAzureRbac(servicePrincipalId, options);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
async queryAzureActivityLogs(
|
|
271
|
+
options: LocalReportCollectionQueryOptions
|
|
272
|
+
): Promise<LocalReportPaginatedCollection<"azureResources.activityLogs">> {
|
|
273
|
+
await this.initialize();
|
|
274
|
+
return this.azureResourcesQueries.queryActivityLogs(options);
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
async queryZeroTrustAssessmentReport(
|
|
278
|
+
options: LocalReportCollectionQueryOptions
|
|
279
|
+
): Promise<
|
|
280
|
+
LocalReportPaginatedCollection<"zeroTrustAssessment.report"> & Pick<ZtaReport, "Meta"> & { Tests: ZtaReportTest[] }
|
|
281
|
+
> {
|
|
282
|
+
await this.initialize();
|
|
283
|
+
return this.zeroTrustAssessmentQueries.queryReport(options);
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
async close(): Promise<void> {
|
|
287
|
+
await this.host.close();
|
|
288
|
+
this.initializePromise = null;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
private async initializeInternal(): Promise<void> {
|
|
292
|
+
await this.host.initialize();
|
|
293
|
+
await prepareRuntimeSqlSchema(this.requireConnection());
|
|
294
|
+
await this.snapshotImporter.importSnapshots();
|
|
295
|
+
await this.enrichmentService.recalculate();
|
|
296
|
+
await this.enrichmentService.readStatus();
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
private requireConnection(): DuckDBConnection {
|
|
300
|
+
return this.host.requireConnection();
|
|
301
|
+
}
|
|
302
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { mkdir } from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
|
|
4
|
+
import { DuckDBInstance, type DuckDBConnection } from "@duckdb/node-api";
|
|
5
|
+
|
|
6
|
+
export type RuntimeHostOptions = {
|
|
7
|
+
databasePath: string;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export class RuntimeHost {
|
|
11
|
+
private readonly databasePath: string;
|
|
12
|
+
private instance: DuckDBInstance | null = null;
|
|
13
|
+
private connection: DuckDBConnection | null = null;
|
|
14
|
+
private initializePromise: Promise<void> | null = null;
|
|
15
|
+
private initialized = false;
|
|
16
|
+
|
|
17
|
+
constructor(options: RuntimeHostOptions) {
|
|
18
|
+
this.databasePath = options.databasePath;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
getDatabasePath(): string {
|
|
22
|
+
return this.databasePath;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
isInitialized(): boolean {
|
|
26
|
+
return this.initialized;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
initialize(): Promise<void> {
|
|
30
|
+
this.initializePromise ??= this.initializeInternal();
|
|
31
|
+
return this.initializePromise;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
requireConnection(): DuckDBConnection {
|
|
35
|
+
if (!this.connection) {
|
|
36
|
+
throw new Error("Local report runtime is not initialized.");
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return this.connection;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
async close(): Promise<void> {
|
|
43
|
+
this.connection?.disconnectSync();
|
|
44
|
+
this.connection = null;
|
|
45
|
+
this.instance?.closeSync();
|
|
46
|
+
this.instance = null;
|
|
47
|
+
this.initializePromise = null;
|
|
48
|
+
this.initialized = false;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
private async initializeInternal(): Promise<void> {
|
|
52
|
+
if (this.databasePath !== ":memory:") {
|
|
53
|
+
await mkdir(path.dirname(this.databasePath), { recursive: true });
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
this.instance = await DuckDBInstance.create(this.databasePath);
|
|
57
|
+
this.connection = await this.instance.connect();
|
|
58
|
+
this.initialized = true;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { LocalEntraReportRuntime } from "./entra/LocalEntraReportRuntime";
|
|
2
|
+
import type { EntraDuckDbImportStatus } from "./entra/snapshotStore";
|
|
3
|
+
import { LocalAzureResourcesReportRuntime } from "./resources/LocalAzureResourcesReportRuntime";
|
|
4
|
+
import type { AzureResourcesDuckDbImportStatus } from "./resources/snapshotStore";
|
|
5
|
+
import { LocalZeroTrustAssessmentReportRuntime } from "./zta/LocalZeroTrustAssessmentReportRuntime";
|
|
6
|
+
import type { ZeroTrustAssessmentDuckDbImportStatus } from "./zta/snapshotStore";
|
|
7
|
+
|
|
8
|
+
export type SnapshotImporterOptions = {
|
|
9
|
+
entra: LocalEntraReportRuntime;
|
|
10
|
+
azureResources: LocalAzureResourcesReportRuntime;
|
|
11
|
+
zeroTrustAssessment: LocalZeroTrustAssessmentReportRuntime;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export type SnapshotImporterStatus = {
|
|
15
|
+
entra: EntraDuckDbImportStatus;
|
|
16
|
+
azureResources: AzureResourcesDuckDbImportStatus;
|
|
17
|
+
zeroTrustAssessment: ZeroTrustAssessmentDuckDbImportStatus;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export class SnapshotImporter {
|
|
21
|
+
private readonly entra: LocalEntraReportRuntime;
|
|
22
|
+
private readonly azureResources: LocalAzureResourcesReportRuntime;
|
|
23
|
+
private readonly zeroTrustAssessment: LocalZeroTrustAssessmentReportRuntime;
|
|
24
|
+
|
|
25
|
+
constructor(options: SnapshotImporterOptions) {
|
|
26
|
+
this.entra = options.entra;
|
|
27
|
+
this.azureResources = options.azureResources;
|
|
28
|
+
this.zeroTrustAssessment = options.zeroTrustAssessment;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
getStatus(): SnapshotImporterStatus {
|
|
32
|
+
return {
|
|
33
|
+
entra: this.entra.getStatus(),
|
|
34
|
+
azureResources: this.azureResources.getStatus(),
|
|
35
|
+
zeroTrustAssessment: this.zeroTrustAssessment.getStatus()
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
async importSnapshots(): Promise<void> {
|
|
40
|
+
await this.entra.importSnapshot();
|
|
41
|
+
await this.azureResources.importSnapshot();
|
|
42
|
+
await this.zeroTrustAssessment.importSnapshot();
|
|
43
|
+
}
|
|
44
|
+
}
|