buildhive-agent 1.0.0-beta.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.
- package/README.md +166 -0
- package/dist/__tests__/fakes/FakeDockerManager.d.ts +115 -0
- package/dist/__tests__/fakes/FakeDockerManager.d.ts.map +1 -0
- package/dist/__tests__/fakes/FakeDockerManager.js +203 -0
- package/dist/__tests__/fakes/FakeDockerManager.js.map +1 -0
- package/dist/acceptanceChecker.d.ts +26 -0
- package/dist/acceptanceChecker.d.ts.map +1 -0
- package/dist/acceptanceChecker.js +64 -0
- package/dist/acceptanceChecker.js.map +1 -0
- package/dist/advancedAgent.d.ts +161 -0
- package/dist/advancedAgent.d.ts.map +1 -0
- package/dist/advancedAgent.js +604 -0
- package/dist/advancedAgent.js.map +1 -0
- package/dist/agent.d.ts +101 -0
- package/dist/agent.d.ts.map +1 -0
- package/dist/agent.js +490 -0
- package/dist/agent.js.map +1 -0
- package/dist/api/jobStatusApi.d.ts +88 -0
- package/dist/api/jobStatusApi.d.ts.map +1 -0
- package/dist/api/jobStatusApi.js +240 -0
- package/dist/api/jobStatusApi.js.map +1 -0
- package/dist/autoUpdater.d.ts +135 -0
- package/dist/autoUpdater.d.ts.map +1 -0
- package/dist/autoUpdater.js +494 -0
- package/dist/autoUpdater.js.map +1 -0
- package/dist/cacheManager.d.ts +108 -0
- package/dist/cacheManager.d.ts.map +1 -0
- package/dist/cacheManager.js +300 -0
- package/dist/cacheManager.js.map +1 -0
- package/dist/cli.d.ts +11 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +749 -0
- package/dist/cli.js.map +1 -0
- package/dist/config/index.d.ts +30 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +35 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/loader.d.ts +45 -0
- package/dist/config/loader.d.ts.map +1 -0
- package/dist/config/loader.js +269 -0
- package/dist/config/loader.js.map +1 -0
- package/dist/config/types.d.ts +193 -0
- package/dist/config/types.d.ts.map +1 -0
- package/dist/config/types.js +90 -0
- package/dist/config/types.js.map +1 -0
- package/dist/config/validation.d.ts +28 -0
- package/dist/config/validation.d.ts.map +1 -0
- package/dist/config/validation.js +397 -0
- package/dist/config/validation.js.map +1 -0
- package/dist/docker.d.ts +96 -0
- package/dist/docker.d.ts.map +1 -0
- package/dist/docker.js +411 -0
- package/dist/docker.js.map +1 -0
- package/dist/enhancedJobExecutor.d.ts +81 -0
- package/dist/enhancedJobExecutor.d.ts.map +1 -0
- package/dist/enhancedJobExecutor.js +223 -0
- package/dist/enhancedJobExecutor.js.map +1 -0
- package/dist/executors/executorFactory.d.ts +46 -0
- package/dist/executors/executorFactory.d.ts.map +1 -0
- package/dist/executors/executorFactory.js +80 -0
- package/dist/executors/executorFactory.js.map +1 -0
- package/dist/executors/index.d.ts +7 -0
- package/dist/executors/index.d.ts.map +1 -0
- package/dist/executors/index.js +6 -0
- package/dist/executors/index.js.map +1 -0
- package/dist/executors/nativeExecutor.d.ts +60 -0
- package/dist/executors/nativeExecutor.d.ts.map +1 -0
- package/dist/executors/nativeExecutor.js +311 -0
- package/dist/executors/nativeExecutor.js.map +1 -0
- package/dist/executors/types.d.ts +38 -0
- package/dist/executors/types.d.ts.map +1 -0
- package/dist/executors/types.js +9 -0
- package/dist/executors/types.js.map +1 -0
- package/dist/healthMonitor.d.ts +213 -0
- package/dist/healthMonitor.d.ts.map +1 -0
- package/dist/healthMonitor.js +547 -0
- package/dist/healthMonitor.js.map +1 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +16 -0
- package/dist/index.js.map +1 -0
- package/dist/jobExecutor.d.ts +117 -0
- package/dist/jobExecutor.d.ts.map +1 -0
- package/dist/jobExecutor.js +458 -0
- package/dist/jobExecutor.js.map +1 -0
- package/dist/lifecycleExecutor.d.ts +54 -0
- package/dist/lifecycleExecutor.d.ts.map +1 -0
- package/dist/lifecycleExecutor.js +230 -0
- package/dist/lifecycleExecutor.js.map +1 -0
- package/dist/main.d.ts +15 -0
- package/dist/main.d.ts.map +1 -0
- package/dist/main.js +77 -0
- package/dist/main.js.map +1 -0
- package/dist/metrics.d.ts +103 -0
- package/dist/metrics.d.ts.map +1 -0
- package/dist/metrics.js +360 -0
- package/dist/metrics.js.map +1 -0
- package/dist/recipes/builtinRecipes.d.ts +11 -0
- package/dist/recipes/builtinRecipes.d.ts.map +1 -0
- package/dist/recipes/builtinRecipes.js +688 -0
- package/dist/recipes/builtinRecipes.js.map +1 -0
- package/dist/recipes/index.d.ts +18 -0
- package/dist/recipes/index.d.ts.map +1 -0
- package/dist/recipes/index.js +17 -0
- package/dist/recipes/index.js.map +1 -0
- package/dist/recipes/recipeRegistry.d.ts +49 -0
- package/dist/recipes/recipeRegistry.d.ts.map +1 -0
- package/dist/recipes/recipeRegistry.js +264 -0
- package/dist/recipes/recipeRegistry.js.map +1 -0
- package/dist/recipes/types.d.ts +116 -0
- package/dist/recipes/types.d.ts.map +1 -0
- package/dist/recipes/types.js +10 -0
- package/dist/recipes/types.js.map +1 -0
- package/dist/recovery.d.ts +133 -0
- package/dist/recovery.d.ts.map +1 -0
- package/dist/recovery.js +299 -0
- package/dist/recovery.js.map +1 -0
- package/dist/registration/apiClient.d.ts +44 -0
- package/dist/registration/apiClient.d.ts.map +1 -0
- package/dist/registration/apiClient.js +149 -0
- package/dist/registration/apiClient.js.map +1 -0
- package/dist/registration/index.d.ts +41 -0
- package/dist/registration/index.d.ts.map +1 -0
- package/dist/registration/index.js +141 -0
- package/dist/registration/index.js.map +1 -0
- package/dist/registration/machineId.d.ts +30 -0
- package/dist/registration/machineId.d.ts.map +1 -0
- package/dist/registration/machineId.js +89 -0
- package/dist/registration/machineId.js.map +1 -0
- package/dist/registration/types.d.ts +32 -0
- package/dist/registration/types.d.ts.map +1 -0
- package/dist/registration/types.js +9 -0
- package/dist/registration/types.js.map +1 -0
- package/dist/resourceGovernor.d.ts +57 -0
- package/dist/resourceGovernor.d.ts.map +1 -0
- package/dist/resourceGovernor.js +125 -0
- package/dist/resourceGovernor.js.map +1 -0
- package/dist/security/secretManager.d.ts +107 -0
- package/dist/security/secretManager.d.ts.map +1 -0
- package/dist/security/secretManager.js +361 -0
- package/dist/security/secretManager.js.map +1 -0
- package/dist/security.d.ts +134 -0
- package/dist/security.d.ts.map +1 -0
- package/dist/security.js +470 -0
- package/dist/security.js.map +1 -0
- package/dist/storage/artifactUploader.d.ts +155 -0
- package/dist/storage/artifactUploader.d.ts.map +1 -0
- package/dist/storage/artifactUploader.js +554 -0
- package/dist/storage/artifactUploader.js.map +1 -0
- package/dist/types.d.ts +49 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +7 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/capabilities.d.ts +23 -0
- package/dist/utils/capabilities.d.ts.map +1 -0
- package/dist/utils/capabilities.js +200 -0
- package/dist/utils/capabilities.js.map +1 -0
- package/dist/utils/logger.d.ts +20 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +188 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/sdkScanner.d.ts +105 -0
- package/dist/utils/sdkScanner.d.ts.map +1 -0
- package/dist/utils/sdkScanner.js +459 -0
- package/dist/utils/sdkScanner.js.map +1 -0
- package/dist/websocketClient.d.ts +154 -0
- package/dist/websocketClient.d.ts.map +1 -0
- package/dist/websocketClient.js +422 -0
- package/dist/websocketClient.js.map +1 -0
- package/package.json +64 -0
package/dist/security.js
ADDED
|
@@ -0,0 +1,470 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Security Manager - Enhanced Docker security configuration and validation
|
|
3
|
+
*
|
|
4
|
+
* Provides comprehensive security measures for container execution including
|
|
5
|
+
* resource limits, network isolation, filesystem security, and monitoring.
|
|
6
|
+
*
|
|
7
|
+
* Requirements: 4.1, 4.2, 4.3, 4.4, 4.5
|
|
8
|
+
*/
|
|
9
|
+
import { createLogger } from './utils/logger.js';
|
|
10
|
+
import { promises as fs } from 'fs';
|
|
11
|
+
import { join, resolve } from 'path';
|
|
12
|
+
import { spawn } from 'child_process';
|
|
13
|
+
const logger = createLogger('security');
|
|
14
|
+
export class SecurityManager {
|
|
15
|
+
config;
|
|
16
|
+
violations = [];
|
|
17
|
+
resourceMonitors = new Map();
|
|
18
|
+
constructor(config) {
|
|
19
|
+
this.config = config;
|
|
20
|
+
logger.info('Security manager initialized with enhanced configuration');
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Generate secure Docker arguments for container creation
|
|
24
|
+
*/
|
|
25
|
+
generateSecureDockerArgs(containerId) {
|
|
26
|
+
const args = [];
|
|
27
|
+
// Basic security settings
|
|
28
|
+
args.push('--security-opt', 'no-new-privileges:true');
|
|
29
|
+
// Drop all capabilities by default
|
|
30
|
+
if (this.config.dropAllCapabilities) {
|
|
31
|
+
args.push('--cap-drop', 'ALL');
|
|
32
|
+
// Add only explicitly allowed capabilities
|
|
33
|
+
for (const cap of this.config.allowedCapabilities) {
|
|
34
|
+
args.push('--cap-add', cap);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
// Network isolation
|
|
38
|
+
args.push('--network', this.config.networkMode);
|
|
39
|
+
if (this.config.networkMode === 'none') {
|
|
40
|
+
logger.info(`Container ${containerId} will have no network access`);
|
|
41
|
+
}
|
|
42
|
+
// Resource limits
|
|
43
|
+
args.push('--memory', `${this.config.maxMemoryMB}m`);
|
|
44
|
+
args.push('--cpus', this.config.maxCpuCores.toString());
|
|
45
|
+
args.push('--pids-limit', this.config.maxProcesses.toString());
|
|
46
|
+
args.push('--ulimit', `nofile=${this.config.maxFileDescriptors}:${this.config.maxFileDescriptors}`);
|
|
47
|
+
// Filesystem security
|
|
48
|
+
if (this.config.readOnlyRoot) {
|
|
49
|
+
args.push('--read-only');
|
|
50
|
+
// Create secure temporary directories
|
|
51
|
+
args.push('--tmpfs', `/tmp:rw,noexec,nosuid,nodev,size=${this.config.tempDirSizeMB}m`);
|
|
52
|
+
args.push('--tmpfs', `/var/tmp:rw,noexec,nosuid,nodev,size=${this.config.tempDirSizeMB}m`);
|
|
53
|
+
// Add writable paths as tmpfs mounts
|
|
54
|
+
for (const writePath of this.config.allowedWritePaths) {
|
|
55
|
+
args.push('--tmpfs', `${writePath}:rw,noexec,nosuid,nodev,size=100m`);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
// Security profiles
|
|
59
|
+
if (this.config.seccompProfile) {
|
|
60
|
+
args.push('--security-opt', `seccomp=${this.config.seccompProfile}`);
|
|
61
|
+
}
|
|
62
|
+
if (this.config.apparmorProfile) {
|
|
63
|
+
args.push('--security-opt', `apparmor=${this.config.apparmorProfile}`);
|
|
64
|
+
}
|
|
65
|
+
// Additional hardening
|
|
66
|
+
args.push('--security-opt', 'no-new-privileges:true');
|
|
67
|
+
args.push('--user', '1000:1000'); // Run as non-root user
|
|
68
|
+
args.push('--init'); // Use proper init system
|
|
69
|
+
logger.info(`Generated ${args.length / 2} security arguments for container ${containerId}`);
|
|
70
|
+
return args;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Validate container configuration against security policies
|
|
74
|
+
*/
|
|
75
|
+
async validateContainerConfig(config) {
|
|
76
|
+
const violations = [];
|
|
77
|
+
// Check resource limits
|
|
78
|
+
if (config.memoryLimit && this.parseMemoryLimit(config.memoryLimit) > this.config.maxMemoryMB) {
|
|
79
|
+
violations.push({
|
|
80
|
+
type: 'resource',
|
|
81
|
+
severity: 'high',
|
|
82
|
+
message: `Memory limit ${config.memoryLimit} exceeds maximum allowed ${this.config.maxMemoryMB}MB`,
|
|
83
|
+
containerId: config.containerId || 'unknown',
|
|
84
|
+
timestamp: new Date()
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
// Check CPU limits
|
|
88
|
+
if (config.cpuLimit && parseFloat(config.cpuLimit) > this.config.maxCpuCores) {
|
|
89
|
+
violations.push({
|
|
90
|
+
type: 'resource',
|
|
91
|
+
severity: 'high',
|
|
92
|
+
message: `CPU limit ${config.cpuLimit} exceeds maximum allowed ${this.config.maxCpuCores}`,
|
|
93
|
+
containerId: config.containerId || 'unknown',
|
|
94
|
+
timestamp: new Date()
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
// Check network configuration
|
|
98
|
+
if (config.networkMode && config.networkMode !== this.config.networkMode) {
|
|
99
|
+
violations.push({
|
|
100
|
+
type: 'network',
|
|
101
|
+
severity: 'critical',
|
|
102
|
+
message: `Network mode ${config.networkMode} not allowed, must use ${this.config.networkMode}`,
|
|
103
|
+
containerId: config.containerId || 'unknown',
|
|
104
|
+
timestamp: new Date()
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
// Check for privileged mode
|
|
108
|
+
if (config.privileged) {
|
|
109
|
+
violations.push({
|
|
110
|
+
type: 'capability',
|
|
111
|
+
severity: 'critical',
|
|
112
|
+
message: 'Privileged mode is not allowed',
|
|
113
|
+
containerId: config.containerId || 'unknown',
|
|
114
|
+
timestamp: new Date()
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
// Check volume mounts for security risks
|
|
118
|
+
if (config.volumeMounts) {
|
|
119
|
+
for (const mount of config.volumeMounts) {
|
|
120
|
+
if (this.isUnsafeMount(mount.hostPath)) {
|
|
121
|
+
violations.push({
|
|
122
|
+
type: 'filesystem',
|
|
123
|
+
severity: 'critical',
|
|
124
|
+
message: `Unsafe volume mount detected: ${mount.hostPath}`,
|
|
125
|
+
containerId: config.containerId || 'unknown',
|
|
126
|
+
timestamp: new Date(),
|
|
127
|
+
details: { mount }
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
return violations;
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Start resource monitoring for a container
|
|
136
|
+
*/
|
|
137
|
+
async startResourceMonitoring(containerId) {
|
|
138
|
+
if (!this.config.enableResourceMonitoring) {
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
logger.info(`Starting resource monitoring for container: ${containerId}`);
|
|
142
|
+
const monitor = setInterval(async () => {
|
|
143
|
+
try {
|
|
144
|
+
const usage = await this.getResourceUsage(containerId);
|
|
145
|
+
await this.checkResourceLimits(containerId, usage);
|
|
146
|
+
}
|
|
147
|
+
catch (error) {
|
|
148
|
+
logger.error(`Resource monitoring failed for container ${containerId}:`, error);
|
|
149
|
+
}
|
|
150
|
+
}, 5000); // Check every 5 seconds
|
|
151
|
+
this.resourceMonitors.set(containerId, monitor);
|
|
152
|
+
// Set up execution timeout
|
|
153
|
+
setTimeout(async () => {
|
|
154
|
+
await this.handleExecutionTimeout(containerId);
|
|
155
|
+
}, this.config.maxExecutionTimeSeconds * 1000);
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Stop resource monitoring for a container
|
|
159
|
+
*/
|
|
160
|
+
stopResourceMonitoring(containerId) {
|
|
161
|
+
const monitor = this.resourceMonitors.get(containerId);
|
|
162
|
+
if (monitor) {
|
|
163
|
+
clearInterval(monitor);
|
|
164
|
+
this.resourceMonitors.delete(containerId);
|
|
165
|
+
logger.info(`Stopped resource monitoring for container: ${containerId}`);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Get current resource usage for a container
|
|
170
|
+
*/
|
|
171
|
+
async getResourceUsage(containerId) {
|
|
172
|
+
try {
|
|
173
|
+
const statsResult = await this.executeCommand('docker', [
|
|
174
|
+
'stats', containerId, '--no-stream', '--format',
|
|
175
|
+
'table {{.MemUsage}}\t{{.CPUPerc}}\t{{.PIDs}}\t{{.NetIO}}'
|
|
176
|
+
]);
|
|
177
|
+
if (statsResult.exitCode !== 0) {
|
|
178
|
+
throw new Error(`Failed to get container stats: ${statsResult.error}`);
|
|
179
|
+
}
|
|
180
|
+
return this.parseResourceStats(statsResult.output);
|
|
181
|
+
}
|
|
182
|
+
catch (error) {
|
|
183
|
+
logger.error(`Failed to get resource usage for container ${containerId}:`, error);
|
|
184
|
+
throw error;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Check if resource usage exceeds limits
|
|
189
|
+
*/
|
|
190
|
+
async checkResourceLimits(containerId, usage) {
|
|
191
|
+
const violations = [];
|
|
192
|
+
// Check memory usage
|
|
193
|
+
if (usage.memoryUsageMB > this.config.maxMemoryMB * 0.9) { // 90% threshold
|
|
194
|
+
violations.push({
|
|
195
|
+
type: 'resource',
|
|
196
|
+
severity: 'high',
|
|
197
|
+
message: `Memory usage ${usage.memoryUsageMB}MB approaching limit ${this.config.maxMemoryMB}MB`,
|
|
198
|
+
containerId,
|
|
199
|
+
timestamp: new Date(),
|
|
200
|
+
details: { usage }
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
// Check CPU usage
|
|
204
|
+
if (usage.cpuUsagePercent > this.config.maxCpuCores * 100 * 0.9) { // 90% threshold
|
|
205
|
+
violations.push({
|
|
206
|
+
type: 'resource',
|
|
207
|
+
severity: 'medium',
|
|
208
|
+
message: `CPU usage ${usage.cpuUsagePercent}% approaching limit`,
|
|
209
|
+
containerId,
|
|
210
|
+
timestamp: new Date(),
|
|
211
|
+
details: { usage }
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
// Check process count
|
|
215
|
+
if (usage.processCount > this.config.maxProcesses * 0.9) { // 90% threshold
|
|
216
|
+
violations.push({
|
|
217
|
+
type: 'resource',
|
|
218
|
+
severity: 'medium',
|
|
219
|
+
message: `Process count ${usage.processCount} approaching limit ${this.config.maxProcesses}`,
|
|
220
|
+
containerId,
|
|
221
|
+
timestamp: new Date(),
|
|
222
|
+
details: { usage }
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
// Log violations
|
|
226
|
+
for (const violation of violations) {
|
|
227
|
+
this.recordViolation(violation);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* Handle execution timeout
|
|
232
|
+
*/
|
|
233
|
+
async handleExecutionTimeout(containerId) {
|
|
234
|
+
logger.warn(`Container ${containerId} exceeded maximum execution time, terminating`);
|
|
235
|
+
const violation = {
|
|
236
|
+
type: 'execution',
|
|
237
|
+
severity: 'high',
|
|
238
|
+
message: `Container exceeded maximum execution time of ${this.config.maxExecutionTimeSeconds} seconds`,
|
|
239
|
+
containerId,
|
|
240
|
+
timestamp: new Date()
|
|
241
|
+
};
|
|
242
|
+
this.recordViolation(violation);
|
|
243
|
+
// Force kill the container
|
|
244
|
+
try {
|
|
245
|
+
await this.executeCommand('docker', ['kill', containerId]);
|
|
246
|
+
}
|
|
247
|
+
catch (error) {
|
|
248
|
+
logger.error(`Failed to kill timed-out container ${containerId}:`, error);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
/**
|
|
252
|
+
* Create secure temporary directory for container
|
|
253
|
+
*/
|
|
254
|
+
async createSecureTempDir(containerId) {
|
|
255
|
+
const tempDir = join('/tmp', `buildhive-${containerId}`);
|
|
256
|
+
try {
|
|
257
|
+
await fs.mkdir(tempDir, { recursive: true, mode: 0o700 });
|
|
258
|
+
// Set strict permissions
|
|
259
|
+
await fs.chmod(tempDir, 0o700);
|
|
260
|
+
logger.info(`Created secure temp directory: ${tempDir}`);
|
|
261
|
+
return tempDir;
|
|
262
|
+
}
|
|
263
|
+
catch (error) {
|
|
264
|
+
logger.error(`Failed to create secure temp directory:`, error);
|
|
265
|
+
throw error;
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
/**
|
|
269
|
+
* Clean up secure temporary directory
|
|
270
|
+
*/
|
|
271
|
+
async cleanupSecureTempDir(tempDir) {
|
|
272
|
+
try {
|
|
273
|
+
await fs.rm(tempDir, { recursive: true, force: true });
|
|
274
|
+
logger.info(`Cleaned up temp directory: ${tempDir}`);
|
|
275
|
+
}
|
|
276
|
+
catch (error) {
|
|
277
|
+
logger.error(`Failed to cleanup temp directory ${tempDir}:`, error);
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
/**
|
|
281
|
+
* Validate Docker image security
|
|
282
|
+
*/
|
|
283
|
+
async validateImageSecurity(image) {
|
|
284
|
+
const violations = [];
|
|
285
|
+
try {
|
|
286
|
+
// Check if image is from trusted registry
|
|
287
|
+
if (!this.isTrustedImage(image)) {
|
|
288
|
+
violations.push({
|
|
289
|
+
type: 'filesystem',
|
|
290
|
+
severity: 'medium',
|
|
291
|
+
message: `Image ${image} is not from a trusted registry`,
|
|
292
|
+
containerId: 'image-validation',
|
|
293
|
+
timestamp: new Date(),
|
|
294
|
+
details: { image }
|
|
295
|
+
});
|
|
296
|
+
}
|
|
297
|
+
// Inspect image for security issues
|
|
298
|
+
const inspectResult = await this.executeCommand('docker', ['inspect', image]);
|
|
299
|
+
if (inspectResult.exitCode === 0) {
|
|
300
|
+
const imageInfo = JSON.parse(inspectResult.output)[0];
|
|
301
|
+
// Check for root user
|
|
302
|
+
if (imageInfo.Config?.User === 'root' || !imageInfo.Config?.User) {
|
|
303
|
+
violations.push({
|
|
304
|
+
type: 'capability',
|
|
305
|
+
severity: 'medium',
|
|
306
|
+
message: `Image ${image} runs as root user`,
|
|
307
|
+
containerId: 'image-validation',
|
|
308
|
+
timestamp: new Date(),
|
|
309
|
+
details: { image }
|
|
310
|
+
});
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
catch (error) {
|
|
315
|
+
logger.error(`Failed to validate image security for ${image}:`, error);
|
|
316
|
+
}
|
|
317
|
+
return violations;
|
|
318
|
+
}
|
|
319
|
+
/**
|
|
320
|
+
* Get security violations
|
|
321
|
+
*/
|
|
322
|
+
getViolations() {
|
|
323
|
+
return [...this.violations];
|
|
324
|
+
}
|
|
325
|
+
/**
|
|
326
|
+
* Clear security violations
|
|
327
|
+
*/
|
|
328
|
+
clearViolations() {
|
|
329
|
+
this.violations = [];
|
|
330
|
+
}
|
|
331
|
+
/**
|
|
332
|
+
* Record a security violation
|
|
333
|
+
*/
|
|
334
|
+
recordViolation(violation) {
|
|
335
|
+
this.violations.push(violation);
|
|
336
|
+
if (this.config.logSecurityEvents) {
|
|
337
|
+
logger.warn(`Security violation [${violation.severity}]: ${violation.message}`, {
|
|
338
|
+
containerId: violation.containerId,
|
|
339
|
+
type: violation.type,
|
|
340
|
+
details: violation.details
|
|
341
|
+
});
|
|
342
|
+
}
|
|
343
|
+
// Keep only last 1000 violations to prevent memory issues
|
|
344
|
+
if (this.violations.length > 1000) {
|
|
345
|
+
this.violations = this.violations.slice(-1000);
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
/**
|
|
349
|
+
* Check if a volume mount is unsafe
|
|
350
|
+
*/
|
|
351
|
+
isUnsafeMount(hostPath) {
|
|
352
|
+
const unsafePaths = [
|
|
353
|
+
'/',
|
|
354
|
+
'/etc',
|
|
355
|
+
'/usr',
|
|
356
|
+
'/bin',
|
|
357
|
+
'/sbin',
|
|
358
|
+
'/boot',
|
|
359
|
+
'/sys',
|
|
360
|
+
'/proc',
|
|
361
|
+
'/dev',
|
|
362
|
+
'/var/run/docker.sock',
|
|
363
|
+
'/home',
|
|
364
|
+
'/root'
|
|
365
|
+
];
|
|
366
|
+
const resolvedPath = resolve(hostPath);
|
|
367
|
+
return unsafePaths.some(unsafePath => resolvedPath === unsafePath || resolvedPath.startsWith(unsafePath + '/'));
|
|
368
|
+
}
|
|
369
|
+
/**
|
|
370
|
+
* Check if image is from trusted registry
|
|
371
|
+
*/
|
|
372
|
+
isTrustedImage(image) {
|
|
373
|
+
const trustedRegistries = [
|
|
374
|
+
'docker.io',
|
|
375
|
+
'gcr.io',
|
|
376
|
+
'quay.io',
|
|
377
|
+
'registry.hub.docker.com'
|
|
378
|
+
];
|
|
379
|
+
// If no registry specified, assume docker.io
|
|
380
|
+
if (!image.includes('/') || !image.includes('.')) {
|
|
381
|
+
return true;
|
|
382
|
+
}
|
|
383
|
+
const registry = image.split('/')[0];
|
|
384
|
+
return trustedRegistries.includes(registry);
|
|
385
|
+
}
|
|
386
|
+
/**
|
|
387
|
+
* Parse memory limit string to MB
|
|
388
|
+
*/
|
|
389
|
+
parseMemoryLimit(limit) {
|
|
390
|
+
const match = limit.match(/^(\d+)([kmg]?)$/i);
|
|
391
|
+
if (!match)
|
|
392
|
+
return 0;
|
|
393
|
+
const value = parseInt(match[1]);
|
|
394
|
+
const unit = match[2]?.toLowerCase() || '';
|
|
395
|
+
switch (unit) {
|
|
396
|
+
case 'k': return value / 1024;
|
|
397
|
+
case 'm': return value;
|
|
398
|
+
case 'g': return value * 1024;
|
|
399
|
+
default: return value / (1024 * 1024); // bytes to MB
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
/**
|
|
403
|
+
* Parse resource stats output
|
|
404
|
+
*/
|
|
405
|
+
parseResourceStats(output) {
|
|
406
|
+
// This is a simplified parser - in production, you'd want more robust parsing
|
|
407
|
+
const lines = output.trim().split('\n');
|
|
408
|
+
const dataLine = lines[1] || '';
|
|
409
|
+
const parts = dataLine.split('\t');
|
|
410
|
+
return {
|
|
411
|
+
memoryUsageMB: this.parseMemoryUsage(parts[0] || '0'),
|
|
412
|
+
cpuUsagePercent: parseFloat(parts[1]?.replace('%', '') || '0'),
|
|
413
|
+
processCount: parseInt(parts[2] || '0'),
|
|
414
|
+
networkBytesIn: 0, // Would need more complex parsing
|
|
415
|
+
networkBytesOut: 0,
|
|
416
|
+
diskUsageMB: 0 // Would need additional docker command
|
|
417
|
+
};
|
|
418
|
+
}
|
|
419
|
+
/**
|
|
420
|
+
* Parse memory usage string
|
|
421
|
+
*/
|
|
422
|
+
parseMemoryUsage(usage) {
|
|
423
|
+
const match = usage.match(/^([\d.]+)([KMGT]?i?B)/);
|
|
424
|
+
if (!match)
|
|
425
|
+
return 0;
|
|
426
|
+
const value = parseFloat(match[1]);
|
|
427
|
+
const unit = match[2];
|
|
428
|
+
switch (unit) {
|
|
429
|
+
case 'KiB':
|
|
430
|
+
case 'KB': return value / 1024;
|
|
431
|
+
case 'MiB':
|
|
432
|
+
case 'MB': return value;
|
|
433
|
+
case 'GiB':
|
|
434
|
+
case 'GB': return value * 1024;
|
|
435
|
+
case 'TiB':
|
|
436
|
+
case 'TB': return value * 1024 * 1024;
|
|
437
|
+
default: return value / (1024 * 1024); // bytes to MB
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
/**
|
|
441
|
+
* Execute a system command
|
|
442
|
+
*/
|
|
443
|
+
async executeCommand(command, args) {
|
|
444
|
+
return new Promise((resolve) => {
|
|
445
|
+
const process = spawn(command, args, { stdio: ['pipe', 'pipe', 'pipe'] });
|
|
446
|
+
let output = '';
|
|
447
|
+
let error = '';
|
|
448
|
+
process.stdout.on('data', (data) => output += data.toString());
|
|
449
|
+
process.stderr.on('data', (data) => error += data.toString());
|
|
450
|
+
process.on('close', (code) => {
|
|
451
|
+
resolve({
|
|
452
|
+
exitCode: code || 0,
|
|
453
|
+
output: output.trim(),
|
|
454
|
+
error: error.trim()
|
|
455
|
+
});
|
|
456
|
+
});
|
|
457
|
+
});
|
|
458
|
+
}
|
|
459
|
+
/**
|
|
460
|
+
* Cleanup all monitoring
|
|
461
|
+
*/
|
|
462
|
+
cleanup() {
|
|
463
|
+
for (const [containerId, monitor] of this.resourceMonitors) {
|
|
464
|
+
clearInterval(monitor);
|
|
465
|
+
}
|
|
466
|
+
this.resourceMonitors.clear();
|
|
467
|
+
logger.info('Security manager cleanup completed');
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
//# sourceMappingURL=security.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"security.js","sourceRoot":"","sources":["../src/security.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,QAAQ,IAAI,EAAE,EAAE,MAAM,IAAI,CAAC;AACpC,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AACrC,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAEtC,MAAM,MAAM,GAAG,YAAY,CAAC,UAAU,CAAC,CAAC;AAuDxC,MAAM,OAAO,eAAe;IAClB,MAAM,CAAiB;IACvB,UAAU,GAAwB,EAAE,CAAC;IACrC,gBAAgB,GAAG,IAAI,GAAG,EAA0B,CAAC;IAE7D,YAAY,MAAsB;QAChC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,MAAM,CAAC,IAAI,CAAC,0DAA0D,CAAC,CAAC;IAC1E,CAAC;IAED;;OAEG;IACH,wBAAwB,CAAC,WAAmB;QAC1C,MAAM,IAAI,GAAa,EAAE,CAAC;QAE1B,0BAA0B;QAC1B,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE,wBAAwB,CAAC,CAAC;QAEtD,mCAAmC;QACnC,IAAI,IAAI,CAAC,MAAM,CAAC,mBAAmB,EAAE,CAAC;YACpC,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,KAAK,CAAC,CAAC;YAE/B,2CAA2C;YAC3C,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,MAAM,CAAC,mBAAmB,EAAE,CAAC;gBAClD,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC;YAC9B,CAAC;QACH,CAAC;QAED,oBAAoB;QACpB,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;QAEhD,IAAI,IAAI,CAAC,MAAM,CAAC,WAAW,KAAK,MAAM,EAAE,CAAC;YACvC,MAAM,CAAC,IAAI,CAAC,aAAa,WAAW,8BAA8B,CAAC,CAAC;QACtE,CAAC;QAED,kBAAkB;QAClB,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC,WAAW,GAAG,CAAC,CAAC;QACrD,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,QAAQ,EAAE,CAAC,CAAC;QACxD,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,QAAQ,EAAE,CAAC,CAAC;QAC/D,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,UAAU,IAAI,CAAC,MAAM,CAAC,kBAAkB,IAAI,IAAI,CAAC,MAAM,CAAC,kBAAkB,EAAE,CAAC,CAAC;QAEpG,sBAAsB;QACtB,IAAI,IAAI,CAAC,MAAM,CAAC,YAAY,EAAE,CAAC;YAC7B,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;YAEzB,sCAAsC;YACtC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,oCAAoC,IAAI,CAAC,MAAM,CAAC,aAAa,GAAG,CAAC,CAAC;YACvF,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,wCAAwC,IAAI,CAAC,MAAM,CAAC,aAAa,GAAG,CAAC,CAAC;YAE3F,qCAAqC;YACrC,KAAK,MAAM,SAAS,IAAI,IAAI,CAAC,MAAM,CAAC,iBAAiB,EAAE,CAAC;gBACtD,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,GAAG,SAAS,mCAAmC,CAAC,CAAC;YACxE,CAAC;QACH,CAAC;QAED,oBAAoB;QACpB,IAAI,IAAI,CAAC,MAAM,CAAC,cAAc,EAAE,CAAC;YAC/B,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE,WAAW,IAAI,CAAC,MAAM,CAAC,cAAc,EAAE,CAAC,CAAC;QACvE,CAAC;QAED,IAAI,IAAI,CAAC,MAAM,CAAC,eAAe,EAAE,CAAC;YAChC,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE,YAAY,IAAI,CAAC,MAAM,CAAC,eAAe,EAAE,CAAC,CAAC;QACzE,CAAC;QAED,uBAAuB;QACvB,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE,wBAAwB,CAAC,CAAC;QACtD,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,WAAW,CAAC,CAAC,CAAC,uBAAuB;QACzD,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,yBAAyB;QAE9C,MAAM,CAAC,IAAI,CAAC,aAAa,IAAI,CAAC,MAAM,GAAG,CAAC,qCAAqC,WAAW,EAAE,CAAC,CAAC;QAC5F,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,uBAAuB,CAAC,MAAW;QACvC,MAAM,UAAU,GAAwB,EAAE,CAAC;QAE3C,wBAAwB;QACxB,IAAI,MAAM,CAAC,WAAW,IAAI,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC,WAAW,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC;YAC9F,UAAU,CAAC,IAAI,CAAC;gBACd,IAAI,EAAE,UAAU;gBAChB,QAAQ,EAAE,MAAM;gBAChB,OAAO,EAAE,gBAAgB,MAAM,CAAC,WAAW,4BAA4B,IAAI,CAAC,MAAM,CAAC,WAAW,IAAI;gBAClG,WAAW,EAAE,MAAM,CAAC,WAAW,IAAI,SAAS;gBAC5C,SAAS,EAAE,IAAI,IAAI,EAAE;aACtB,CAAC,CAAC;QACL,CAAC;QAED,mBAAmB;QACnB,IAAI,MAAM,CAAC,QAAQ,IAAI,UAAU,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC;YAC7E,UAAU,CAAC,IAAI,CAAC;gBACd,IAAI,EAAE,UAAU;gBAChB,QAAQ,EAAE,MAAM;gBAChB,OAAO,EAAE,aAAa,MAAM,CAAC,QAAQ,4BAA4B,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE;gBAC1F,WAAW,EAAE,MAAM,CAAC,WAAW,IAAI,SAAS;gBAC5C,SAAS,EAAE,IAAI,IAAI,EAAE;aACtB,CAAC,CAAC;QACL,CAAC;QAED,8BAA8B;QAC9B,IAAI,MAAM,CAAC,WAAW,IAAI,MAAM,CAAC,WAAW,KAAK,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC;YACzE,UAAU,CAAC,IAAI,CAAC;gBACd,IAAI,EAAE,SAAS;gBACf,QAAQ,EAAE,UAAU;gBACpB,OAAO,EAAE,gBAAgB,MAAM,CAAC,WAAW,0BAA0B,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE;gBAC9F,WAAW,EAAE,MAAM,CAAC,WAAW,IAAI,SAAS;gBAC5C,SAAS,EAAE,IAAI,IAAI,EAAE;aACtB,CAAC,CAAC;QACL,CAAC;QAED,4BAA4B;QAC5B,IAAI,MAAM,CAAC,UAAU,EAAE,CAAC;YACtB,UAAU,CAAC,IAAI,CAAC;gBACd,IAAI,EAAE,YAAY;gBAClB,QAAQ,EAAE,UAAU;gBACpB,OAAO,EAAE,gCAAgC;gBACzC,WAAW,EAAE,MAAM,CAAC,WAAW,IAAI,SAAS;gBAC5C,SAAS,EAAE,IAAI,IAAI,EAAE;aACtB,CAAC,CAAC;QACL,CAAC;QAED,yCAAyC;QACzC,IAAI,MAAM,CAAC,YAAY,EAAE,CAAC;YACxB,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,YAAY,EAAE,CAAC;gBACxC,IAAI,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC;oBACvC,UAAU,CAAC,IAAI,CAAC;wBACd,IAAI,EAAE,YAAY;wBAClB,QAAQ,EAAE,UAAU;wBACpB,OAAO,EAAE,iCAAiC,KAAK,CAAC,QAAQ,EAAE;wBAC1D,WAAW,EAAE,MAAM,CAAC,WAAW,IAAI,SAAS;wBAC5C,SAAS,EAAE,IAAI,IAAI,EAAE;wBACrB,OAAO,EAAE,EAAE,KAAK,EAAE;qBACnB,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;QACH,CAAC;QAED,OAAO,UAAU,CAAC;IACpB,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,uBAAuB,CAAC,WAAmB;QAC/C,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,wBAAwB,EAAE,CAAC;YAC1C,OAAO;QACT,CAAC;QAED,MAAM,CAAC,IAAI,CAAC,+CAA+C,WAAW,EAAE,CAAC,CAAC;QAE1E,MAAM,OAAO,GAAG,WAAW,CAAC,KAAK,IAAI,EAAE;YACrC,IAAI,CAAC;gBACH,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,gBAAgB,CAAC,WAAW,CAAC,CAAC;gBACvD,MAAM,IAAI,CAAC,mBAAmB,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC;YACrD,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,MAAM,CAAC,KAAK,CAAC,4CAA4C,WAAW,GAAG,EAAE,KAAK,CAAC,CAAC;YAClF,CAAC;QACH,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,wBAAwB;QAElC,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;QAEhD,2BAA2B;QAC3B,UAAU,CAAC,KAAK,IAAI,EAAE;YACpB,MAAM,IAAI,CAAC,sBAAsB,CAAC,WAAW,CAAC,CAAC;QACjD,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,uBAAuB,GAAG,IAAI,CAAC,CAAC;IACjD,CAAC;IAED;;OAEG;IACH,sBAAsB,CAAC,WAAmB;QACxC,MAAM,OAAO,GAAG,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;QACvD,IAAI,OAAO,EAAE,CAAC;YACZ,aAAa,CAAC,OAAO,CAAC,CAAC;YACvB,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;YAC1C,MAAM,CAAC,IAAI,CAAC,8CAA8C,WAAW,EAAE,CAAC,CAAC;QAC3E,CAAC;IACH,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,gBAAgB,CAAC,WAAmB;QACxC,IAAI,CAAC;YACH,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,cAAc,CAAC,QAAQ,EAAE;gBACtD,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,UAAU;gBAC/C,0DAA0D;aAC3D,CAAC,CAAC;YAEH,IAAI,WAAW,CAAC,QAAQ,KAAK,CAAC,EAAE,CAAC;gBAC/B,MAAM,IAAI,KAAK,CAAC,kCAAkC,WAAW,CAAC,KAAK,EAAE,CAAC,CAAC;YACzE,CAAC;YAED,OAAO,IAAI,CAAC,kBAAkB,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;QACrD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,CAAC,KAAK,CAAC,8CAA8C,WAAW,GAAG,EAAE,KAAK,CAAC,CAAC;YAClF,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,mBAAmB,CAAC,WAAmB,EAAE,KAAoB;QACzE,MAAM,UAAU,GAAwB,EAAE,CAAC;QAE3C,qBAAqB;QACrB,IAAI,KAAK,CAAC,aAAa,GAAG,IAAI,CAAC,MAAM,CAAC,WAAW,GAAG,GAAG,EAAE,CAAC,CAAC,gBAAgB;YACzE,UAAU,CAAC,IAAI,CAAC;gBACd,IAAI,EAAE,UAAU;gBAChB,QAAQ,EAAE,MAAM;gBAChB,OAAO,EAAE,gBAAgB,KAAK,CAAC,aAAa,wBAAwB,IAAI,CAAC,MAAM,CAAC,WAAW,IAAI;gBAC/F,WAAW;gBACX,SAAS,EAAE,IAAI,IAAI,EAAE;gBACrB,OAAO,EAAE,EAAE,KAAK,EAAE;aACnB,CAAC,CAAC;QACL,CAAC;QAED,kBAAkB;QAClB,IAAI,KAAK,CAAC,eAAe,GAAG,IAAI,CAAC,MAAM,CAAC,WAAW,GAAG,GAAG,GAAG,GAAG,EAAE,CAAC,CAAC,gBAAgB;YACjF,UAAU,CAAC,IAAI,CAAC;gBACd,IAAI,EAAE,UAAU;gBAChB,QAAQ,EAAE,QAAQ;gBAClB,OAAO,EAAE,aAAa,KAAK,CAAC,eAAe,qBAAqB;gBAChE,WAAW;gBACX,SAAS,EAAE,IAAI,IAAI,EAAE;gBACrB,OAAO,EAAE,EAAE,KAAK,EAAE;aACnB,CAAC,CAAC;QACL,CAAC;QAED,sBAAsB;QACtB,IAAI,KAAK,CAAC,YAAY,GAAG,IAAI,CAAC,MAAM,CAAC,YAAY,GAAG,GAAG,EAAE,CAAC,CAAC,gBAAgB;YACzE,UAAU,CAAC,IAAI,CAAC;gBACd,IAAI,EAAE,UAAU;gBAChB,QAAQ,EAAE,QAAQ;gBAClB,OAAO,EAAE,iBAAiB,KAAK,CAAC,YAAY,sBAAsB,IAAI,CAAC,MAAM,CAAC,YAAY,EAAE;gBAC5F,WAAW;gBACX,SAAS,EAAE,IAAI,IAAI,EAAE;gBACrB,OAAO,EAAE,EAAE,KAAK,EAAE;aACnB,CAAC,CAAC;QACL,CAAC;QAED,iBAAiB;QACjB,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;YACnC,IAAI,CAAC,eAAe,CAAC,SAAS,CAAC,CAAC;QAClC,CAAC;IACH,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,sBAAsB,CAAC,WAAmB;QACtD,MAAM,CAAC,IAAI,CAAC,aAAa,WAAW,+CAA+C,CAAC,CAAC;QAErF,MAAM,SAAS,GAAsB;YACnC,IAAI,EAAE,WAAW;YACjB,QAAQ,EAAE,MAAM;YAChB,OAAO,EAAE,gDAAgD,IAAI,CAAC,MAAM,CAAC,uBAAuB,UAAU;YACtG,WAAW;YACX,SAAS,EAAE,IAAI,IAAI,EAAE;SACtB,CAAC;QAEF,IAAI,CAAC,eAAe,CAAC,SAAS,CAAC,CAAC;QAEhC,2BAA2B;QAC3B,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,cAAc,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC;QAC7D,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,CAAC,KAAK,CAAC,sCAAsC,WAAW,GAAG,EAAE,KAAK,CAAC,CAAC;QAC5E,CAAC;IACH,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,mBAAmB,CAAC,WAAmB;QAC3C,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,EAAE,aAAa,WAAW,EAAE,CAAC,CAAC;QAEzD,IAAI,CAAC;YACH,MAAM,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;YAE1D,yBAAyB;YACzB,MAAM,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;YAE/B,MAAM,CAAC,IAAI,CAAC,kCAAkC,OAAO,EAAE,CAAC,CAAC;YACzD,OAAO,OAAO,CAAC;QAEjB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,CAAC,KAAK,CAAC,yCAAyC,EAAE,KAAK,CAAC,CAAC;YAC/D,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,oBAAoB,CAAC,OAAe;QACxC,IAAI,CAAC;YACH,MAAM,EAAE,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;YACvD,MAAM,CAAC,IAAI,CAAC,8BAA8B,OAAO,EAAE,CAAC,CAAC;QACvD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,CAAC,KAAK,CAAC,oCAAoC,OAAO,GAAG,EAAE,KAAK,CAAC,CAAC;QACtE,CAAC;IACH,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,qBAAqB,CAAC,KAAa;QACvC,MAAM,UAAU,GAAwB,EAAE,CAAC;QAE3C,IAAI,CAAC;YACH,0CAA0C;YAC1C,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,EAAE,CAAC;gBAChC,UAAU,CAAC,IAAI,CAAC;oBACd,IAAI,EAAE,YAAY;oBAClB,QAAQ,EAAE,QAAQ;oBAClB,OAAO,EAAE,SAAS,KAAK,iCAAiC;oBACxD,WAAW,EAAE,kBAAkB;oBAC/B,SAAS,EAAE,IAAI,IAAI,EAAE;oBACrB,OAAO,EAAE,EAAE,KAAK,EAAE;iBACnB,CAAC,CAAC;YACL,CAAC;YAED,oCAAoC;YACpC,MAAM,aAAa,GAAG,MAAM,IAAI,CAAC,cAAc,CAAC,QAAQ,EAAE,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC,CAAC;YAE9E,IAAI,aAAa,CAAC,QAAQ,KAAK,CAAC,EAAE,CAAC;gBACjC,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;gBAEtD,sBAAsB;gBACtB,IAAI,SAAS,CAAC,MAAM,EAAE,IAAI,KAAK,MAAM,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC;oBACjE,UAAU,CAAC,IAAI,CAAC;wBACd,IAAI,EAAE,YAAY;wBAClB,QAAQ,EAAE,QAAQ;wBAClB,OAAO,EAAE,SAAS,KAAK,oBAAoB;wBAC3C,WAAW,EAAE,kBAAkB;wBAC/B,SAAS,EAAE,IAAI,IAAI,EAAE;wBACrB,OAAO,EAAE,EAAE,KAAK,EAAE;qBACnB,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;QAEH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,CAAC,KAAK,CAAC,yCAAyC,KAAK,GAAG,EAAE,KAAK,CAAC,CAAC;QACzE,CAAC;QAED,OAAO,UAAU,CAAC;IACpB,CAAC;IAED;;OAEG;IACH,aAAa;QACX,OAAO,CAAC,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC;IAC9B,CAAC;IAED;;OAEG;IACH,eAAe;QACb,IAAI,CAAC,UAAU,GAAG,EAAE,CAAC;IACvB,CAAC;IAED;;OAEG;IACK,eAAe,CAAC,SAA4B;QAClD,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAEhC,IAAI,IAAI,CAAC,MAAM,CAAC,iBAAiB,EAAE,CAAC;YAClC,MAAM,CAAC,IAAI,CAAC,uBAAuB,SAAS,CAAC,QAAQ,MAAM,SAAS,CAAC,OAAO,EAAE,EAAE;gBAC9E,WAAW,EAAE,SAAS,CAAC,WAAW;gBAClC,IAAI,EAAE,SAAS,CAAC,IAAI;gBACpB,OAAO,EAAE,SAAS,CAAC,OAAO;aAC3B,CAAC,CAAC;QACL,CAAC;QAED,0DAA0D;QAC1D,IAAI,IAAI,CAAC,UAAU,CAAC,MAAM,GAAG,IAAI,EAAE,CAAC;YAClC,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC;QACjD,CAAC;IACH,CAAC;IAED;;OAEG;IACK,aAAa,CAAC,QAAgB;QACpC,MAAM,WAAW,GAAG;YAClB,GAAG;YACH,MAAM;YACN,MAAM;YACN,MAAM;YACN,OAAO;YACP,OAAO;YACP,MAAM;YACN,OAAO;YACP,MAAM;YACN,sBAAsB;YACtB,OAAO;YACP,OAAO;SACR,CAAC;QAEF,MAAM,YAAY,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;QAEvC,OAAO,WAAW,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CACnC,YAAY,KAAK,UAAU,IAAI,YAAY,CAAC,UAAU,CAAC,UAAU,GAAG,GAAG,CAAC,CACzE,CAAC;IACJ,CAAC;IAED;;OAEG;IACK,cAAc,CAAC,KAAa;QAClC,MAAM,iBAAiB,GAAG;YACxB,WAAW;YACX,QAAQ;YACR,SAAS;YACT,yBAAyB;SAC1B,CAAC;QAEF,6CAA6C;QAC7C,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;YACjD,OAAO,IAAI,CAAC;QACd,CAAC;QAED,MAAM,QAAQ,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QACrC,OAAO,iBAAiB,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IAC9C,CAAC;IAED;;OAEG;IACK,gBAAgB,CAAC,KAAa;QACpC,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAC;QAC9C,IAAI,CAAC,KAAK;YAAE,OAAO,CAAC,CAAC;QAErB,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QACjC,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC;QAE3C,QAAQ,IAAI,EAAE,CAAC;YACb,KAAK,GAAG,CAAC,CAAC,OAAO,KAAK,GAAG,IAAI,CAAC;YAC9B,KAAK,GAAG,CAAC,CAAC,OAAO,KAAK,CAAC;YACvB,KAAK,GAAG,CAAC,CAAC,OAAO,KAAK,GAAG,IAAI,CAAC;YAC9B,OAAO,CAAC,CAAC,OAAO,KAAK,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,cAAc;QACvD,CAAC;IACH,CAAC;IAED;;OAEG;IACK,kBAAkB,CAAC,MAAc;QACvC,8EAA8E;QAC9E,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACxC,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QAChC,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAEnC,OAAO;YACL,aAAa,EAAE,IAAI,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC;YACrD,eAAe,EAAE,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,GAAG,CAAC;YAC9D,YAAY,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC;YACvC,cAAc,EAAE,CAAC,EAAE,kCAAkC;YACrD,eAAe,EAAE,CAAC;YAClB,WAAW,EAAE,CAAC,CAAC,uCAAuC;SACvD,CAAC;IACJ,CAAC;IAED;;OAEG;IACK,gBAAgB,CAAC,KAAa;QACpC,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,uBAAuB,CAAC,CAAC;QACnD,IAAI,CAAC,KAAK;YAAE,OAAO,CAAC,CAAC;QAErB,MAAM,KAAK,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QACnC,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QAEtB,QAAQ,IAAI,EAAE,CAAC;YACb,KAAK,KAAK,CAAC;YAAC,KAAK,IAAI,CAAC,CAAC,OAAO,KAAK,GAAG,IAAI,CAAC;YAC3C,KAAK,KAAK,CAAC;YAAC,KAAK,IAAI,CAAC,CAAC,OAAO,KAAK,CAAC;YACpC,KAAK,KAAK,CAAC;YAAC,KAAK,IAAI,CAAC,CAAC,OAAO,KAAK,GAAG,IAAI,CAAC;YAC3C,KAAK,KAAK,CAAC;YAAC,KAAK,IAAI,CAAC,CAAC,OAAO,KAAK,GAAG,IAAI,GAAG,IAAI,CAAC;YAClD,OAAO,CAAC,CAAC,OAAO,KAAK,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,cAAc;QACvD,CAAC;IACH,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,cAAc,CAAC,OAAe,EAAE,IAAc;QAC1D,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;YAC7B,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC;YAE1E,IAAI,MAAM,GAAG,EAAE,CAAC;YAChB,IAAI,KAAK,GAAG,EAAE,CAAC;YAEf,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,MAAM,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;YAC/D,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,KAAK,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;YAE9D,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE;gBAC3B,OAAO,CAAC;oBACN,QAAQ,EAAE,IAAI,IAAI,CAAC;oBACnB,MAAM,EAAE,MAAM,CAAC,IAAI,EAAE;oBACrB,KAAK,EAAE,KAAK,CAAC,IAAI,EAAE;iBACpB,CAAC,CAAC;YACL,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC;IAED;;OAEG;IACH,OAAO;QACL,KAAK,MAAM,CAAC,WAAW,EAAE,OAAO,CAAC,IAAI,IAAI,CAAC,gBAAgB,EAAE,CAAC;YAC3D,aAAa,CAAC,OAAO,CAAC,CAAC;QACzB,CAAC;QACD,IAAI,CAAC,gBAAgB,CAAC,KAAK,EAAE,CAAC;QAC9B,MAAM,CAAC,IAAI,CAAC,oCAAoC,CAAC,CAAC;IACpD,CAAC;CACF"}
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Artifact Uploader - MVP.4.2.4
|
|
3
|
+
*
|
|
4
|
+
* Handles artifact upload to storage backends (local or S3).
|
|
5
|
+
*
|
|
6
|
+
* Features:
|
|
7
|
+
* - Local file storage with configurable base path
|
|
8
|
+
* - S3 upload with multipart support for large files (>50MB)
|
|
9
|
+
* - S3-compatible storage support (MinIO, Cloudflare R2, etc.)
|
|
10
|
+
* - Presigned download URL generation
|
|
11
|
+
* - Retry logic with exponential backoff
|
|
12
|
+
* - Proper error handling and logging
|
|
13
|
+
* - Cleanup of temporary files after upload
|
|
14
|
+
* - Batch S3 object deletion for retention cleanup
|
|
15
|
+
*
|
|
16
|
+
* @module storage/artifactUploader
|
|
17
|
+
*/
|
|
18
|
+
import type { StorageConfig } from '../config/types.js';
|
|
19
|
+
export interface UploadResult {
|
|
20
|
+
url: string;
|
|
21
|
+
size: number;
|
|
22
|
+
uploadedAt: Date;
|
|
23
|
+
}
|
|
24
|
+
export interface UploadOptions {
|
|
25
|
+
/**
|
|
26
|
+
* Maximum number of retry attempts on failure
|
|
27
|
+
*/
|
|
28
|
+
maxRetries?: number;
|
|
29
|
+
/**
|
|
30
|
+
* Base delay in milliseconds for exponential backoff
|
|
31
|
+
*/
|
|
32
|
+
retryDelayMs?: number;
|
|
33
|
+
/**
|
|
34
|
+
* Whether to delete the source file after successful upload
|
|
35
|
+
*/
|
|
36
|
+
deleteAfterUpload?: boolean;
|
|
37
|
+
}
|
|
38
|
+
export declare class ArtifactUploader {
|
|
39
|
+
private config;
|
|
40
|
+
private s3Client;
|
|
41
|
+
constructor(config: StorageConfig);
|
|
42
|
+
/**
|
|
43
|
+
* Lazily create and cache an S3Client instance based on the current config.
|
|
44
|
+
*/
|
|
45
|
+
private getS3Client;
|
|
46
|
+
/**
|
|
47
|
+
* Build the S3 object key from an artifact name, applying the configured path prefix.
|
|
48
|
+
*/
|
|
49
|
+
private buildS3Key;
|
|
50
|
+
/**
|
|
51
|
+
* Build a public-style S3 URL for an object.
|
|
52
|
+
*/
|
|
53
|
+
private buildS3Url;
|
|
54
|
+
/**
|
|
55
|
+
* Upload an artifact to the configured storage backend
|
|
56
|
+
*
|
|
57
|
+
* @param sourcePath - Absolute path to the artifact file
|
|
58
|
+
* @param artifactName - Name/path for the artifact in storage
|
|
59
|
+
* @param options - Upload options
|
|
60
|
+
* @returns Upload result with URL and metadata
|
|
61
|
+
*/
|
|
62
|
+
uploadArtifact(sourcePath: string, artifactName: string, options?: UploadOptions): Promise<UploadResult>;
|
|
63
|
+
/**
|
|
64
|
+
* Upload artifact to local storage
|
|
65
|
+
*
|
|
66
|
+
* @param sourcePath - Source file path
|
|
67
|
+
* @param artifactName - Target artifact name
|
|
68
|
+
* @param maxRetries - Maximum retry attempts
|
|
69
|
+
* @param retryDelayMs - Retry delay in milliseconds
|
|
70
|
+
* @returns Upload result
|
|
71
|
+
*/
|
|
72
|
+
private uploadToLocal;
|
|
73
|
+
/**
|
|
74
|
+
* Upload artifact to S3
|
|
75
|
+
*
|
|
76
|
+
* Uses PutObjectCommand for files <= 50 MB and multipart Upload for larger files.
|
|
77
|
+
* Supports S3-compatible storage (MinIO, Cloudflare R2) via custom endpoint.
|
|
78
|
+
*
|
|
79
|
+
* @param sourcePath - Source file path
|
|
80
|
+
* @param artifactName - Target artifact name
|
|
81
|
+
* @param maxRetries - Maximum retry attempts
|
|
82
|
+
* @param retryDelayMs - Retry delay in milliseconds
|
|
83
|
+
* @returns Upload result
|
|
84
|
+
*/
|
|
85
|
+
private uploadToS3;
|
|
86
|
+
/**
|
|
87
|
+
* Generate a presigned download URL for an artifact in S3.
|
|
88
|
+
*
|
|
89
|
+
* @param artifactName - The artifact name/path in storage
|
|
90
|
+
* @param expiresInSeconds - URL expiration time (default: 3600 = 1 hour)
|
|
91
|
+
* @returns Presigned download URL
|
|
92
|
+
*/
|
|
93
|
+
getSignedDownloadUrl(artifactName: string, expiresInSeconds?: number): Promise<string>;
|
|
94
|
+
/**
|
|
95
|
+
* Delete S3 objects in batch using DeleteObjectsCommand.
|
|
96
|
+
*
|
|
97
|
+
* @param keys - Array of S3 object keys to delete
|
|
98
|
+
* @returns Number of objects successfully deleted
|
|
99
|
+
*/
|
|
100
|
+
deleteS3Objects(keys: string[]): Promise<number>;
|
|
101
|
+
/**
|
|
102
|
+
* Delete a file from the filesystem
|
|
103
|
+
*
|
|
104
|
+
* @param filePath - Path to the file to delete
|
|
105
|
+
*/
|
|
106
|
+
private deleteFile;
|
|
107
|
+
/**
|
|
108
|
+
* Retry an operation with exponential backoff
|
|
109
|
+
*
|
|
110
|
+
* @param operation - Async operation to retry
|
|
111
|
+
* @param maxRetries - Maximum number of retry attempts
|
|
112
|
+
* @param baseDelayMs - Base delay for exponential backoff
|
|
113
|
+
* @param operationName - Name for logging
|
|
114
|
+
*/
|
|
115
|
+
private retryOperation;
|
|
116
|
+
/**
|
|
117
|
+
* Clean up old artifacts based on retention policy
|
|
118
|
+
*
|
|
119
|
+
* @param basePath - Base path to scan for old artifacts
|
|
120
|
+
* @returns Number of files deleted
|
|
121
|
+
*/
|
|
122
|
+
cleanupOldArtifacts(basePath?: string): Promise<number>;
|
|
123
|
+
/**
|
|
124
|
+
* Recursively find files older than the cutoff time
|
|
125
|
+
*
|
|
126
|
+
* @param dirPath - Directory to scan
|
|
127
|
+
* @param cutoffTime - Cutoff timestamp (files older than this will be included)
|
|
128
|
+
* @returns Array of file paths
|
|
129
|
+
*/
|
|
130
|
+
private findOldFiles;
|
|
131
|
+
/**
|
|
132
|
+
* Get storage statistics
|
|
133
|
+
*
|
|
134
|
+
* @returns Storage usage statistics
|
|
135
|
+
*/
|
|
136
|
+
getStorageStats(): Promise<{
|
|
137
|
+
type: 'local' | 's3';
|
|
138
|
+
totalFiles: number;
|
|
139
|
+
totalSizeBytes: number;
|
|
140
|
+
oldestFileDate?: Date;
|
|
141
|
+
newestFileDate?: Date;
|
|
142
|
+
}>;
|
|
143
|
+
/**
|
|
144
|
+
* Recursively find all files in a directory
|
|
145
|
+
*
|
|
146
|
+
* @param dirPath - Directory to scan
|
|
147
|
+
* @returns Array of file paths
|
|
148
|
+
*/
|
|
149
|
+
private findAllFiles;
|
|
150
|
+
/**
|
|
151
|
+
* Retrieve storage statistics from S3 using ListObjectsV2 with pagination.
|
|
152
|
+
*/
|
|
153
|
+
private getS3StorageStats;
|
|
154
|
+
}
|
|
155
|
+
//# sourceMappingURL=artifactUploader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"artifactUploader.d.ts","sourceRoot":"","sources":["../../src/storage/artifactUploader.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAKH,OAAO,KAAK,EAAE,aAAa,EAAY,MAAM,oBAAoB,CAAC;AAclE,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,IAAI,CAAC;CAClB;AAED,MAAM,WAAW,aAAa;IAC5B;;OAEG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB;;OAEG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB;;OAEG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAKD,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,MAAM,CAAgB;IAC9B,OAAO,CAAC,QAAQ,CAAyB;gBAE7B,MAAM,EAAE,aAAa;IASjC;;OAEG;IACH,OAAO,CAAC,WAAW;IAgCnB;;OAEG;IACH,OAAO,CAAC,UAAU;IAQlB;;OAEG;IACH,OAAO,CAAC,UAAU;IAUlB;;;;;;;OAOG;IACG,cAAc,CAClB,UAAU,EAAE,MAAM,EAClB,YAAY,EAAE,MAAM,EACpB,OAAO,GAAE,aAAkB,GAC1B,OAAO,CAAC,YAAY,CAAC;IA+CxB;;;;;;;;OAQG;YACW,aAAa;IAkC3B;;;;;;;;;;;OAWG;YACW,UAAU;IAwFxB;;;;;;OAMG;IACG,oBAAoB,CACxB,YAAY,EAAE,MAAM,EACpB,gBAAgB,GAAE,MAAa,GAC9B,OAAO,CAAC,MAAM,CAAC;IAgClB;;;;;OAKG;IACG,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC;IAwDtD;;;;OAIG;YACW,UAAU;IAaxB;;;;;;;OAOG;YACW,cAAc;IAiC5B;;;;;OAKG;IACG,mBAAmB,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAoC7D;;;;;;OAMG;YACW,YAAY;IA+B1B;;;;OAIG;IACG,eAAe,IAAI,OAAO,CAAC;QAC/B,IAAI,EAAE,OAAO,GAAG,IAAI,CAAC;QACrB,UAAU,EAAE,MAAM,CAAC;QACnB,cAAc,EAAE,MAAM,CAAC;QACvB,cAAc,CAAC,EAAE,IAAI,CAAC;QACtB,cAAc,CAAC,EAAE,IAAI,CAAC;KACvB,CAAC;IAkCF;;;;;OAKG;YACW,YAAY;IA4B1B;;OAEG;YACW,iBAAiB;CA+DhC"}
|