[go: up one dir, main page]

Skip to main content

TeamCity

Customers using TeamCity should use the Kusari CLI to integrate SBOM ingestion into their build configurations.

note

You need an API key to set this up.

Adding Secrets to TeamCity

TeamCity supports storing secrets as Password Parameters. These are encrypted at rest and masked in build logs.

Adding Parameters via UI

  1. Go to your TeamCity project or build configuration
  2. Navigate to Parameters
  3. Click Add new parameter and add the following:

First Parameter: Client ID

  • Name: env.KUSARI_CLIENT_ID
  • Kind: Environment variable (env.)
  • Value: your-client-id-here
  • Spec: Click Edit and set Type to password

Second Parameter: Client Secret

  • Name: env.KUSARI_CLIENT_SECRET
  • Kind: Environment variable (env.)
  • Value: your-client-secret-here
  • Spec: Click Edit and set Type to password
Password Parameters

Password type parameters are masked in build logs with asterisks and encrypted at rest. Never store credentials in Kotlin DSL files directly—use tokens instead.

Basic Usage (Build Steps)

Here's a basic example using TeamCity build steps:

Step 1: Install Dependencies

Add a Command Line build step:

#!/bin/bash
set -e

KUSARI_CLI_VERSION="0.17.1"

# Install wget if not available
apt-get update && apt-get install -y wget tar ca-certificates curl jq || \
yum install -y wget tar ca-certificates curl jq || \
apk add --no-cache wget tar ca-certificates curl jq

# Install kusari CLI
wget https://github.com/kusaridev/kusari-cli/releases/download/v${KUSARI_CLI_VERSION}/kusari-cli_${KUSARI_CLI_VERSION}_linux_amd64.tar.gz
wget https://github.com/kusaridev/kusari-cli/releases/download/v${KUSARI_CLI_VERSION}/kusari-cli_${KUSARI_CLI_VERSION}_checksums.txt
grep kusari-cli_${KUSARI_CLI_VERSION}_linux_amd64.tar.gz kusari-cli_${KUSARI_CLI_VERSION}_checksums.txt | sha256sum -c -
tar -xzf kusari-cli_${KUSARI_CLI_VERSION}_linux_amd64.tar.gz
chmod +x kusari
mv kusari /usr/local/bin/
kusari --version

# Install syft for SBOM generation
curl -sSfL https://raw.githubusercontent.com/anchore/syft/main/install.sh | sh -s -- -b /usr/local/bin

Step 2: Build and Generate SBOM

Add another Command Line build step:

#!/bin/bash
set -e

# Build your application
docker build --tag %system.teamcity.projectName%:latest --file Dockerfile .

# Generate SBOM
syft %system.teamcity.projectName%:latest -o cyclonedx-json --file sbom.json

Step 3: Upload SBOM

Add a final Command Line build step:

#!/bin/bash
set -e

KUSARI_TENANT_ENDPOINT="https://[tenant_name].api.us.kusari.cloud"

# Login to Kusari
kusari auth login --client-id="${KUSARI_CLIENT_ID}" --client-secret="${KUSARI_CLIENT_SECRET}"

# Upload SBOM to Kusari Platform
kusari platform upload \
--file-path="sbom.json" \
--tenant-endpoint="${KUSARI_TENANT_ENDPOINT}" \
--component-name="%system.teamcity.projectName%"

Kotlin DSL Configuration

For teams using Versioned Settings with Kotlin DSL:

.teamcity/settings.kts
import jetbrains.buildServer.configs.kotlin.*
import jetbrains.buildServer.configs.kotlin.buildSteps.script

version = "2024.12"

project {
buildType(BuildAndUploadSBOM)
}

