@ampsec/platform-client 3.0.0 → 4.0.1

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.
Files changed (118) hide show
  1. package/build/src/FilterCriteria.d.ts +18 -0
  2. package/build/src/FilterCriteria.js +3 -0
  3. package/build/src/FilterCriteria.js.map +1 -0
  4. package/build/src/dto/enums/agent.status.js +1 -0
  5. package/build/src/dto/enums/agent.status.js.map +1 -1
  6. package/build/src/dto/enums/connector.status.js +1 -0
  7. package/build/src/dto/enums/connector.status.js.map +1 -1
  8. package/build/src/dto/enums/finding.severity.js +1 -0
  9. package/build/src/dto/enums/finding.severity.js.map +1 -1
  10. package/build/src/dto/enums/finding.status.js +1 -0
  11. package/build/src/dto/enums/finding.status.js.map +1 -1
  12. package/build/src/dto/page.dto.d.ts +8 -0
  13. package/build/src/dto/platform/platform.agents.dto.d.ts +2 -2
  14. package/build/src/dto/platform/platform.assets.dto.d.ts +2 -2
  15. package/build/src/dto/platform/platform.connectors.dto.d.ts +2 -2
  16. package/build/src/dto/platform/platform.findings.dto.d.ts +2 -2
  17. package/build/src/dto/platform/platform.metrics.dto.d.ts +2 -2
  18. package/build/src/dto/platform/platform.reportResults.dto.d.ts +2 -2
  19. package/build/src/dto/platform/platform.saasAssets.dto.d.ts +2 -2
  20. package/build/src/dto/platform/platform.saasComponents.dto.d.ts +2 -2
  21. package/build/src/dto/platform/platform.saasUsers.dto.d.ts +1 -1
  22. package/build/src/dto/platform/platform.users.dto.d.ts +2 -2
  23. package/build/src/etag.d.ts +3 -0
  24. package/build/src/etag.js +6 -1
  25. package/build/src/etag.js.map +1 -1
  26. package/build/src/index.d.ts +2 -0
  27. package/build/src/index.js +2 -0
  28. package/build/src/index.js.map +1 -1
  29. package/build/src/services/AmpApi.d.ts +32 -0
  30. package/build/src/services/AmpApi.js +39 -0
  31. package/build/src/services/AmpApi.js.map +1 -0
  32. package/build/src/services/AmpSdk.d.ts +31 -0
  33. package/build/src/services/AmpSdk.js +38 -0
  34. package/build/src/services/AmpSdk.js.map +1 -0
  35. package/build/src/services/data.service.d.ts +23 -0
  36. package/build/src/services/data.service.js +52 -0
  37. package/build/src/services/data.service.js.map +1 -0
  38. package/build/src/services/entity.service.d.ts +34 -0
  39. package/build/src/services/entity.service.js +78 -0
  40. package/build/src/services/entity.service.js.map +1 -0
  41. package/build/src/services/index.d.ts +5 -0
  42. package/build/src/services/index.js +22 -0
  43. package/build/src/services/index.js.map +1 -0
  44. package/build/src/services/rest/RestClient.d.ts +46 -0
  45. package/build/src/services/rest/RestClient.js +106 -0
  46. package/build/src/services/rest/RestClient.js.map +1 -0
  47. package/build/src/services/rest/RestRequest.d.ts +8 -0
  48. package/build/src/services/rest/RestRequest.js +3 -0
  49. package/build/src/services/rest/RestRequest.js.map +1 -0
  50. package/build/src/services/rest/RestResponse.d.ts +7 -0
  51. package/build/src/services/rest/RestResponse.js +3 -0
  52. package/build/src/services/rest/RestResponse.js.map +1 -0
  53. package/build/src/services/rest/index.d.ts +5 -0
  54. package/build/src/services/rest/index.js +22 -0
  55. package/build/src/services/rest/index.js.map +1 -0
  56. package/build/src/services/rest/rateLimit.rest.d.ts +11 -0
  57. package/build/src/services/rest/rateLimit.rest.js +25 -0
  58. package/build/src/services/rest/rateLimit.rest.js.map +1 -0
  59. package/build/src/services/rest/retry.rest.d.ts +7 -0
  60. package/build/src/services/rest/retry.rest.js +18 -0
  61. package/build/src/services/rest/retry.rest.js.map +1 -0
  62. package/build/src/services/rest/utils.d.ts +7 -0
  63. package/build/src/services/rest/utils.js +12 -0
  64. package/build/src/services/rest/utils.js.map +1 -0
  65. package/package.json +7 -3
  66. package/src/FilterCriteria.ts +18 -0
  67. package/src/dto/agents.dto.ts +15 -0
  68. package/src/dto/assets.dto.ts +10 -0
  69. package/src/dto/base.dto.ts +25 -0
  70. package/src/dto/connectors.dto.ts +13 -0
  71. package/src/dto/enums/agent.status.ts +6 -0
  72. package/src/dto/enums/connector.status.ts +7 -0
  73. package/src/dto/enums/finding.severity.ts +7 -0
  74. package/src/dto/enums/finding.status.ts +5 -0
  75. package/src/dto/enums/index.ts +4 -0
  76. package/src/dto/extKeyMap.dto.ts +6 -0
  77. package/src/dto/findings.dto.ts +26 -0
  78. package/src/dto/index.ts +19 -0
  79. package/src/dto/message.dto.ts +3 -0
  80. package/src/dto/metrics.dto.ts +10 -0
  81. package/src/dto/page.dto.ts +14 -0
  82. package/src/dto/platform/index.ts +13 -0
  83. package/src/dto/platform/multi.tenant.based.dto.ts +11 -0
  84. package/src/dto/platform/platform.agents.dto.ts +6 -0
  85. package/src/dto/platform/platform.assets.dto.ts +6 -0
  86. package/src/dto/platform/platform.connectors.dto.ts +6 -0
  87. package/src/dto/platform/platform.findings.dto.ts +6 -0
  88. package/src/dto/platform/platform.metrics.dto.ts +6 -0
  89. package/src/dto/platform/platform.providers.dto.ts +5 -0
  90. package/src/dto/platform/platform.reportResults.dto.ts +6 -0
  91. package/src/dto/platform/platform.saasAssets.dto.ts +5 -0
  92. package/src/dto/platform/platform.saasComponents.dto.ts +6 -0
  93. package/src/dto/platform/platform.saasUsers.dto.ts +6 -0
  94. package/src/dto/platform/platform.tenants.dto.ts +5 -0
  95. package/src/dto/platform/platform.users.dto.ts +6 -0
  96. package/src/dto/platform/tenant.based.dto.ts +11 -0
  97. package/src/dto/providers.dto.ts +8 -0
  98. package/src/dto/reportResults.dto.ts +12 -0
  99. package/src/dto/riskContributors.dto.ts +10 -0
  100. package/src/dto/saasAssets.dto.ts +16 -0
  101. package/src/dto/saasComponents.dto.ts +18 -0
  102. package/src/dto/saasUsers.dto.ts +14 -0
  103. package/src/dto/tenants.dto.ts +8 -0
  104. package/src/dto/users.dto.ts +28 -0
  105. package/src/etag.ts +17 -0
  106. package/src/index.ts +4 -0
  107. package/src/services/AmpApi.ts +66 -0
  108. package/src/services/AmpSdk.ts +72 -0
  109. package/src/services/data.service.ts +69 -0
  110. package/src/services/entity.service.ts +104 -0
  111. package/src/services/index.ts +5 -0
  112. package/src/services/rest/RestClient.ts +103 -0
  113. package/src/services/rest/RestRequest.ts +9 -0
  114. package/src/services/rest/RestResponse.ts +8 -0
  115. package/src/services/rest/index.ts +5 -0
  116. package/src/services/rest/rateLimit.rest.ts +31 -0
  117. package/src/services/rest/retry.rest.ts +21 -0
  118. package/src/services/rest/utils.ts +13 -0
