@@ -251,6 +251,134 @@ upload_to_s3() {
251251 fi
252252}
253253
254+ # Create ClickHouse table if it doesn't exist, or truncate if it does
255+ setup_clickhouse_table () {
256+ local table_name=" $1 "
257+
258+ log_info " Setting up ClickHouse table: $table_name "
259+
260+ # Build ClickHouse URL
261+ local clickhouse_url=" ${CLICKHOUSE_URL} "
262+ local auth_params=" "
263+
264+ if [[ -n " ${CLICKHOUSE_USERNAME:- } " && " ${CLICKHOUSE_USERNAME} " != " default" ]]; then
265+ auth_params=" --user ${CLICKHOUSE_USERNAME} "
266+ fi
267+
268+ if [[ -n " ${CLICKHOUSE_PASSWORD:- } " ]]; then
269+ auth_params=" ${auth_params} --password ${CLICKHOUSE_PASSWORD} "
270+ fi
271+
272+ # Check if table exists
273+ local table_exists
274+ if table_exists=$( curl -s ${auth_params} --data " SELECT COUNT(*) FROM system.tables WHERE database='${CLICKHOUSE_DATABASE} ' AND name='${table_name} '" " ${clickhouse_url} " ) ; then
275+ if [[ " $table_exists " == " 1" ]]; then
276+ log_info " Table $table_name exists, truncating..."
277+ if curl -s ${auth_params} --data " TRUNCATE TABLE ${CLICKHOUSE_DATABASE} .${table_name} " " ${clickhouse_url} " ; then
278+ log_success " Table $table_name truncated"
279+ else
280+ log_error " Failed to truncate table $table_name "
281+ exit 1
282+ fi
283+ else
284+ log_info " Creating new table: $table_name "
285+ local create_table_sql="
286+ CREATE TABLE ${CLICKHOUSE_DATABASE} .${table_name} (
287+ name String,
288+ version String,
289+ license String,
290+ inserted_at DateTime DEFAULT now()
291+ ) ENGINE = MergeTree()
292+ ORDER BY (name, version, license);
293+ "
294+
295+ if curl -s ${auth_params} --data " $create_table_sql " " ${clickhouse_url} " ; then
296+ log_success " Table $table_name created successfully"
297+ else
298+ log_error " Failed to create table $table_name "
299+ exit 1
300+ fi
301+ fi
302+ else
303+ log_error " Failed to check if table exists"
304+ exit 1
305+ fi
306+ }
307+
308+ insert_sbom_data () {
309+ local sbom_file=" $1 "
310+ local table_name=" $2 "
311+ local sbom_format=" $3 "
312+
313+ log_info " Extracting components from $sbom_format SBOM for ClickHouse"
314+
315+ # Build ClickHouse URL
316+ local clickhouse_url=" ${CLICKHOUSE_URL} "
317+ local auth_params=" "
318+
319+ if [[ -n " ${CLICKHOUSE_USERNAME:- } " && " ${CLICKHOUSE_USERNAME} " != " default" ]]; then
320+ auth_params=" --user ${CLICKHOUSE_USERNAME} "
321+ fi
322+
323+ if [[ -n " ${CLICKHOUSE_PASSWORD:- } " ]]; then
324+ auth_params=" ${auth_params} --password ${CLICKHOUSE_PASSWORD} "
325+ fi
326+
327+ # Create temporary file for data
328+ local data_file=" $temp_dir /clickhouse_data.tsv"
329+
330+ # Extract data based on SBOM format
331+ case " $sbom_format " in
332+ " cyclonedx" )
333+ # Extract from CycloneDX format
334+ jq -r '
335+ .components[]? // empty |
336+ [
337+ .name // "unknown",
338+ .version // "unknown",
339+ (.licenses[]?.license.id // .licenses[]?.license.name // .licenses[]?.expression // "unknown")
340+ ] | @tsv
341+ ' " $sbom_file " > " $data_file "
342+ ;;
343+ " spdx" |" spdxjson" )
344+ # Extract from SPDX format
345+ jq -r '
346+ .packages[]? // empty |
347+ select(.name != null) |
348+ [
349+ .name // "unknown",
350+ .versionInfo // "unknown",
351+ (.licenseDeclared // .licenseConcluded // "unknown")
352+ ] | @tsv
353+ ' " $sbom_file " > " $data_file "
354+ ;;
355+ * )
356+ log_error " Unsupported SBOM format for ClickHouse: $sbom_format "
357+ exit 1
358+ ;;
359+ esac
360+
361+ # Check if we have data to insert
362+ if [[ ! -s " $data_file " ]]; then
363+ log_warning " No component data found in SBOM"
364+ return
365+ fi
366+
367+ local component_count=$( wc -l < " $data_file " )
368+ log_info " Found $component_count components to insert"
369+
370+ # Insert data into ClickHouse
371+ if curl -s ${auth_params} \
372+ -H " Content-Type: text/tab-separated-values" \
373+ --data-binary " @$data_file " \
374+ " ${clickhouse_url} /?query=INSERT%20INTO%20${CLICKHOUSE_DATABASE} .${table_name} %20(name,%20version,%20license)%20FORMAT%20TSV" ; then
375+ log_success " Inserted $component_count components into ClickHouse table $table_name "
376+ else
377+ log_error " Failed to insert data into ClickHouse"
378+ exit 1
379+ fi
380+ }
381+
254382# Global variable for temp directory (so cleanup can access it)
255383temp_dir=" "
256384
@@ -317,6 +445,13 @@ main() {
317445
318446 log_success " SBOM processing completed successfully!"
319447 log_info " SBOM available at: s3://$S3_BUCKET /$s3_key "
448+
449+ if [[ -n " ${CLICKHOUSE_URL:- } " ]]; then
450+ local table_name=$( echo " $REPOSITORY " | sed ' s|[^a-zA-Z0-9]|_|g' | tr ' [:upper:]' ' [:lower:]' )
451+ setup_clickhouse_table " $table_name "
452+ insert_sbom_data " $processed_sbom " " $table_name " " $desired_format "
453+ log_info " Component data available in ClickHouse table: ${CLICKHOUSE_DATABASE} .${table_name} "
454+ fi
320455}
321456
322457# Run main function
0 commit comments