object BuildAndUploadSBOM : BuildType({
name = "Build and Upload SBOM"

params {
password("env.KUSARI_CLIENT_ID", "credentialsJSON:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx")
password("env.KUSARI_CLIENT_SECRET", "credentialsJSON:yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy")
param("env.KUSARI_CLI_VERSION", "0.17.1")
param("env.KUSARI_TENANT_ENDPOINT", "https://[tenant_name].api.us.kusari.cloud")
}

vcs {
root(DslContext.settingsRoot)
}

steps {
script {
name = "Install Kusari CLI"
scriptContent = """
#!/bin/bash
set -e

wget https://github.com/kusaridev/kusari-cli/releases/download/v${'$'}{KUSARI_CLI_VERSION}/kusari-cli_${'$'}{KUSARI_CLI_VERSION}_linux_amd64.tar.gz
wget https://github.com/kusaridev/kusari-cli/releases/download/v${'$'}{KUSARI_CLI_VERSION}/kusari-cli_${'$'}{KUSARI_CLI_VERSION}_checksums.txt
grep kusari-cli_${'$'}{KUSARI_CLI_VERSION}_linux_amd64.tar.gz kusari-cli_${'$'}{KUSARI_CLI_VERSION}_checksums.txt | sha256sum -c -
tar -xzf kusari-cli_${'$'}{KUSARI_CLI_VERSION}_linux_amd64.tar.gz
chmod +x kusari
mv kusari /usr/local/bin/
kusari --version

# Install syft
curl -sSfL https://raw.githubusercontent.com/anchore/syft/main/install.sh | sh -s -- -b /usr/local/bin
""".trimIndent()
}

script {
name = "Build Docker Image"
scriptContent = """
#!/bin/bash
set -e
docker build --tag %system.teamcity.projectName%:latest --file Dockerfile .
""".trimIndent()
}

script {
name = "Generate and Upload SBOM"
scriptContent = """
#!/bin/bash
set -e

# Generate SBOM
syft %system.teamcity.projectName%:latest -o cyclonedx-json --file sbom.json

# Login to Kusari
kusari auth login --client-id="${'$'}{KUSARI_CLIENT_ID}" --client-secret="${'$'}{KUSARI_CLIENT_SECRET}"

# Upload SBOM
kusari platform upload \
--file-path="sbom.json" \
--tenant-endpoint="${'$'}{KUSARI_TENANT_ENDPOINT}" \
--component-name="%system.teamcity.projectName%"
""".trimIndent()
}
}

artifactRules = "sbom.json => sbom"
})
Secure Tokens

When using Kotlin DSL, use credentialsJSON: references to secure tokens stored in TeamCity. Never hardcode secrets in your settings.kts files.