@@ -0,0 +1,6 @@
1
+ import {FindingDto, FindingUpsertDto} from '../findings.dto';
2
+ import {TenantBased, UpsertTenantBased} from './tenant.based.dto';
3
+
4
+ export type PlatformFindingUpsertDto = FindingUpsertDto & UpsertTenantBased;
5
+
6
+ export type PlatformFindingDto = FindingDto & TenantBased;
@@ -0,0 +1,6 @@
1
+ import {MetricDto, MetricUpsertDto} from '../metrics.dto';
2
+ import {TenantBased, UpsertTenantBased} from './tenant.based.dto';
3
+
4
+ export type PlatformMetricUpsertDto = MetricUpsertDto & UpsertTenantBased;
5
+
6
+ export type PlatformMetricDto = MetricDto & TenantBased;
@@ -0,0 +1,5 @@
1
+ import {ProviderDto, ProviderUpsertDto} from '../providers.dto';
2
+
3
+ export type PlatformProviderUpsertDto = ProviderUpsertDto;
4
+
5
+ export type PlatformProviderDto = ProviderDto;
@@ -0,0 +1,6 @@
1
+ import {ReportResultDto, ReportResultUpsertDto} from '../reportResults.dto';
2
+ import {TenantBased, UpsertTenantBased} from './tenant.based.dto';
3
+
4
+ export type PlatformReportResultUpsertDto = ReportResultUpsertDto & UpsertTenantBased;
5
+
6
+ export type PlatformReportResultDto = ReportResultDto & TenantBased;
@@ -0,0 +1,5 @@
1
+ import {SaasAssetDto, SaasAssetUpsertDto} from '../saasAssets.dto';
2
+ import {TenantBased, UpsertTenantBased} from './tenant.based.dto';
3
+
4
+ export type PlatformSaasAssetUpsertDto = SaasAssetUpsertDto & UpsertTenantBased;
5
+ export type PlatformSaasAssetDto = SaasAssetDto & TenantBased;
@@ -0,0 +1,6 @@
1
+ import {SaasComponentDto, SaasComponentUpsertDto} from '../saasComponents.dto';
2
+ import {TenantBased, UpsertTenantBased} from './tenant.based.dto';
3
+
4
+ export type PlatformSaasComponentUpsertDto = SaasComponentUpsertDto & UpsertTenantBased;
5
+
6
+ export type PlatformSaasComponentDto = SaasComponentDto & TenantBased;
@@ -0,0 +1,6 @@
1
+ import {SaasUserUpsertDto} from '../saasUsers.dto';
2
+ import {TenantBased, UpsertTenantBased} from './tenant.based.dto';
3
+
4
+ export type PlatformSaasUserUpsertDto = SaasUserUpsertDto & UpsertTenantBased;
5
+
6
+ export type PlatformSaasUserDto = SaasUserUpsertDto & TenantBased;
@@ -0,0 +1,5 @@
1
+ import {TenantDto, TenantUpsertDto} from '../tenants.dto';
2
+
3
+ export type PlatformTenantUpsertDto = TenantUpsertDto;
4
+
5
+ export type PlatformTenantDto = TenantDto;
@@ -0,0 +1,6 @@
1
+ import {UserDto, UserUpsertDto} from '../users.dto';
2
+ import {TenantBased, UpsertTenantBased} from './tenant.based.dto';
3
+
4
+ export type PlatformUserUpsertDto = UserUpsertDto & UpsertTenantBased;
5
+
6
+ export type PlatformUserDto = UserDto & TenantBased;
@@ -0,0 +1,11 @@
1
+ import {BaseDto, BaseUpsertDto} from '../base.dto';
2
+
3
+ export type UpsertTenantBased = BaseUpsertDto & {
4
+ /** Tenant Id */
5
+ tid?: number;
6
+ };
7
+
8
+ export type TenantBased = BaseDto & {
9
+ /** Tenant Id */
10
+ tid: number;
11
+ };
@@ -0,0 +1,8 @@
1
+ import {BaseDto, BaseUpsertDto} from './base.dto';
2
+
3
+ export type ProviderUpsertDto = BaseUpsertDto & {
4
+ /** Human readable name of the provider */
5
+ displayValue: string;
6
+ };
7
+
8
+ export type ProviderDto = BaseDto & ProviderUpsertDto;
@@ -0,0 +1,12 @@
1
+ import {BaseDto, BaseUpsertDto} from './base.dto';
2
+
3
+ export type ReportResultUpsertDto = BaseUpsertDto & {
4
+ /** External Id */
5
+ extKey: string;
6
+ /** Timestamp the report result was generated in ISO8601 format */
7
+ ts: string;
8
+ /** The results generated for the given report */
9
+ results: unknown;
10
+ };
11
+
12
+ export type ReportResultDto = BaseDto & ReportResultUpsertDto;
@@ -0,0 +1,10 @@
1
+ import {BaseDto, BaseUpsertDto} from './base.dto';
2
+
3
+ export type RiskContributorUpsertDto = BaseUpsertDto & {
4
+ /** Short descriptor of the risk contributor, e.g. V, P, etc... */
5
+ displayValue: string;
6
+ /** Description of the risk contributor */
7
+ description: string;
8
+ };
9
+
10
+ export type RiskContributorDto = BaseDto & RiskContributorUpsertDto;
@@ -0,0 +1,16 @@
1
+ import {ChangeAwareDto, ChangeAwareUpsertDto} from './base.dto';
2
+
3
+ export type SaasAssetUpsertDto = ChangeAwareUpsertDto & {
4
+ /** External Id */
5
+ sn: string;
6
+ /** Connector Id */
7
+ cid: number;
8
+ /** Asset Id */
9
+ aid: number;
10
+ /** User Id */
11
+ uid?: number | undefined;
12
+ /** Information specific to this asset */
13
+ meta: unknown;
14
+ };
15
+
16
+ export type SaasAssetDto = ChangeAwareDto & SaasAssetUpsertDto;
@@ -0,0 +1,18 @@
1
+ import {ChangeAwareDto, ChangeAwareUpsertDto} from './base.dto';
2
+
3
+ export type SaasComponentUpsertDto = ChangeAwareUpsertDto & {
4
+ /** Asset Id */
5
+ aid?: number | undefined;
6
+ /** Connector Id */
7
+ cid: number;
8
+ /** */
9
+ kind: string;
10
+ /** Context specific information related to the Saas Component */
11
+ meta: unknown;
12
+ /** User Id of the affected user */
13
+ uid?: number | undefined;
14
+ /** External Id */
15
+ extKey: string;
16
+ };
17
+
18
+ export type SaasComponentDto = ChangeAwareDto & SaasComponentUpsertDto;
@@ -0,0 +1,14 @@
1
+ import {ChangeAwareDto, ChangeAwareUpsertDto} from './base.dto';
2
+
3
+ export type SaasUserUpsertDto = ChangeAwareUpsertDto & {
4
+ /** User Id */
5
+ uid: number;
6
+ /** Connector Id */
7
+ cid: number;
8
+ /** External Id */
9
+ email: string;
10
+ /** Additional information specific to this Saas User */
11
+ meta: unknown;
12
+ };
13
+
14
+ export type SaasUserDto = ChangeAwareDto & SaasUserUpsertDto;
@@ -0,0 +1,8 @@
1
+ import {BaseDto, BaseUpsertDto} from './base.dto';
2
+
3
+ export type TenantUpsertDto = BaseUpsertDto & {
4
+ /** Human readable name of the tenant */
5
+ displayValue: string;
6
+ };
7
+
8
+ export type TenantDto = BaseDto & TenantUpsertDto;
@@ -0,0 +1,28 @@
1
+ import {ChangeAwareDto, ChangeAwareUpsertDto} from './base.dto';
2
+ import {MetricDto} from './metrics.dto';
3
+ import {RiskContributorDto} from './riskContributors.dto';
4
+
5
+ export type UserUpsertDto = ChangeAwareUpsertDto & {
6
+ /** Tenant ID */
7
+ tid: number;
8
+ /** External ID: list of emails, allows or merging users across email aliases */
9
+ emails: string[];
10
+ /** User first name */
11
+ firstName: string;
12
+ /** User last name */
13
+ lastName: string;
14
+ /** Department to which the user is assigned */
15
+ department?: string;
16
+ /** User title */
17
+ title?: string;
18
+ /** Human readable name of the user's tenant, e.g. tenant.displayName */
19
+ organization?: string;
20
+ /** Employment start date used for calculating tenure */
21
+ startDate?: string;
22
+ /** Risk Contributors associated with the user */
23
+ riskContributors: RiskContributorDto[];
24
+ /** Metrics associated with the user */
25
+ metrics: MetricDto[];
26
+ };
27
+
28
+ export type UserDto = ChangeAwareDto & UserUpsertDto;
package/src/etag.ts ADDED
@@ -0,0 +1,17 @@
1
+ import md5 from 'blueimp-md5';
2
+ import {ChangeAwareDto, ChangeAwareUpsertDto} from './';
3
+
4
+ export function calculateEtag(model: unknown): string {
5
+ const hashObject: {etag?: string} = {...(model as object)};
6
+ delete hashObject.etag;
7
+ return md5(JSON.stringify(hashObject));
8
+ }
9
+
10
+ export function withEtag(model: ChangeAwareDto | ChangeAwareUpsertDto) {
11
+ model.etag = calculateEtag(model);
12
+ }
13
+
14
+ export function createWithEtag<T extends {etag: string}>(model: T): T {
15
+ model.etag = calculateEtag(model);
16
+ return model;
17
+ }
package/src/index.ts ADDED
@@ -0,0 +1,4 @@
1
+ export * from './dto';
2
+ export * from './etag';
3
+ export * from './services';
4
+ export * from './FilterCriteria';
@@ -0,0 +1,66 @@
1
+ import {
2
+ AgentDto,
3
+ AgentUpsertDto,
4
+ AssetDto,
5
+ ConnectorDto,
6
+ ConnectorUpsertDto,
7
+ FindingDto,
8
+ ProviderDto,
9
+ ReportResultDto,
10
+ SaasAssetDto,
11
+ SaasComponentDto,
12
+ SaasUserDto,
13
+ TenantDto,
14
+ TenantUpsertDto,
15
+ UserDto,
16
+ } from '../dto';
17
+ import {AmpEntityService, AmpEntityServiceImpl} from './entity.service';
18
+ import {AmpDataService, AmpDataServiceImpl} from './data.service';
19
+ import {AmpRestClientOptions, RestClient, getAmpRestClient} from './rest';
20
+
21
+ export type AmpApiOptions = AmpRestClientOptions;
22
+
23
+ /**
24
+ * AMP API
25
+ * This client is a wrapper around the AMP REST API meant to be used by
26
+ * agents, i.e. Amplifier Security's customers. If you are trying to implement
27
+ * a plugin leverage the AmpSdk instead (see {@link AmpSdkServices} ).
28
+ *
29
+ * This client provides READ_ONLY access to most of the AMP API. You will
30
+ * have write access to the following resources:
31
+ * - Agents: {@link AmpApi.agents}
32
+ * - Connectors: {@link AmpApi.connectors}
33
+ * - Tenants: {@link AmpApi.tenants}
34
+ */
35
+ export class AmpApi {
36
+ readonly agents: AmpEntityService<AgentUpsertDto, AgentDto>;
37
+ readonly asset: AmpDataService<AssetDto>;
38
+ readonly connectors: AmpEntityService<ConnectorUpsertDto, ConnectorDto>;
39
+ readonly findings: AmpDataService<FindingDto>;
40
+ readonly providers: AmpDataService<ProviderDto>;
41
+ readonly reports: AmpDataService<ReportResultDto>;
42
+ readonly saasAssets: AmpDataService<SaasAssetDto>;
43
+ readonly saasComponents: AmpDataService<SaasComponentDto>;
44
+ readonly saasUsers: AmpDataService<SaasUserDto>;
45
+ readonly tenants: AmpEntityService<TenantUpsertDto, TenantDto>;
46
+ readonly users: AmpDataService<UserDto>;
47
+
48
+ constructor(rest: RestClient) {
49
+ this.agents = new AmpEntityServiceImpl<AgentUpsertDto, AgentDto>(rest, 'agents');
50
+ this.asset = new AmpDataServiceImpl<AssetDto>(rest, 'assets');
51
+ this.connectors = new AmpEntityServiceImpl<ConnectorUpsertDto, ConnectorDto>(rest, 'connectors');
52
+ this.findings = new AmpDataServiceImpl<FindingDto>(rest, 'findings');
53
+ this.providers = new AmpDataServiceImpl<ProviderDto>(rest, 'providers');
54
+ this.reports = new AmpDataServiceImpl<ReportResultDto>(rest, 'report_results');
55
+ this.saasAssets = new AmpDataServiceImpl<SaasAssetDto>(rest, 'saas_assets');
56
+ this.saasComponents = new AmpDataServiceImpl<SaasComponentDto>(rest, 'saas_components');
57
+ this.saasUsers = new AmpDataServiceImpl<SaasUserDto>(rest, 'saas_users');
58
+ this.tenants = new AmpEntityServiceImpl<TenantUpsertDto, TenantDto>(rest, 'agents');
59
+ this.users = new AmpDataServiceImpl<UserDto>(rest, 'users');
60
+ }
61
+
62
+ static instance(options: AmpApiOptions): AmpApi {
63
+ const rest = getAmpRestClient(options);
64
+ return new AmpApi(rest);
65
+ }
66
+ }
@@ -0,0 +1,72 @@
1
+ import {
2
+ ConnectorDto,
3
+ ConnectorUpsertDto,
4
+ PlatformAgentDto,
5
+ PlatformAgentUpsertDto,
6
+ PlatformAssetDto,
7
+ PlatformAssetUpsertDto,
8
+ PlatformFindingDto,
9
+ PlatformFindingUpsertDto,
10
+ PlatformReportResultDto,
11
+ PlatformReportResultUpsertDto,
12
+ PlatformSaasAssetDto,
13
+ PlatformSaasAssetUpsertDto,
14
+ PlatformSaasComponentDto,
15
+ PlatformSaasComponentUpsertDto,
16
+ PlatformSaasUserDto,
17
+ PlatformSaasUserUpsertDto,
18
+ PlatformUserDto,
19
+ PlatformUserUpsertDto,
20
+ ProviderDto,
21
+ TenantDto,
22
+ TenantUpsertDto,
23
+ } from '../dto';
24
+ import {AmpEntityService, AmpEntityServiceImpl, AmpGlobalEntityService, AmpGlobalEntityServiceImpl, AmpSaaSEntityService, AmpSaaSEntityServiceImpl} from './entity.service';
25
+ import {AmpDataService, AmpDataServiceImpl, TARGET_API_AGENT, TARGET_API_PLATFORM} from './data.service';
26
+ import {AmpRestClientOptions, RestClient, getAmpRestClient} from './rest';
27
+
28
+ export type AmpSdkOptions = AmpRestClientOptions;
29
+
30
+ /**
31
+ * AMP API
32
+ * This client is a wrapper around the AMP REST API meant to be used by
33
+ * service accounts, i.e. plugins and platform extensions. If you are
34
+ * trying to implement a simple web client you should leverage the AmpApi
35
+ * instead (see {@link AmpApi} ).
36
+ *
37
+ * This client provides CRUD access to most of the AMP API. You
38
+ * have READ_ONLY access to the following resources:
39
+ * - providers: {@link AmpSdkServices.providers}
40
+ */
41
+ export class AmpSdkServices {
42
+ readonly agents: AmpEntityService<PlatformAgentUpsertDto, PlatformAgentDto>;
43
+ readonly asset: AmpGlobalEntityService<PlatformAssetUpsertDto, PlatformAssetDto>;
44
+ readonly connectors: AmpEntityService<ConnectorUpsertDto, ConnectorDto>;
45
+ readonly findings: AmpSaaSEntityService<PlatformFindingUpsertDto, PlatformFindingDto>;
46
+ readonly providers: AmpDataService<ProviderDto>;
47
+ readonly reports: AmpSaaSEntityService<PlatformReportResultUpsertDto, PlatformReportResultDto>;
48
+ readonly saasAssets: AmpSaaSEntityService<PlatformSaasAssetUpsertDto, PlatformSaasAssetDto>;
49
+ readonly saasComponents: AmpSaaSEntityService<PlatformSaasComponentUpsertDto, PlatformSaasComponentDto>;
50
+ readonly saasUsers: AmpSaaSEntityService<PlatformSaasUserUpsertDto, PlatformSaasUserDto>;
51
+ readonly tenants: AmpEntityService<TenantUpsertDto, TenantDto>;
52
+ readonly users: AmpGlobalEntityService<PlatformUserUpsertDto, PlatformUserDto>;
53
+
54
+ constructor(rest: RestClient) {
55
+ this.agents = new AmpEntityServiceImpl<PlatformAgentUpsertDto, PlatformAgentDto>(rest, 'agents', TARGET_API_PLATFORM);
56
+ this.asset = new AmpGlobalEntityServiceImpl<PlatformAssetUpsertDto, PlatformAssetDto>(rest, 'assets', TARGET_API_PLATFORM);
57
+ this.connectors = new AmpEntityServiceImpl<ConnectorUpsertDto, ConnectorDto>(rest, 'connectors', TARGET_API_PLATFORM);
58
+ this.findings = new AmpSaaSEntityServiceImpl<PlatformFindingUpsertDto, PlatformFindingDto>(rest, 'findings', TARGET_API_PLATFORM);
59
+ this.providers = new AmpDataServiceImpl<ProviderDto>(rest, 'providers', TARGET_API_AGENT);
60
+ this.reports = new AmpSaaSEntityServiceImpl<PlatformReportResultUpsertDto, PlatformReportResultDto>(rest, 'report_results', TARGET_API_PLATFORM);
61
+ this.saasAssets = new AmpSaaSEntityServiceImpl<PlatformSaasAssetUpsertDto, PlatformSaasAssetDto>(rest, 'saas_assets', TARGET_API_PLATFORM);
62
+ this.saasComponents = new AmpSaaSEntityServiceImpl<PlatformSaasComponentUpsertDto, PlatformSaasComponentDto>(rest, 'saas_components', TARGET_API_PLATFORM);
63
+ this.saasUsers = new AmpSaaSEntityServiceImpl<PlatformSaasUserUpsertDto, PlatformSaasUserDto>(rest, 'saas_users', TARGET_API_PLATFORM);
64
+ this.tenants = new AmpEntityServiceImpl<TenantUpsertDto, TenantDto>(rest, 'tenants', TARGET_API_PLATFORM);
65
+ this.users = new AmpGlobalEntityServiceImpl<PlatformUserUpsertDto, PlatformUserDto>(rest, 'users', TARGET_API_PLATFORM);
66
+ }
67
+
68
+ static instance(options: AmpSdkOptions): AmpSdkServices {
69
+ const rest = getAmpRestClient(options);
70
+ return new AmpSdkServices(rest);
71
+ }
72
+ }
@@ -0,0 +1,69 @@
1
+ import {BaseDto, Page} from '../dto';
2
+ import {FilterCriteria} from '../FilterCriteria';
3
+ import {RestClient, RestRequest} from './rest';
4
+
5
+ export interface AmpDataService<ReadT extends BaseDto> {
6
+ list(_filter: FilterCriteria): Promise<Page<ReadT>>;
7
+ getById(_id: number): Promise<Page<ReadT>>;
8
+ }
9
+
10
+ export interface ErrorHandler<T> {
11
+ (_error: unknown): T;
12
+ }
13
+
14
+ export type TargetApi = 'api' | 'platform';
15
+ export const TARGET_API_PLATFORM: TargetApi = 'platform';
16
+ export const TARGET_API_AGENT: TargetApi = 'api';
17
+
18
+ export class AmpDataServiceImpl<ReadT extends BaseDto> implements AmpDataService<ReadT> {
19
+ protected readonly rest: RestClient;
20
+ protected readonly kind: string;
21
+ protected readonly targetApi: string;
22
+
23
+ constructor(rest: RestClient, kind: string, targetApi: TargetApi = 'api') {
24
+ this.rest = rest;
25
+ this.kind = kind;
26
+ this.targetApi = targetApi;
27
+ }
28
+
29
+ protected async call<T>(req: RestRequest, errorHandler: ErrorHandler<T>): Promise<T> {
30
+ try {
31
+ const res = await this.rest.call(req);
32
+ return res.data as T;
33
+ } catch (error: unknown) {
34
+ if (error instanceof Error) {
35
+ console.error(error.message);
36
+ }
37
+ return errorHandler(error);
38
+ }
39
+ }
40
+
41
+ protected async getPage(req: RestRequest): Promise<Page<ReadT>> {
42
+ return this.call(req, (error: unknown) => {
43
+ if (error instanceof Error) {
44
+ console.error(error.message);
45
+ }
46
+ return {
47
+ data: [],
48
+ kind: this.kind.toUpperCase(),
49
+ error: (error as {message: string}).message,
50
+ hints: {},
51
+ };
52
+ });
53
+ }
54
+
55
+ list(filter: FilterCriteria): Promise<Page<ReadT>> {
56
+ return this.getPage({
57
+ url: `/${this.targetApi}/v1/${this.kind}`,
58
+ method: 'GET',
59
+ params: filter,
60
+ });
61
+ }
62
+
63
+ getById(id: number): Promise<Page<ReadT>> {
64
+ return this.getPage({
65
+ url: `/${this.targetApi}/v1/${this.kind}/${id}`,
66
+ method: 'GET',
67
+ });
68
+ }
69
+ }
@@ -0,0 +1,104 @@
1
+ import {BaseDto, BaseUpsertDto, ExtKeyMap, Page} from '../dto';
2
+ import {AmpDataService, AmpDataServiceImpl, ErrorHandler, TARGET_API_AGENT, TargetApi} from './data.service';
3
+ import {RestClient, RestRequest} from './rest';
4
+
5
+ export interface AmpEntityService<WriteT extends BaseUpsertDto, ReadT extends BaseDto> extends AmpDataService<ReadT> {
6
+ create(_model: WriteT): Promise<Page<ReadT>>;
7
+ update(_model: WriteT): Promise<Page<ReadT>>;
8
+ delete(_id: number): Promise<Page<ReadT>>;
9
+ }
10
+ export interface AmpGlobalEntityService<WriteT extends BaseUpsertDto, ReadT extends BaseDto> extends AmpDataService<ReadT> {
11
+ create(_model: WriteT): Promise<Page<ReadT>>;
12
+ update(_model: WriteT): Promise<Page<ReadT>>;
13
+ delete(_id: number): Promise<Page<ReadT>>;
14
+ getLookupIds(_tid: number): Promise<ExtKeyMap>;
15
+ }
16
+ export interface AmpSaaSEntityService<WriteT extends BaseUpsertDto, ReadT extends BaseDto> extends AmpDataService<ReadT> {
17
+ create(_model: WriteT): Promise<Page<ReadT>>;
18
+ update(_model: WriteT): Promise<Page<ReadT>>;
19
+ delete(_id: number): Promise<Page<ReadT>>;
20
+ getLookupIds(_cid: number): Promise<ExtKeyMap>;
21
+ }
22
+
23
+ export class AmpEntityServiceImpl<WriteT extends BaseUpsertDto, ReadT extends BaseDto> extends AmpDataServiceImpl<ReadT> implements AmpEntityService<WriteT, ReadT> {
24
+ constructor(rest: RestClient, kind: string, targetApi: TargetApi = TARGET_API_AGENT) {
25
+ super(rest, kind, targetApi);
26
+ }
27
+
28
+ create(model: WriteT): Promise<Page<ReadT>> {
29
+ return this.getPage({
30
+ url: `/${this.targetApi}/v1/${this.kind}`,
31
+ method: 'POST',
32
+ data: model,
33
+ });
34
+ }
35
+
36
+ update(model: WriteT): Promise<Page<ReadT>> {
37
+ return this.getPage({
38
+ url: `/${this.targetApi}/v1/${this.kind}/${model.id}`,
39
+ method: 'PUT',
40
+ data: model,
41
+ });
42
+ }
43
+
44
+ async delete(id: number): Promise<Page<ReadT>> {
45
+ const res = await this.getById(id);
46
+ if (res.data.length === 1) {
47
+ const req: RestRequest = {
48
+ url: `/${this.targetApi}/v1/${this.kind}/${id}`,
49
+ method: 'DELETE',
50
+ };
51
+ const {error} = await this.call(req, (error: unknown) => {
52
+ if (error instanceof Error) {
53
+ console.error(error.message);
54
+ }
55
+ return {success: false, error};
56
+ });
57
+ if (error) {
58
+ throw new Error(`Failed to delete ${this.kind} with id="${id}"`);
59
+ }
60
+ }
61
+ return res;
62
+ }
63
+ }
64
+
65
+ const extIdMapErrorHandler: ErrorHandler<ExtKeyMap> = (error: unknown) => {
66
+ if (error instanceof Error) {
67
+ console.error(error.message);
68
+ }
69
+ return {};
70
+ };
71
+
72
+ export class AmpGlobalEntityServiceImpl<WriteT extends BaseUpsertDto, ReadT extends BaseDto>
73
+ extends AmpEntityServiceImpl<WriteT, ReadT>
74
+ implements AmpGlobalEntityService<WriteT, ReadT>
75
+ {
76
+ constructor(rest: RestClient, kind: string, targetApi: TargetApi = TARGET_API_AGENT) {
77
+ super(rest, kind, targetApi);
78
+ }
79
+ getLookupIds(tid: number): Promise<ExtKeyMap> {
80
+ const req: RestRequest = {
81
+ url: `/${this.targetApi}/v1/${this.kind}/ext_key_map`,
82
+ method: 'GET',
83
+ params: {tid},
84
+ };
85
+ return this.call(req, extIdMapErrorHandler);
86
+ }
87
+ }
88
+
89
+ export class AmpSaaSEntityServiceImpl<WriteT extends BaseUpsertDto, ReadT extends BaseDto>
90
+ extends AmpEntityServiceImpl<WriteT, ReadT>
91
+ implements AmpSaaSEntityService<WriteT, ReadT>
92
+ {
93
+ constructor(rest: RestClient, kind: string, targetApi: TargetApi = TARGET_API_AGENT) {
94
+ super(rest, kind, targetApi);
95
+ }
96
+ getLookupIds(cid: number): Promise<ExtKeyMap> {
97
+ const req: RestRequest = {
98
+ url: `/${this.targetApi}/v1/${this.kind}/ext_key_map`,
99
+ method: 'GET',
100
+ params: {cid},
101
+ };
102
+ return this.call(req, extIdMapErrorHandler);
103
+ }
104
+ }
@@ -0,0 +1,5 @@
1
+ export * from './AmpApi';
2
+ export * from './AmpSdk';
3
+ export * from './data.service';
4
+ export * from './entity.service';
5
+ export * from './rest';
@@ -0,0 +1,103 @@
1
+ import _ from 'lodash';
2
+ import axios, {Axios, AxiosError, AxiosStatic} from 'axios';
3
+ import {RestRequest} from './RestRequest';
4
+ import {RestResponse} from './RestResponse';
5
+ import {RestClientRetryStrategy, noopRestRetryStrategy} from './retry.rest';
6
+ import {HeadersMap, convertHeaders} from './utils';
7
+ import {RestClientRateLimitStrategy, StaticRestClientRateLimitStrategy, noopRestClientRateLimitStrategy} from './rateLimit.rest';
8
+
9
+ export type AmpRestClientOptions = {
10
+ baseUrl: string;
11
+ token: string;
12
+ timeout?: number;
13
+ retryStrategy?: RestClientRetryStrategy;
14
+ rateLimitStrategy?: RestClientRateLimitStrategy;
15
+ verbose?: boolean;
16
+ client?: AxiosStatic;
17
+ };
18
+
19
+ export type RestClientOptions = {
20
+ baseUrl?: string;
21
+ headers?: HeadersMap;
22
+ timeout?: number;
23
+ retryStrategy?: RestClientRetryStrategy;
24
+ rateLimitStrategy?: RestClientRateLimitStrategy;
25
+ verbose?: boolean;
26
+ client?: AxiosStatic;
27
+ };
28
+
29
+ /**
30
+ * RestClient is a generic interface for making REST calls.
31
+ */
32
+ export interface RestClient {
33
+ call(_request: RestRequest): Promise<RestResponse>;
34
+ }
35
+
36
+ /**
37
+ * DefaultRestClient is a default implementation of RestClient.
38
+ * It defaults to useing axios to make REST calls and adds reasonble defaults
39
+ * for retry logic, error handling, headers, and timeouts.
40
+ *
41
+ * These strategies can be useful when scraping 3rd party APIs.
42
+ */
43
+ export class DefaultRestClient {
44
+ protected readonly ampAxios: Axios;
45
+ protected readonly retryStrategy: RestClientRetryStrategy;
46
+ protected readonly rateLimitStrategy: RestClientRateLimitStrategy;
47
+ protected readonly verbose: boolean;
48
+ constructor(options: RestClientOptions = {}) {
49
+ // TODO: rest client
50
+ const client = options.client ?? axios;
51
+ this.ampAxios = client.create({
52
+ baseURL: options.baseUrl,
53
+ timeout: options.timeout,
54
+ });
55
+ Object.keys(options.headers ?? {}).forEach(key => {
56
+ this.ampAxios.defaults.headers.common[key] = options.headers?.[key];
57
+ });
58
+ this.verbose = options.verbose ?? false;
59
+ this.ampAxios.defaults.headers.common['Accepts'] = 'application/json';
60
+ this.ampAxios.defaults.headers.post['Content-Type'] = 'application/json';
61
+ this.ampAxios.defaults.headers.put['Content-Type'] = 'application/json';
62
+ this.retryStrategy = options.retryStrategy ?? noopRestRetryStrategy;
63
+ this.rateLimitStrategy = options.rateLimitStrategy ?? noopRestClientRateLimitStrategy;
64
+ }
65
+ async call(request: RestRequest): Promise<RestResponse> {
66
+ const req = _.merge(request);
67
+ try {
68
+ await this.rateLimitStrategy.reserve(req);
69
+ if (this.verbose) console.log('Request', req);
70
+ const res = await this.ampAxios.request(req);
71
+ return {
72
+ status: res.status,
73
+ headers: convertHeaders(res),
74
+ data: res.data,
75
+ error: null,
76
+ };
77
+ } catch (err: unknown) {
78
+ if (err instanceof AxiosError) {
79
+ const axiosError = err as AxiosError;
80
+ return {
81
+ status: axiosError.response?.status ?? 500,
82
+ headers: axiosError.response ? convertHeaders(axiosError.response) : {},
83
+ data: null,
84
+ error: err,
85
+ };
86
+ }
87
+ throw err;
88
+ }
89
+ }
90
+ }
91
+
92
+ export const getAmpRestClient = (options: AmpRestClientOptions): RestClient => {
93
+ const ampClient = new DefaultRestClient({
94
+ baseUrl: options.baseUrl,
95
+ headers: {
96
+ Authorization: `Bearer ${options.token}`,
97
+ },
98
+ rateLimitStrategy: new StaticRestClientRateLimitStrategy(50),
99
+ verbose: options.verbose ?? false,
100
+ client: options.client,
101
+ });
102
+ return ampClient;
103
+ };
@@ -0,0 +1,9 @@
1
+ import {HeadersMap, QueryMap} from './utils';
2
+
3
+ export type RestRequest = {
4
+ url: string;
5
+ headers?: HeadersMap;
6
+ params?: QueryMap;
7
+ data?: unknown;
8
+ method?: 'GET' | 'POST' | 'PUT' | 'DELETE';
9
+ };