Required Parameters

  • --file-path: Path to the SBOM file to upload
  • --tenant-endpoint: Kusari Platform tenant API endpoint (e.g., https://demo.api.us.kusari.cloud)
  • Client credentials: Set via kusari auth login using KUSARI_CLIENT_ID and KUSARI_CLIENT_SECRET environment variables

Optional Parameters

  • --component-name: Component name for grouping multiple SBOM subjects. If a component with this name does not exist, it will be created. Default: uses the subject name from the SBOM
  • --check-blocked-packages: Check if SBOMs contain dependencies from your blocked package list. If found, the program exits with non-zero status
  • --document-type: Type of SBOM: source, build, or image
  • --alias: Alias for the package for grouping
  • --sbom-subject-name-override: Override the SBOM subject name extracted from the document
  • --sbom-subject-version-override: Override the SBOM subject version extracted from the document

Complete Example with Multiple SBOMs

Kotlin DSL example for generating and uploading both image and build SBOMs:

.teamcity/settings.kts
import jetbrains.buildServer.configs.kotlin.*
import jetbrains.buildServer.configs.kotlin.buildSteps.script

version = "2024.12"

project {
buildType(BuildAndUploadMultipleSBOMs)
}

object BuildAndUploadMultipleSBOMs : BuildType({
name = "Build and Upload Multiple SBOMs"

params {
password("env.KUSARI_CLIENT_ID", "credentialsJSON:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx")
password("env.KUSARI_CLIENT_SECRET", "credentialsJSON:yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy")
param("env.KUSARI_CLI_VERSION", "0.17.1")
param("env.KUSARI_TENANT_ENDPOINT", "https://[tenant_name].api.us.kusari.cloud")
}

vcs {
root(DslContext.settingsRoot)
}

steps {
script {
name = "Install Tools"
scriptContent = """
#!/bin/bash
set -e

# Install Kusari CLI
wget https://github.com/kusaridev/kusari-cli/releases/download/v${'$'}{KUSARI_CLI_VERSION}/kusari-cli_${'$'}{KUSARI_CLI_VERSION}_linux_amd64.tar.gz
wget https://github.com/kusaridev/kusari-cli/releases/download/v${'$'}{KUSARI_CLI_VERSION}/kusari-cli_${'$'}{KUSARI_CLI_VERSION}_checksums.txt
grep kusari-cli_${'$'}{KUSARI_CLI_VERSION}_linux_amd64.tar.gz kusari-cli_${'$'}{KUSARI_CLI_VERSION}_checksums.txt | sha256sum -c -
tar -xzf kusari-cli_${'$'}{KUSARI_CLI_VERSION}_linux_amd64.tar.gz
chmod +x kusari
mv kusari /usr/local/bin/

# Install syft
curl -sSfL https://raw.githubusercontent.com/anchore/syft/main/install.sh | sh -s -- -b /usr/local/bin

# Install Go and cyclonedx-gomod
wget https://go.dev/dl/go1.23.3.linux-amd64.tar.gz
tar -C /usr/local -xzf go1.23.3.linux-amd64.tar.gz
export PATH=${'$'}PATH:/usr/local/go/bin
go install github.com/CycloneDX/cyclonedx-gomod/cmd/cyclonedx-gomod@latest
""".trimIndent()
}

script {
name = "Build and Generate SBOMs"
scriptContent = """
#!/bin/bash
set -e
export PATH=${'$'}PATH:/usr/local/go/bin:/root/go/bin

# Build Docker image
docker build --tag %system.teamcity.projectName%:latest --file Dockerfile .

# Generate image SBOM
echo "Generating image SBOM..."
syft %system.teamcity.projectName%:latest -o cyclonedx-json --file cyclonedx_image.sbom.json

# Generate build SBOM
echo "Generating build SBOM..."
cyclonedx-gomod app -licenses -json -output cyclonedx_build.sbom.json -main ./src
""".trimIndent()
}

script {
name = "Upload SBOMs to Kusari"
scriptContent = """
#!/bin/bash
set -e

# Login to Kusari
kusari auth login --client-id="${'$'}{KUSARI_CLIENT_ID}" --client-secret="${'$'}{KUSARI_CLIENT_SECRET}"

# Upload image SBOM
echo "Uploading image SBOM..."
kusari platform upload \
--file-path="cyclonedx_image.sbom.json" \
--tenant-endpoint="${'$'}{KUSARI_TENANT_ENDPOINT}" \
--document-type="image" \
--component-name="%system.teamcity.projectName%"

# Upload build SBOM
echo "Uploading build SBOM..."
kusari platform upload \
--file-path="cyclonedx_build.sbom.json" \
--tenant-endpoint="${'$'}{KUSARI_TENANT_ENDPOINT}" \
--document-type="build" \
--component-name="%system.teamcity.projectName%"
""".trimIndent()
}
}

artifactRules = """
cyclonedx_image.sbom.json => sbom
cyclonedx_build.sbom.json => sbom
""".trimIndent()
})

Example with Blocked Packages Check

Enable the --check-blocked-packages flag to validate that uploaded SBOMs don't contain dependencies from your blocked package list:

# Upload with blocked packages check
kusari platform upload \
--file-path="sbom.json" \
--tenant-endpoint="${KUSARI_TENANT_ENDPOINT}" \
--component-name="%system.teamcity.projectName%" \
--document-type="image" \
--check-blocked-packages

Example screenshot showing blocked packages found:

blocked_packages

note

Modification of the blocked packages can be done on the admin page

TeamCity Built-in Parameters

Useful TeamCity parameters for your SBOM uploads:

ParameterDescription
%system.teamcity.projectName%Name of the project
%build.number%Build number
%build.vcs.number%VCS revision (commit SHA)
%teamcity.build.branch%Branch name
%system.teamcity.buildConfName%Build configuration name

Full Documentation

For complete CLI documentation including all options and advanced configurations, see the Kusari CLI platform upload documentation.