diff --git a/.github/workflows/check-ta.yaml b/.github/workflows/check-ta.yaml new file mode 100644 index 000000000..f42d2f9d1 --- /dev/null +++ b/.github/workflows/check-ta.yaml @@ -0,0 +1,13 @@ +name: Validate PR - Trusted Artifact variants +'on': + pull_request: + branches: [main] +jobs: + go: + name: Check Trusted Artifact variants + runs-on: ubuntu-latest + steps: + - name: Check out code + uses: actions/checkout@v4 + - name: Check Trusted Artifact variants + run: hack/generate-ta-tasks.sh diff --git a/hack/generate-ta-tasks.sh b/hack/generate-ta-tasks.sh new file mode 100755 index 000000000..d0b4d48a6 --- /dev/null +++ b/hack/generate-ta-tasks.sh @@ -0,0 +1,58 @@ +#!/usr/bin/env bash + +set -o errexit +set -o nounset +set -o pipefail +set -o posix + +shopt -s globstar nullglob + +HACK_DIR="$(realpath "$(dirname "${BASH_SOURCE[0]}")")" +TASK_DIR="$(realpath "${HACK_DIR}/../task")" + +if ! command -v tash &> /dev/null; then + echo INFO: tash command is not available will download and use the latest version + tash_dir="$(mktemp -d)" + trap 'rm -rf ${tash_dir}' EXIT + tash_url=https://github.com/enterprise-contract/hacks/releases/download/latest/tash + echo INFO: downloading from ${tash_url} to "${tash_dir}" + curl --no-progress-meter --location --output "${tash_dir}/tash" "${tash_url}" + echo INFO: SHA256: "$(sha256sum "${tash_dir}/tash")" + chmod +x "${tash_dir}/tash" + tash() { + "${tash_dir}/tash" "$@" + } +fi + +declare -i changes=0 +emit() { + if [ "${GITHUB_ACTIONS:-false}" == "true" ]; then + printf "::error file=%s,line=1,col=0::%s\n" "$1" "$2" + else + printf "INFO: \033[1m%s\033[0m %s\n" "$1" "$2" + fi + changes=$((changes + 1)) +} + + +cd "${TASK_DIR}" +for recipe_path in **/recipe.yaml; do + task_path="${recipe_path%/recipe.yaml}/$(basename "${recipe_path%/*/*}").yaml" + tash "${recipe_path}" > "${task_path}" + readme_path="${recipe_path%/recipe.yaml}/README.md" + "${HACK_DIR}/generate-readme.sh" "${task_path}" > "${readme_path}" + if ! git diff --quiet HEAD "${task_path}"; then + emit "task/${task_path}" "file is out of date and has been updated" + fi + if ! git diff --quiet HEAD "${readme_path}"; then + emit "task/${readme_path}" "file is out of date and has been updated" + fi +done + +if [[ ${changes} -gt 0 ]]; then + if [ "${GITHUB_ACTIONS:-false}" == "true" ]; then + exit 1 + else + printf "INFO: \033[1mMake sure to include the regenerated files in your changeset\033[0m\n" + fi +fi diff --git a/task/buildah-oci-ta/0.1/README.md b/task/buildah-oci-ta/0.1/README.md index 734952879..6df7de9df 100644 --- a/task/buildah-oci-ta/0.1/README.md +++ b/task/buildah-oci-ta/0.1/README.md @@ -8,31 +8,33 @@ When prefetch-dependencies task was activated it is using its artifacts to run b ## Parameters |name|description|default value|required| |---|---|---|---| -|IMAGE|Reference of the image buildah will produce.||true| -|SOURCE_ARTIFACT|The trusted artifact URI containing the application source code.||true| -|CACHI2_ARTIFACT|The trusted artifact URI containing the prefetched dependencies.|""|false| -|DOCKERFILE|Path to the Dockerfile to build.|./Dockerfile|false| +|BUILD_ARGS|Array of --build-arg values ("arg=value" strings)|[]|false| +|BUILD_ARGS_FILE|Path to a file with build arguments, see https://www.mankier.com/1/buildah-build#--build-arg-file|""|false| +|CACHI2_ARTIFACT|The Trusted Artifact URI pointing to the artifact with the prefetched dependencies.|""|false| +|COMMIT_SHA|The image is built from this commit.|""|false| |CONTEXT|Path to the directory to use as context.|.|false| -|TLSVERIFY|Verify the TLS on the registry endpoint (for push/pull to a non-TLS registry)|true|false| +|DOCKERFILE|Path to the Dockerfile to build.|./Dockerfile|false| |DOCKER_AUTH|unused, should be removed in next task version|""|false| +|ENTITLEMENT_SECRET|Name of secret which contains the entitlement certificates|etc-pki-entitlement|false| |HERMETIC|Determines if build will be executed without network access.|false|false| -|PREFETCH_INPUT|In case it is not empty, the prefetched content should be made available to the build.|""|false| +|IMAGE|Reference of the image buildah will produce.||true| |IMAGE_EXPIRES_AFTER|Delete image tag after specified time. Empty means to keep the image tag. Time values could be something like 1h, 2d, 3w for hours, days, and weeks, respectively.|""|false| -|COMMIT_SHA|The image is built from this commit.|""|false| -|YUM_REPOS_D_SRC|Path in the git repository in which yum repository files are stored|repos.d|false| +|PREFETCH_INPUT|In case it is not empty, the prefetched content should be made available to the build.|""|false| +|SOURCE_ARTIFACT|The Trusted Artifact URI pointing to the artifact with the application source code.||true| +|TARGET_STAGE|Target stage in Dockerfile to build. If not specified, the Dockerfile is processed entirely to (and including) its last stage.|""|false| +|TLSVERIFY|Verify the TLS on the registry endpoint (for push/pull to a non-TLS registry)|true|false| |YUM_REPOS_D_FETCHED|Path in source workspace where dynamically-fetched repos are present|fetched.repos.d|false| +|YUM_REPOS_D_SRC|Path in the git repository in which yum repository files are stored|repos.d|false| |YUM_REPOS_D_TARGET|Target path on the container in which yum repository files should be made available|/etc/yum.repos.d|false| -|TARGET_STAGE|Target stage in Dockerfile to build. If not specified, the Dockerfile is processed entirely to (and including) its last stage.|""|false| -|ENTITLEMENT_SECRET|Name of secret which contains the entitlement certificates|etc-pki-entitlement|false| -|BUILD_ARGS|Array of --build-arg values ("arg=value" strings)|[]|false| -|BUILD_ARGS_FILE|Path to a file with build arguments, see https://www.mankier.com/1/buildah-build#--build-arg-file|""|false| +|caTrustConfigMapKey|The name of the key in the ConfigMap that contains the CA bundle data.|ca-bundle.crt|false| +|caTrustConfigMapName|The name of the ConfigMap to read CA bundle data from.|trusted-ca|false| ## Results |name|description| |---|---| +|BASE_IMAGES_DIGESTS|Digests of the base images used for build| |IMAGE_DIGEST|Digest of the image just built| |IMAGE_URL|Image repository where the built image was pushed| -|BASE_IMAGES_DIGESTS|Digests of the base images used for build| -|SBOM_JAVA_COMPONENTS_COUNT|The counting of Java components by publisher in JSON format| |JAVA_COMMUNITY_DEPENDENCIES|The Java dependencies that came from community sources such as Maven central.| +|SBOM_JAVA_COMPONENTS_COUNT|The counting of Java components by publisher in JSON format| diff --git a/task/buildah-oci-ta/0.1/buildah-oci-ta.yaml b/task/buildah-oci-ta/0.1/buildah-oci-ta.yaml index 1e4b56415..fb349fa64 100644 --- a/task/buildah-oci-ta/0.1/buildah-oci-ta.yaml +++ b/task/buildah-oci-ta/0.1/buildah-oci-ta.yaml @@ -2,13 +2,13 @@ apiVersion: tekton.dev/v1 kind: Task metadata: + name: buildah-oci-ta + annotations: + tekton.dev/pipelines.minVersion: 0.12.1 + tekton.dev/tags: image-build, appstudio, hacbs labels: app.kubernetes.io/version: "0.1" - build.appstudio.redhat.com/build_type: "docker" - annotations: - tekton.dev/pipelines.minVersion: "0.12.1" - tekton.dev/tags: "image-build, appstudio, hacbs" - name: buildah-oci-ta + build.appstudio.redhat.com/build_type: docker spec: description: |- Buildah task builds source code into a container image and pushes the image into container registry using buildah tool. @@ -16,459 +16,480 @@ spec: When [Java dependency rebuild](https://redhat-appstudio.github.io/docs.stonesoup.io/Documentation/main/cli/proc_enabled_java_dependencies.html) is enabled it triggers rebuilds of Java artifacts. When prefetch-dependencies task was activated it is using its artifacts to run build in hermetic environment. params: - - description: Reference of the image buildah will produce. - name: IMAGE - type: string - - description: The Trusted Artifact URI pointing to the artifact with the application source code. - name: SOURCE_ARTIFACT - type: string - - description: The Trusted Artifact URI pointing to the artifact with the prefetched dependencies. - name: CACHI2_ARTIFACT - type: string - default: "" - - default: ./Dockerfile - description: Path to the Dockerfile to build. - name: DOCKERFILE - type: string - - default: . - description: Path to the directory to use as context. - name: CONTEXT - type: string - - default: "true" - description: Verify the TLS on the registry endpoint (for push/pull to a non-TLS registry) - name: TLSVERIFY - type: string - - description: unused, should be removed in next task version - name: DOCKER_AUTH - type: string - default: "" - - default: "false" - description: Determines if build will be executed without network access. - name: HERMETIC - type: string - - default: "" - description: In case it is not empty, the prefetched content should be made available to the build. - name: PREFETCH_INPUT - type: string - - default: "" - description: Delete image tag after specified time. Empty means to keep the image tag. Time values could be something like 1h, 2d, 3w for hours, days, and weeks, respectively. - name: IMAGE_EXPIRES_AFTER - type: string - - name: COMMIT_SHA - description: The image is built from this commit. - type: string - default: "" - - name: YUM_REPOS_D_SRC - description: Path in the git repository in which yum repository files are stored - default: repos.d - - name: YUM_REPOS_D_FETCHED - description: Path in source workspace where dynamically-fetched repos are present - default: fetched.repos.d - - name: YUM_REPOS_D_TARGET - description: Target path on the container in which yum repository files should be made available - default: /etc/yum.repos.d - - name: TARGET_STAGE - description: Target stage in Dockerfile to build. If not specified, the Dockerfile is processed entirely to (and including) its last stage. - type: string - default: "" - - name: ENTITLEMENT_SECRET - description: Name of secret which contains the entitlement certificates - type: string - default: "etc-pki-entitlement" - - name: BUILD_ARGS - description: Array of --build-arg values ("arg=value" strings) - type: array - default: [] - - name: BUILD_ARGS_FILE - description: Path to a file with build arguments, see https://www.mankier.com/1/buildah-build#--build-arg-file - type: string - default: "" - - results: - - description: Digest of the image just built - name: IMAGE_DIGEST - - description: Image repository where the built image was pushed - name: IMAGE_URL - - description: Digests of the base images used for build - name: BASE_IMAGES_DIGESTS - - name: SBOM_JAVA_COMPONENTS_COUNT - description: The counting of Java components by publisher in JSON format - type: string - - name: JAVA_COMMUNITY_DEPENDENCIES - description: The Java dependencies that came from community sources such as Maven central. - stepTemplate: - env: - - name: BUILDAH_FORMAT - value: oci - - name: STORAGE_DRIVER - value: vfs - - name: HERMETIC - value: $(params.HERMETIC) + - name: BUILD_ARGS + description: Array of --build-arg values ("arg=value" strings) + type: array + default: [] + - name: BUILD_ARGS_FILE + description: Path to a file with build arguments, see https://www.mankier.com/1/buildah-build#--build-arg-file + type: string + default: "" + - name: CACHI2_ARTIFACT + description: The Trusted Artifact URI pointing to the artifact with + the prefetched dependencies. + type: string + default: "" + - name: COMMIT_SHA + description: The image is built from this commit. + type: string + default: "" - name: CONTEXT - value: $(params.CONTEXT) + description: Path to the directory to use as context. + type: string + default: . - name: DOCKERFILE - value: $(params.DOCKERFILE) + description: Path to the Dockerfile to build. + type: string + default: ./Dockerfile + - name: DOCKER_AUTH + description: unused, should be removed in next task version + type: string + default: "" + - name: ENTITLEMENT_SECRET + description: Name of secret which contains the entitlement certificates + type: string + default: etc-pki-entitlement + - name: HERMETIC + description: Determines if build will be executed without network access. + type: string + default: "false" - name: IMAGE - value: $(params.IMAGE) - - name: TLSVERIFY - value: $(params.TLSVERIFY) + description: Reference of the image buildah will produce. + type: string - name: IMAGE_EXPIRES_AFTER - value: $(params.IMAGE_EXPIRES_AFTER) - - name: YUM_REPOS_D_SRC - value: $(params.YUM_REPOS_D_SRC) + description: Delete image tag after specified time. Empty means to keep + the image tag. Time values could be something like 1h, 2d, 3w for + hours, days, and weeks, respectively. + type: string + default: "" + - name: PREFETCH_INPUT + description: In case it is not empty, the prefetched content should + be made available to the build. + type: string + default: "" + - name: SOURCE_ARTIFACT + description: The Trusted Artifact URI pointing to the artifact with + the application source code. + type: string + - name: TARGET_STAGE + description: Target stage in Dockerfile to build. If not specified, + the Dockerfile is processed entirely to (and including) its last stage. + type: string + default: "" + - name: TLSVERIFY + description: Verify the TLS on the registry endpoint (for push/pull + to a non-TLS registry) + type: string + default: "true" - name: YUM_REPOS_D_FETCHED - value: $(params.YUM_REPOS_D_FETCHED) + description: Path in source workspace where dynamically-fetched repos + are present + default: fetched.repos.d + - name: YUM_REPOS_D_SRC + description: Path in the git repository in which yum repository files + are stored + default: repos.d - name: YUM_REPOS_D_TARGET - value: $(params.YUM_REPOS_D_TARGET) - - name: TARGET_STAGE - value: $(params.TARGET_STAGE) - - name: ENTITLEMENT_SECRET - value: $(params.ENTITLEMENT_SECRET) - - name: BUILD_ARGS_FILE - value: $(params.BUILD_ARGS_FILE) + description: Target path on the container in which yum repository files + should be made available + default: /etc/yum.repos.d + - name: caTrustConfigMapKey + description: The name of the key in the ConfigMap that contains the + CA bundle data. + type: string + default: ca-bundle.crt + - name: caTrustConfigMapName + description: The name of the ConfigMap to read CA bundle data from. + type: string + default: trusted-ca + results: + - name: BASE_IMAGES_DIGESTS + description: Digests of the base images used for build + - name: IMAGE_DIGEST + description: Digest of the image just built + - name: IMAGE_URL + description: Image repository where the built image was pushed + - name: JAVA_COMMUNITY_DEPENDENCIES + description: The Java dependencies that came from community sources + such as Maven central. + - name: SBOM_JAVA_COMPONENTS_COUNT + description: The counting of Java components by publisher in JSON format + type: string + volumes: + - name: etc-pki-entitlement + secret: + optional: true + secretName: $(params.ENTITLEMENT_SECRET) + - name: shared + emptyDir: {} + - name: trusted-ca + configMap: + items: + - key: $(params.caTrustConfigMapKey) + path: ca-bundle.crt + name: $(params.caTrustConfigMapName) + optional: true + - name: varlibcontainers + emptyDir: {} + - name: workdir + emptyDir: {} + stepTemplate: + env: + - name: BUILDAH_FORMAT + value: oci + - name: BUILD_ARGS_FILE + value: $(params.BUILD_ARGS_FILE) + - name: CONTEXT + value: $(params.CONTEXT) + - name: DOCKERFILE + value: $(params.DOCKERFILE) + - name: ENTITLEMENT_SECRET + value: $(params.ENTITLEMENT_SECRET) + - name: HERMETIC + value: $(params.HERMETIC) + - name: IMAGE + value: $(params.IMAGE) + - name: IMAGE_EXPIRES_AFTER + value: $(params.IMAGE_EXPIRES_AFTER) + - name: STORAGE_DRIVER + value: vfs + - name: TARGET_STAGE + value: $(params.TARGET_STAGE) + - name: TLSVERIFY + value: $(params.TLSVERIFY) + - name: YUM_REPOS_D_FETCHED + value: $(params.YUM_REPOS_D_FETCHED) + - name: YUM_REPOS_D_SRC + value: $(params.YUM_REPOS_D_SRC) + - name: YUM_REPOS_D_TARGET + value: $(params.YUM_REPOS_D_TARGET) volumeMounts: - mountPath: /shared name: shared - mountPath: /var/workdir name: workdir steps: - - image: quay.io/redhat-appstudio/build-trusted-artifacts:latest@sha256:4e39fb97f4444c2946944482df47b39c5bbc195c54c6560b0647635f553ab23d - name: use-trusted-artifact - args: - - use - - $(params.SOURCE_ARTIFACT)=/var/workdir/source - - $(params.CACHI2_ARTIFACT)=/var/workdir/cachi2 - - image: quay.io/redhat-appstudio/buildah:v1.31.0@sha256:34f12c7b72ec2c28f1ded0c494b428df4791c909f1f174dd21b8ed6a57cf5ddb - name: build - computeResources: - limits: - memory: 4Gi - requests: - memory: 512Mi - cpu: 250m - env: - - name: COMMIT_SHA - value: $(params.COMMIT_SHA) - args: - - $(params.BUILD_ARGS[*]) - script: | - SOURCE_CODE_DIR=source - if [ -e "$SOURCE_CODE_DIR/$CONTEXT/$DOCKERFILE" ]; then - dockerfile_path="$(pwd)/$SOURCE_CODE_DIR/$CONTEXT/$DOCKERFILE" - elif [ -e "$SOURCE_CODE_DIR/$DOCKERFILE" ]; then - dockerfile_path="$(pwd)/$SOURCE_CODE_DIR/$DOCKERFILE" - elif echo "$DOCKERFILE" | grep -q "^https\?://"; then - echo "Fetch Dockerfile from $DOCKERFILE" - dockerfile_path=$(mktemp --suffix=-Dockerfile) - http_code=$(curl -s -L -w "%{http_code}" --output "$dockerfile_path" "$DOCKERFILE") - if [ $http_code != 200 ]; then - echo "No Dockerfile is fetched. Server responds $http_code" + - name: use-trusted-artifact + image: quay.io/redhat-appstudio/build-trusted-artifacts:latest@sha256:4e39fb97f4444c2946944482df47b39c5bbc195c54c6560b0647635f553ab23d + args: + - use + - $(params.SOURCE_ARTIFACT)=/var/workdir/source + - $(params.CACHI2_ARTIFACT)=/var/workdir/cachi2 + - name: build + image: quay.io/redhat-appstudio/buildah:v1.31.0@sha256:34f12c7b72ec2c28f1ded0c494b428df4791c909f1f174dd21b8ed6a57cf5ddb + args: + - $(params.BUILD_ARGS[*]) + workingDir: /var/workdir + volumeMounts: + - mountPath: /var/lib/containers + name: varlibcontainers + - mountPath: /entitlement + name: etc-pki-entitlement + - mountPath: /mnt/trusted-ca + name: trusted-ca + readOnly: true + env: + - name: COMMIT_SHA + value: $(params.COMMIT_SHA) + script: | + ca_bundle=/mnt/trusted-ca/ca-bundle.crt + if [ -f "$ca_bundle" ]; then + echo "INFO: Using mounted CA bundle: $ca_bundle" + cp -vf $ca_bundle /etc/pki/ca-trust/source/anchors + update-ca-trust + fi + + SOURCE_CODE_DIR=source + if [ -e "$SOURCE_CODE_DIR/$CONTEXT/$DOCKERFILE" ]; then + dockerfile_path="$(pwd)/$SOURCE_CODE_DIR/$CONTEXT/$DOCKERFILE" + elif [ -e "$SOURCE_CODE_DIR/$DOCKERFILE" ]; then + dockerfile_path="$(pwd)/$SOURCE_CODE_DIR/$DOCKERFILE" + elif echo "$DOCKERFILE" | grep -q "^https\?://"; then + echo "Fetch Dockerfile from $DOCKERFILE" + dockerfile_path=$(mktemp --suffix=-Dockerfile) + http_code=$(curl -s -L -w "%{http_code}" --output "$dockerfile_path" "$DOCKERFILE") + if [ $http_code != 200 ]; then + echo "No Dockerfile is fetched. Server responds $http_code" + exit 1 + fi + http_code=$(curl -s -L -w "%{http_code}" --output "$dockerfile_path.dockerignore.tmp" "$DOCKERFILE.dockerignore") + if [ $http_code = 200 ]; then + echo "Fetched .dockerignore from $DOCKERFILE.dockerignore" + mv "$dockerfile_path.dockerignore.tmp" $SOURCE_CODE_DIR/$CONTEXT/.dockerignore + fi + else + echo "Cannot find Dockerfile $DOCKERFILE" exit 1 fi - http_code=$(curl -s -L -w "%{http_code}" --output "$dockerfile_path.dockerignore.tmp" "$DOCKERFILE.dockerignore") - if [ $http_code = 200 ]; then - echo "Fetched .dockerignore from $DOCKERFILE.dockerignore" - mv "$dockerfile_path.dockerignore.tmp" $SOURCE_CODE_DIR/$CONTEXT/.dockerignore + if [ -n "$JVM_BUILD_WORKSPACE_ARTIFACT_CACHE_PORT_80_TCP_ADDR" ] && grep -q '^\s*RUN \(./\)\?mvn' "$dockerfile_path"; then + sed -i -e "s|^\s*RUN \(\(./\)\?mvn\)\(.*\)|RUN echo \"mirror.defaulthttp://$JVM_BUILD_WORKSPACE_ARTIFACT_CACHE_PORT_80_TCP_ADDR/v1/cache/default/0/*\" > /tmp/settings.yaml; \1 -s /tmp/settings.yaml \3|g" "$dockerfile_path" + touch /var/lib/containers/java fi - else - echo "Cannot find Dockerfile $DOCKERFILE" - exit 1 - fi - if [ -n "$JVM_BUILD_WORKSPACE_ARTIFACT_CACHE_PORT_80_TCP_ADDR" ] && grep -q '^\s*RUN \(./\)\?mvn' "$dockerfile_path"; then - sed -i -e "s|^\s*RUN \(\(./\)\?mvn\)\(.*\)|RUN echo \"mirror.defaulthttp://$JVM_BUILD_WORKSPACE_ARTIFACT_CACHE_PORT_80_TCP_ADDR/v1/cache/default/0/*\" > /tmp/settings.yaml; \1 -s /tmp/settings.yaml \3|g" "$dockerfile_path" - touch /var/lib/containers/java - fi - # Fixing group permission on /var/lib/containers - chown root:root /var/lib/containers + # Fixing group permission on /var/lib/containers + chown root:root /var/lib/containers - sed -i 's/^\s*short-name-mode\s*=\s*.*/short-name-mode = "disabled"/' /etc/containers/registries.conf + sed -i 's/^\s*short-name-mode\s*=\s*.*/short-name-mode = "disabled"/' /etc/containers/registries.conf - # Setting new namespace to run buildah - 2^32-2 - echo 'root:1:4294967294' | tee -a /etc/subuid >> /etc/subgid + # Setting new namespace to run buildah - 2^32-2 + echo 'root:1:4294967294' | tee -a /etc/subuid >>/etc/subgid - BUILDAH_ARGS=() + BUILDAH_ARGS=() - BASE_IMAGES=$(grep -i '^\s*FROM' "$dockerfile_path" | sed 's/--platform=\S*//' | awk '{print $2}') - if [ "${HERMETIC}" == "true" ]; then - BUILDAH_ARGS+=("--pull=never") - UNSHARE_ARGS="--net" - for image in $BASE_IMAGES; do - if [ "${image}" != "scratch" ]; then - unshare -Ufp --keep-caps -r --map-users 1,1,65536 --map-groups 1,1,65536 -- buildah pull $image - fi + BASE_IMAGES=$(grep -i '^\s*FROM' "$dockerfile_path" | sed 's/--platform=\S*//' | awk '{print $2}') + if [ "${HERMETIC}" == "true" ]; then + BUILDAH_ARGS+=("--pull=never") + UNSHARE_ARGS="--net" + for image in $BASE_IMAGES; do + if [ "${image}" != "scratch" ]; then + unshare -Ufp --keep-caps -r --map-users 1,1,65536 --map-groups 1,1,65536 -- buildah pull $image + fi + done + echo "Build will be executed with network isolation" + fi + + if [ -n "${TARGET_STAGE}" ]; then + BUILDAH_ARGS+=("--target=${TARGET_STAGE}") + fi + + if [ -n "${BUILD_ARGS_FILE}" ]; then + BUILDAH_ARGS+=("--build-arg-file=$(pwd)/$SOURCE_CODE_DIR/${BUILD_ARGS_FILE}") + fi + + for build_arg in "$@"; do + BUILDAH_ARGS+=("--build-arg=$build_arg") done - echo "Build will be executed with network isolation" - fi - - if [ -n "${TARGET_STAGE}" ]; then - BUILDAH_ARGS+=("--target=${TARGET_STAGE}") - fi - - if [ -n "${BUILD_ARGS_FILE}" ]; then - BUILDAH_ARGS+=("--build-arg-file=$(pwd)/$SOURCE_CODE_DIR/${BUILD_ARGS_FILE}") - fi - - for build_arg in "$@"; do - BUILDAH_ARGS+=("--build-arg=$build_arg") - done - - if [ -f "/var/workdir/cachi2/cachi2.env" ]; then - cp -r "/var/workdir/cachi2" /tmp/ - chmod -R go+rwX /tmp/cachi2 - VOLUME_MOUNTS="--volume /tmp/cachi2:/cachi2" - sed -i 's|^\s*run |RUN . /cachi2/cachi2.env \&\& \\\n |i' "$dockerfile_path" - echo "Prefetched content will be made available" - - prefetched_repo_for_my_arch="/tmp/cachi2/output/deps/rpm/$(uname -m)/repos.d/cachi2.repo" - if [ -f "$prefetched_repo_for_my_arch" ]; then - echo "Adding $prefetched_repo_for_my_arch to $YUM_REPOS_D_FETCHED" - mkdir -p "$YUM_REPOS_D_FETCHED" - cp --no-clobber "$prefetched_repo_for_my_arch" "$YUM_REPOS_D_FETCHED" + + if [ -f "/var/workdir/cachi2/cachi2.env" ]; then + cp -r "/var/workdir/cachi2" /tmp/ + chmod -R go+rwX /tmp/cachi2 + VOLUME_MOUNTS="--volume /tmp/cachi2:/cachi2" + sed -i 's|^\s*run |RUN . /cachi2/cachi2.env \&\& \\\n |i' "$dockerfile_path" + echo "Prefetched content will be made available" + + prefetched_repo_for_my_arch="/tmp/cachi2/output/deps/rpm/$(uname -m)/repos.d/cachi2.repo" + if [ -f "$prefetched_repo_for_my_arch" ]; then + echo "Adding $prefetched_repo_for_my_arch to $YUM_REPOS_D_FETCHED" + mkdir -p "$YUM_REPOS_D_FETCHED" + cp --no-clobber "$prefetched_repo_for_my_arch" "$YUM_REPOS_D_FETCHED" + fi fi - fi - - # if yum repofiles stored in git, copy them to mount point outside the source dir - if [ -d "${SOURCE_CODE_DIR}/${YUM_REPOS_D_SRC}" ]; then - mkdir -p ${YUM_REPOS_D_FETCHED} - cp -r ${SOURCE_CODE_DIR}/${YUM_REPOS_D_SRC}/* ${YUM_REPOS_D_FETCHED} - fi - - # if anything in the repofiles mount point (either fetched or from git), mount it - if [ -d "${YUM_REPOS_D_FETCHED}" ]; then - chmod -R go+rwX ${YUM_REPOS_D_FETCHED} - mount_point=$(realpath ${YUM_REPOS_D_FETCHED}) - VOLUME_MOUNTS="${VOLUME_MOUNTS} --volume ${mount_point}:${YUM_REPOS_D_TARGET}" - fi - - LABELS=( - "--label" "build-date=$(date -u +'%Y-%m-%dT%H:%M:%S')" - "--label" "architecture=$(uname -m)" - "--label" "vcs-type=git" - ) - [ -n "$COMMIT_SHA" ] && LABELS+=("--label" "vcs-ref=$COMMIT_SHA") - [ -n "$IMAGE_EXPIRES_AFTER" ] && LABELS+=("--label" "quay.expires-after=$IMAGE_EXPIRES_AFTER") - - ENTITLEMENT_PATH="/entitlement" - if [ -d "$ENTITLEMENT_PATH" ]; then - cp -r --preserve=mode "$ENTITLEMENT_PATH" /tmp/entitlement - VOLUME_MOUNTS="${VOLUME_MOUNTS} --volume /tmp/entitlement:/etc/pki/entitlement" - echo "Adding the entitlement to the build" - fi - - unshare -Uf $UNSHARE_ARGS --keep-caps -r --map-users 1,1,65536 --map-groups 1,1,65536 -w ${SOURCE_CODE_DIR}/$CONTEXT -- buildah build \ - $VOLUME_MOUNTS \ - "${BUILDAH_ARGS[@]}" \ - "${LABELS[@]}" \ - --tls-verify=$TLSVERIFY --no-cache \ - --ulimit nofile=4096:4096 \ - -f "$dockerfile_path" -t $IMAGE . - - container=$(buildah from --pull-never $IMAGE) - buildah mount $container | tee /shared/container_path - echo $container > /shared/container_name - - # Save the SBOM produced by Cachi2 so it can be merged into the final SBOM later - if [ -f "/tmp/cachi2/output/bom.json" ]; then - cp /tmp/cachi2/output/bom.json ./sbom-cachi2.json - fi - - # Expose base image digests - touch $(results.BASE_IMAGES_DIGESTS.path) - for image in $BASE_IMAGES; do - if [ "${image}" != "scratch" ]; then - buildah images --format '{{ .Name }}:{{ .Tag }}@{{ .Digest }}' --filter reference="$image" >> $(results.BASE_IMAGES_DIGESTS.path) + + # if yum repofiles stored in git, copy them to mount point outside the source dir + if [ -d "${SOURCE_CODE_DIR}/${YUM_REPOS_D_SRC}" ]; then + mkdir -p ${YUM_REPOS_D_FETCHED} + cp -r ${SOURCE_CODE_DIR}/${YUM_REPOS_D_SRC}/* ${YUM_REPOS_D_FETCHED} fi - done - # Needed to generate base images SBOM - echo "$BASE_IMAGES" > /var/workdir/base_images_from_dockerfile + # if anything in the repofiles mount point (either fetched or from git), mount it + if [ -d "${YUM_REPOS_D_FETCHED}" ]; then + chmod -R go+rwX ${YUM_REPOS_D_FETCHED} + mount_point=$(realpath ${YUM_REPOS_D_FETCHED}) + VOLUME_MOUNTS="${VOLUME_MOUNTS} --volume ${mount_point}:${YUM_REPOS_D_TARGET}" + fi - securityContext: - capabilities: - add: - - SETFCAP - volumeMounts: - - mountPath: /var/lib/containers - name: varlibcontainers - - mountPath: "/entitlement" - name: etc-pki-entitlement - - name: shared - mountPath: "/shared" - workingDir: /var/workdir - - - name: sbom-syft-generate - image: quay.io/redhat-appstudio/syft:v0.105.1@sha256:1910b829997650c696881e5fc2fc654ddf3184c27edb1b2024e9cb2ba51ac431 - # Respect Syft configuration if the user has it in the root of their repository - # (need to set the workdir, see https://github.com/anchore/syft/issues/2465) - workingDir: /var/workdir/source - script: | - echo "Running syft on the source directory" - syft dir:/var/workdir/source --output cyclonedx-json=/var/workdir/sbom-source.json - find $(cat /shared/container_path) -xtype l -delete - echo "Running syft on the image filesystem" - syft dir:$(cat /shared/container_path) --output cyclonedx-json=/var/workdir/sbom-image.json - volumeMounts: - - mountPath: /var/lib/containers - name: varlibcontainers - - name: shared - mountPath: "/shared" - - name: analyse-dependencies-java-sbom - image: quay.io/redhat-appstudio/hacbs-jvm-build-request-processor:127ee0c223a2b56a9bd20a6f2eaeed3bd6015f77 - script: | - if [ -f /var/lib/containers/java ]; then - /opt/jboss/container/java/run/run-java.sh analyse-dependencies path $(cat /shared/container_path) -s /var/workdir/sbom-image.json --task-run-name $(context.taskRun.name) --publishers $(results.SBOM_JAVA_COMPONENTS_COUNT.path) - sed -i 's/^/ /' $(results.SBOM_JAVA_COMPONENTS_COUNT.path) # Workaround for SRVKP-2875 - else - touch $(results.JAVA_COMMUNITY_DEPENDENCIES.path) - fi - volumeMounts: - - mountPath: /var/lib/containers - name: varlibcontainers - - name: shared - mountPath: "/shared" - securityContext: - runAsUser: 0 - - - name: merge-syft-sboms - image: registry.access.redhat.com/ubi9/python-39:1-172.1712567222@sha256:c96f839e927c52990143df4efb2872946fcd5de9e1ed2014947bb2cf3084c27a - script: | - #!/bin/python3 - import json - - # load SBOMs - with open("./sbom-image.json") as f: - image_sbom = json.load(f) - - with open("./sbom-source.json") as f: - source_sbom = json.load(f) - - # fetch unique components from available SBOMs - def get_identifier(component): - return component["name"] + '@' + component.get("version", "") - - image_sbom_components = image_sbom.get("components", []) - existing_components = [get_identifier(component) for component in image_sbom_components] - - source_sbom_components = source_sbom.get("components", []) - for component in source_sbom_components: - if get_identifier(component) not in existing_components: - image_sbom_components.append(component) - existing_components.append(get_identifier(component)) - - image_sbom_components.sort(key=lambda c: get_identifier(c)) - - # write the CycloneDX unified SBOM - with open("./sbom-cyclonedx.json", "w") as f: - json.dump(image_sbom, f, indent=4) - workingDir: /var/workdir - securityContext: - runAsUser: 0 - - - name: merge-cachi2-sbom - image: quay.io/redhat-appstudio/cachi2:0.7.0@sha256:1fc772aa3636fd0b43d62120d832e5913843e028e8cac42814b487c3a0a32bd8 - script: | - if [ -f "/var/workdir/sbom-cachi2.json" ]; then - echo "Merging contents of sbom-cachi2.json into sbom-cyclonedx.json" - /src/utils/merge_syft_sbom.py sbom-cachi2.json sbom-cyclonedx.json > sbom-temp.json - mv sbom-temp.json sbom-cyclonedx.json - else - echo "Skipping step since no Cachi2 SBOM was produced" - fi - workingDir: /var/workdir - securityContext: - runAsUser: 0 - - - name: create-purl-sbom - image: registry.access.redhat.com/ubi9/python-39:1-172.1712567222@sha256:c96f839e927c52990143df4efb2872946fcd5de9e1ed2014947bb2cf3084c27a - script: | - #!/bin/python3 - import json - - with open("./sbom-cyclonedx.json") as f: - cyclonedx_sbom = json.load(f) - - purls = [{"purl": component["purl"]} for component in cyclonedx_sbom.get("components", []) if "purl" in component] - purl_content = {"image_contents": {"dependencies": purls}} - - with open("sbom-purl.json", "w") as output_file: - json.dump(purl_content, output_file, indent=4) - workingDir: /var/workdir - securityContext: - runAsUser: 0 - - - name: create-base-images-sbom - image: quay.io/redhat-appstudio/base-images-sbom-script@sha256:667669e3def018f9dbb8eaf8868887a40bc07842221e9a98f6787edcff021840 - env: - - name: BASE_IMAGES_DIGESTS_PATH - value: $(results.BASE_IMAGES_DIGESTS.path) - script: | - python3 /app/base_images_sbom_script.py --sbom=sbom-cyclonedx.json --base-images-from-dockerfile=base_images_from_dockerfile --base-images-digests=$BASE_IMAGES_DIGESTS_PATH - workingDir: /var/workdir - securityContext: - runAsUser: 0 - - - name: inject-sbom-and-push - image: quay.io/redhat-appstudio/buildah:v1.31.0@sha256:34f12c7b72ec2c28f1ded0c494b428df4791c909f1f174dd21b8ed6a57cf5ddb - computeResources: {} - script: | - base_image_name=$(buildah inspect --format '{{ index .ImageAnnotations "org.opencontainers.image.base.name"}}' $IMAGE | cut -f1 -d'@') - base_image_digest=$(buildah inspect --format '{{ index .ImageAnnotations "org.opencontainers.image.base.digest"}}' $IMAGE) - container=$(buildah from --pull-never $IMAGE) - buildah copy $container sbom-cyclonedx.json sbom-purl.json /root/buildinfo/content_manifests/ - buildah config -a org.opencontainers.image.base.name=${base_image_name} -a org.opencontainers.image.base.digest=${base_image_digest} $container - buildah commit $container $IMAGE - - status=-1 - max_run=5 - sleep_sec=10 - for run in $(seq 1 $max_run); do - status=0 - [ "$run" -gt 1 ] && sleep $sleep_sec - echo "Pushing sbom image to registry" - buildah push \ - --tls-verify=$TLSVERIFY \ - --digestfile /var/workdir/image-digest $IMAGE \ - docker://$IMAGE && break || status=$? - done - if [ "$status" -ne 0 ]; then - echo "Failed to push sbom image to registry after ${max_run} tries" - exit 1 - fi + LABELS=( + "--label" "build-date=$(date -u +'%Y-%m-%dT%H:%M:%S')" + "--label" "architecture=$(uname -m)" + "--label" "vcs-type=git" + ) + [ -n "$COMMIT_SHA" ] && LABELS+=("--label" "vcs-ref=$COMMIT_SHA") + [ -n "$IMAGE_EXPIRES_AFTER" ] && LABELS+=("--label" "quay.expires-after=$IMAGE_EXPIRES_AFTER") + + ENTITLEMENT_PATH="/entitlement" + if [ -d "$ENTITLEMENT_PATH" ]; then + cp -r --preserve=mode "$ENTITLEMENT_PATH" /tmp/entitlement + VOLUME_MOUNTS="${VOLUME_MOUNTS} --volume /tmp/entitlement:/etc/pki/entitlement" + echo "Adding the entitlement to the build" + fi - cat "/var/workdir"/image-digest | tee $(results.IMAGE_DIGEST.path) - echo -n "$IMAGE" | tee $(results.IMAGE_URL.path) + unshare -Uf $UNSHARE_ARGS --keep-caps -r --map-users 1,1,65536 --map-groups 1,1,65536 -w ${SOURCE_CODE_DIR}/$CONTEXT -- buildah build \ + $VOLUME_MOUNTS \ + "${BUILDAH_ARGS[@]}" \ + "${LABELS[@]}" \ + --tls-verify=$TLSVERIFY --no-cache \ + --ulimit nofile=4096:4096 \ + -f "$dockerfile_path" -t $IMAGE . + + container=$(buildah from --pull-never $IMAGE) + buildah mount $container | tee /shared/container_path + echo $container >/shared/container_name + + # Save the SBOM produced by Cachi2 so it can be merged into the final SBOM later + if [ -f "/tmp/cachi2/output/bom.json" ]; then + cp /tmp/cachi2/output/bom.json ./sbom-cachi2.json + fi - securityContext: - runAsUser: 0 - capabilities: - add: - - SETFCAP - volumeMounts: - - mountPath: /var/lib/containers - name: varlibcontainers - workingDir: /var/workdir - - - name: upload-sbom - image: quay.io/redhat-appstudio/cosign:v2.1.1@sha256:c883d6f8d39148f2cea71bff4622d196d89df3e510f36c140c097b932f0dd5d5 - args: - - attach - - sbom - - --sbom - - sbom-cyclonedx.json - - --type - - cyclonedx - - $(params.IMAGE) - workingDir: /var/workdir + # Expose base image digests + touch $(results.BASE_IMAGES_DIGESTS.path) + for image in $BASE_IMAGES; do + if [ "${image}" != "scratch" ]; then + buildah images --format '{{ .Name }}:{{ .Tag }}@{{ .Digest }}' --filter reference="$image" >>$( results.BASE_IMAGES_DIGESTS.path) + fi + done - volumes: - - name: varlibcontainers - emptyDir: {} - - name: shared - emptyDir: {} - - name: workdir - emptyDir: {} - - name: etc-pki-entitlement - secret: - secretName: $(params.ENTITLEMENT_SECRET) - optional: true + # Needed to generate base images SBOM + echo "$BASE_IMAGES" >/var/workdir/base_images_from_dockerfile + computeResources: + limits: + memory: 4Gi + requests: + cpu: 250m + memory: 512Mi + securityContext: + capabilities: + add: + - SETFCAP + - name: sbom-syft-generate + image: quay.io/redhat-appstudio/syft:v0.105.1@sha256:1910b829997650c696881e5fc2fc654ddf3184c27edb1b2024e9cb2ba51ac431 + workingDir: /var/workdir/source + volumeMounts: + - mountPath: /var/lib/containers + name: varlibcontainers + - mountPath: /shared + name: shared + script: | + echo "Running syft on the source directory" + syft dir:/var/workdir/source --output cyclonedx-json=/var/workdir/sbom-source.json + find $(cat /shared/container_path) -xtype l -delete + echo "Running syft on the image filesystem" + syft dir:$(cat /shared/container_path) --output cyclonedx-json=/var/workdir/sbom-image.json + - name: analyse-dependencies-java-sbom + image: quay.io/redhat-appstudio/hacbs-jvm-build-request-processor:127ee0c223a2b56a9bd20a6f2eaeed3bd6015f77 + volumeMounts: + - mountPath: /var/lib/containers + name: varlibcontainers + - mountPath: /shared + name: shared + script: | + if [ -f /var/lib/containers/java ]; then + /opt/jboss/container/java/run/run-java.sh analyse-dependencies path $(cat /shared/container_path) -s /var/workdir/sbom-image.json --task-run-name $(context.taskRun.name) --publishers $(results.SBOM_JAVA_COMPONENTS_COUNT.path) + sed -i 's/^/ /' $(results.SBOM_JAVA_COMPONENTS_COUNT.path) # Workaround for SRVKP-2875 + else + touch $(results.JAVA_COMMUNITY_DEPENDENCIES.path) + fi + securityContext: + runAsUser: 0 + - name: merge-syft-sboms + image: registry.access.redhat.com/ubi9/python-39:1-172.1712567222@sha256:c96f839e927c52990143df4efb2872946fcd5de9e1ed2014947bb2cf3084c27a + workingDir: /var/workdir + script: | + #!/bin/python3 + import json + + # load SBOMs + with open("./sbom-image.json") as f: + image_sbom = json.load(f) + + with open("./sbom-source.json") as f: + source_sbom = json.load(f) + + # fetch unique components from available SBOMs + def get_identifier(component): + return component["name"] + '@' + component.get("version", "") + + image_sbom_components = image_sbom.get("components", []) + existing_components = [get_identifier(component) for component in image_sbom_components] + + source_sbom_components = source_sbom.get("components", []) + for component in source_sbom_components: + if get_identifier(component) not in existing_components: + image_sbom_components.append(component) + existing_components.append(get_identifier(component)) + + image_sbom_components.sort(key=lambda c: get_identifier(c)) + + # write the CycloneDX unified SBOM + with open("./sbom-cyclonedx.json", "w") as f: + json.dump(image_sbom, f, indent=4) + securityContext: + runAsUser: 0 + - name: merge-cachi2-sbom + image: quay.io/redhat-appstudio/cachi2:0.7.0@sha256:1fc772aa3636fd0b43d62120d832e5913843e028e8cac42814b487c3a0a32bd8 + workingDir: /var/workdir + script: | + if [ -f "sbom-cachi2.json" ]; then + echo "Merging contents of sbom-cachi2.json into sbom-cyclonedx.json" + /src/utils/merge_syft_sbom.py sbom-cachi2.json sbom-cyclonedx.json >sbom-temp.json + mv sbom-temp.json sbom-cyclonedx.json + else + echo "Skipping step since no Cachi2 SBOM was produced" + fi + securityContext: + runAsUser: 0 + - name: create-purl-sbom + image: registry.access.redhat.com/ubi9/python-39:1-172.1712567222@sha256:c96f839e927c52990143df4efb2872946fcd5de9e1ed2014947bb2cf3084c27a + workingDir: /var/workdir + script: | + #!/bin/python3 + import json + + with open("./sbom-cyclonedx.json") as f: + cyclonedx_sbom = json.load(f) + + purls = [{"purl": component["purl"]} for component in cyclonedx_sbom.get("components", []) if "purl" in component] + purl_content = {"image_contents": {"dependencies": purls}} + + with open("sbom-purl.json", "w") as output_file: + json.dump(purl_content, output_file, indent=4) + securityContext: + runAsUser: 0 + - name: create-base-images-sbom + image: quay.io/redhat-appstudio/base-images-sbom-script@sha256:667669e3def018f9dbb8eaf8868887a40bc07842221e9a98f6787edcff021840 + workingDir: /var/workdir + env: + - name: BASE_IMAGES_DIGESTS_PATH + value: $(results.BASE_IMAGES_DIGESTS.path) + script: | + python3 /app/base_images_sbom_script.py --sbom=sbom-cyclonedx.json --base-images-from-dockerfile=base_images_from_dockerfile --base-images-digests=$BASE_IMAGES_DIGESTS_PATH + securityContext: + runAsUser: 0 + - name: inject-sbom-and-push + image: quay.io/redhat-appstudio/buildah:v1.31.0@sha256:34f12c7b72ec2c28f1ded0c494b428df4791c909f1f174dd21b8ed6a57cf5ddb + workingDir: /var/workdir + volumeMounts: + - mountPath: /var/lib/containers + name: varlibcontainers + script: | + base_image_name=$(buildah inspect --format '{{ index .ImageAnnotations "org.opencontainers.image.base.name"}}' $IMAGE | cut -f1 -d'@') + base_image_digest=$(buildah inspect --format '{{ index .ImageAnnotations "org.opencontainers.image.base.digest"}}' $IMAGE) + container=$(buildah from --pull-never $IMAGE) + buildah copy $container sbom-cyclonedx.json sbom-purl.json /root/buildinfo/content_manifests/ + buildah config -a org.opencontainers.image.base.name=${base_image_name} -a org.opencontainers.image.base.digest=${base_image_digest} $container + buildah commit $container $IMAGE + + status=-1 + max_run=5 + sleep_sec=10 + for run in $(seq 1 $max_run); do + status=0 + [ "$run" -gt 1 ] && sleep $sleep_sec + echo "Pushing sbom image to registry" + buildah push \ + --tls-verify=$TLSVERIFY \ + --digestfile /var/workdir/image-digest $IMAGE \ + docker://$IMAGE && break || status=$? + done + if [ "$status" -ne 0 ]; then + echo "Failed to push sbom image to registry after ${max_run} tries" + exit 1 + fi + + cat "/var/workdir"/image-digest | tee $(results.IMAGE_DIGEST.path) + echo -n "$IMAGE" | tee $(results.IMAGE_URL.path) + securityContext: + capabilities: + add: + - SETFCAP + runAsUser: 0 + - name: upload-sbom + image: quay.io/redhat-appstudio/cosign:v2.1.1@sha256:c883d6f8d39148f2cea71bff4622d196d89df3e510f36c140c097b932f0dd5d5 + args: + - attach + - sbom + - --sbom + - sbom-cyclonedx.json + - --type + - cyclonedx + - $(params.IMAGE) + workingDir: /var/workdir diff --git a/task/buildah-oci-ta/0.1/recipe.yaml b/task/buildah-oci-ta/0.1/recipe.yaml new file mode 100644 index 000000000..97d348d20 --- /dev/null +++ b/task/buildah-oci-ta/0.1/recipe.yaml @@ -0,0 +1,18 @@ +--- +base: ../../buildah/0.1/buildah.yaml +removeParams: + - BUILDER_IMAGE +add: + - use-source + - use-cachi2 +removeWorkspaces: + - source +replacements: + workspaces.source.path: /var/workdir +regexReplacements: + "/workspace(/.*)": /var/workdir$1 +description: |- + Buildah task builds source code into a container image and pushes the image into container registry using buildah tool. + In addition it generates a SBOM file, injects the SBOM file into final container image and pushes the SBOM file as separate image using cosign tool. + When [Java dependency rebuild](https://redhat-appstudio.github.io/docs.stonesoup.io/Documentation/main/cli/proc_enabled_java_dependencies.html) is enabled it triggers rebuilds of Java artifacts. + When prefetch-dependencies task was activated it is using its artifacts to run build in hermetic environment. diff --git a/task/buildah-remote-oci-ta/0.1/buildah-remote-oci-ta.yaml b/task/buildah-remote-oci-ta/0.1/buildah-remote-oci-ta.yaml index b936e2c26..4fb4f8e57 100644 --- a/task/buildah-remote-oci-ta/0.1/buildah-remote-oci-ta.yaml +++ b/task/buildah-remote-oci-ta/0.1/buildah-remote-oci-ta.yaml @@ -16,43 +16,45 @@ spec: When [Java dependency rebuild](https://redhat-appstudio.github.io/docs.stonesoup.io/Documentation/main/cli/proc_enabled_java_dependencies.html) is enabled it triggers rebuilds of Java artifacts. When prefetch-dependencies task was activated it is using its artifacts to run build in hermetic environment. params: - - description: Reference of the image buildah will produce. - name: IMAGE - type: string - - description: The Trusted Artifact URI pointing to the artifact with the application - source code. - name: SOURCE_ARTIFACT + - default: [] + description: Array of --build-arg values ("arg=value" strings) + name: BUILD_ARGS + type: array + - default: "" + description: Path to a file with build arguments, see https://www.mankier.com/1/buildah-build#--build-arg-file + name: BUILD_ARGS_FILE type: string - default: "" description: The Trusted Artifact URI pointing to the artifact with the prefetched dependencies. name: CACHI2_ARTIFACT type: string - - default: ./Dockerfile - description: Path to the Dockerfile to build. - name: DOCKERFILE + - default: "" + description: The image is built from this commit. + name: COMMIT_SHA type: string - default: . description: Path to the directory to use as context. name: CONTEXT type: string - - default: "true" - description: Verify the TLS on the registry endpoint (for push/pull to a non-TLS - registry) - name: TLSVERIFY + - default: ./Dockerfile + description: Path to the Dockerfile to build. + name: DOCKERFILE type: string - default: "" description: unused, should be removed in next task version name: DOCKER_AUTH type: string + - default: etc-pki-entitlement + description: Name of secret which contains the entitlement certificates + name: ENTITLEMENT_SECRET + type: string - default: "false" description: Determines if build will be executed without network access. name: HERMETIC type: string - - default: "" - description: In case it is not empty, the prefetched content should be made available - to the build. - name: PREFETCH_INPUT + - description: Reference of the image buildah will produce. + name: IMAGE type: string - default: "" description: Delete image tag after specified time. Empty means to keep the image @@ -61,83 +63,90 @@ spec: name: IMAGE_EXPIRES_AFTER type: string - default: "" - description: The image is built from this commit. - name: COMMIT_SHA + description: In case it is not empty, the prefetched content should be made available + to the build. + name: PREFETCH_INPUT + type: string + - description: The Trusted Artifact URI pointing to the artifact with the application + source code. + name: SOURCE_ARTIFACT + type: string + - default: "" + description: Target stage in Dockerfile to build. If not specified, the Dockerfile + is processed entirely to (and including) its last stage. + name: TARGET_STAGE + type: string + - default: "true" + description: Verify the TLS on the registry endpoint (for push/pull to a non-TLS + registry) + name: TLSVERIFY type: string - - default: repos.d - description: Path in the git repository in which yum repository files are stored - name: YUM_REPOS_D_SRC - default: fetched.repos.d description: Path in source workspace where dynamically-fetched repos are present name: YUM_REPOS_D_FETCHED + - default: repos.d + description: Path in the git repository in which yum repository files are stored + name: YUM_REPOS_D_SRC - default: /etc/yum.repos.d description: Target path on the container in which yum repository files should be made available name: YUM_REPOS_D_TARGET - - default: "" - description: Target stage in Dockerfile to build. If not specified, the Dockerfile - is processed entirely to (and including) its last stage. - name: TARGET_STAGE + - default: ca-bundle.crt + description: The name of the key in the ConfigMap that contains the CA bundle + data. + name: caTrustConfigMapKey type: string - - default: etc-pki-entitlement - description: Name of secret which contains the entitlement certificates - name: ENTITLEMENT_SECRET - type: string - - default: [] - description: Array of --build-arg values ("arg=value" strings) - name: BUILD_ARGS - type: array - - default: "" - description: Path to a file with build arguments, see https://www.mankier.com/1/buildah-build#--build-arg-file - name: BUILD_ARGS_FILE + - default: trusted-ca + description: The name of the ConfigMap to read CA bundle data from. + name: caTrustConfigMapName type: string - description: The platform to build on name: PLATFORM type: string results: + - description: Digests of the base images used for build + name: BASE_IMAGES_DIGESTS - description: Digest of the image just built name: IMAGE_DIGEST - description: Image repository where the built image was pushed name: IMAGE_URL - - description: Digests of the base images used for build - name: BASE_IMAGES_DIGESTS - - description: The counting of Java components by publisher in JSON format - name: SBOM_JAVA_COMPONENTS_COUNT - type: string - description: The Java dependencies that came from community sources such as Maven central. name: JAVA_COMMUNITY_DEPENDENCIES + - description: The counting of Java components by publisher in JSON format + name: SBOM_JAVA_COMPONENTS_COUNT + type: string stepTemplate: computeResources: {} env: - name: BUILDAH_FORMAT value: oci - - name: STORAGE_DRIVER - value: vfs - - name: HERMETIC - value: $(params.HERMETIC) + - name: BUILD_ARGS_FILE + value: $(params.BUILD_ARGS_FILE) - name: CONTEXT value: $(params.CONTEXT) - name: DOCKERFILE value: $(params.DOCKERFILE) + - name: ENTITLEMENT_SECRET + value: $(params.ENTITLEMENT_SECRET) + - name: HERMETIC + value: $(params.HERMETIC) - name: IMAGE value: $(params.IMAGE) - - name: TLSVERIFY - value: $(params.TLSVERIFY) - name: IMAGE_EXPIRES_AFTER value: $(params.IMAGE_EXPIRES_AFTER) - - name: YUM_REPOS_D_SRC - value: $(params.YUM_REPOS_D_SRC) + - name: STORAGE_DRIVER + value: vfs + - name: TARGET_STAGE + value: $(params.TARGET_STAGE) + - name: TLSVERIFY + value: $(params.TLSVERIFY) - name: YUM_REPOS_D_FETCHED value: $(params.YUM_REPOS_D_FETCHED) + - name: YUM_REPOS_D_SRC + value: $(params.YUM_REPOS_D_SRC) - name: YUM_REPOS_D_TARGET value: $(params.YUM_REPOS_D_TARGET) - - name: TARGET_STAGE - value: $(params.TARGET_STAGE) - - name: ENTITLEMENT_SECRET - value: $(params.ENTITLEMENT_SECRET) - - name: BUILD_ARGS_FILE - value: $(params.BUILD_ARGS_FILE) - name: BUILDER_IMAGE value: quay.io/redhat-appstudio/buildah:v1.31.0@sha256:34f12c7b72ec2c28f1ded0c494b428df4791c909f1f174dd21b8ed6a57cf5ddb volumeMounts: @@ -197,6 +206,7 @@ spec: rsync -ra /shared/ "$SSH_HOST:$BUILD_DIR/volumes/shared/" rsync -ra /var/workdir/ "$SSH_HOST:$BUILD_DIR/volumes/workdir/" rsync -ra /entitlement/ "$SSH_HOST:$BUILD_DIR/volumes/etc-pki-entitlement/" + rsync -ra /mnt/trusted-ca/ "$SSH_HOST:$BUILD_DIR/volumes/trusted-ca/" rsync -ra "$HOME/.docker/" "$SSH_HOST:$BUILD_DIR/.docker/" rsync -ra "/tekton/results/" "$SSH_HOST:$BUILD_DIR/tekton-results/" cat >scripts/script-build.sh <<'REMOTESSHEOF' @@ -204,6 +214,13 @@ spec: set -o verbose set -e cd /var/workdir + ca_bundle=/mnt/trusted-ca/ca-bundle.crt + if [ -f "$ca_bundle" ]; then + echo "INFO: Using mounted CA bundle: $ca_bundle" + cp -vf $ca_bundle /etc/pki/ca-trust/source/anchors + update-ca-trust + fi + SOURCE_CODE_DIR=source if [ -e "$SOURCE_CODE_DIR/$CONTEXT/$DOCKERFILE" ]; then dockerfile_path="$(pwd)/$SOURCE_CODE_DIR/$CONTEXT/$DOCKERFILE" @@ -237,7 +254,7 @@ spec: sed -i 's/^\s*short-name-mode\s*=\s*.*/short-name-mode = "disabled"/' /etc/containers/registries.conf # Setting new namespace to run buildah - 2^32-2 - echo 'root:1:4294967294' | tee -a /etc/subuid >> /etc/subgid + echo 'root:1:4294967294' | tee -a /etc/subuid >>/etc/subgid BUILDAH_ARGS=() @@ -318,7 +335,7 @@ spec: container=$(buildah from --pull-never $IMAGE) buildah mount $container | tee /shared/container_path - echo $container > /shared/container_name + echo $container >/shared/container_name # Save the SBOM produced by Cachi2 so it can be merged into the final SBOM later if [ -f "/tmp/cachi2/output/bom.json" ]; then @@ -329,12 +346,12 @@ spec: touch $(results.BASE_IMAGES_DIGESTS.path) for image in $BASE_IMAGES; do if [ "${image}" != "scratch" ]; then - buildah images --format '{{ .Name }}:{{ .Tag }}@{{ .Digest }}' --filter reference="$image" >> $(results.BASE_IMAGES_DIGESTS.path) + buildah images --format '{{ .Name }}:{{ .Tag }}@{{ .Digest }}' --filter reference="$image" >>$( results.BASE_IMAGES_DIGESTS.path) fi done # Needed to generate base images SBOM - echo "$BASE_IMAGES" > /var/workdir/base_images_from_dockerfile + echo "$BASE_IMAGES" >/var/workdir/base_images_from_dockerfile buildah push "$IMAGE" oci:rhtap-final-image REMOTESSHEOF @@ -342,23 +359,24 @@ spec: rsync -ra scripts "$SSH_HOST:$BUILD_DIR" ssh $SSH_ARGS "$SSH_HOST" $PORT_FORWARD podman run $PODMAN_PORT_FORWARD \ -e BUILDAH_FORMAT="$BUILDAH_FORMAT" \ - -e STORAGE_DRIVER="$STORAGE_DRIVER" \ - -e HERMETIC="$HERMETIC" \ + -e BUILD_ARGS_FILE="$BUILD_ARGS_FILE" \ -e CONTEXT="$CONTEXT" \ -e DOCKERFILE="$DOCKERFILE" \ + -e ENTITLEMENT_SECRET="$ENTITLEMENT_SECRET" \ + -e HERMETIC="$HERMETIC" \ -e IMAGE="$IMAGE" \ - -e TLSVERIFY="$TLSVERIFY" \ -e IMAGE_EXPIRES_AFTER="$IMAGE_EXPIRES_AFTER" \ - -e YUM_REPOS_D_SRC="$YUM_REPOS_D_SRC" \ + -e STORAGE_DRIVER="$STORAGE_DRIVER" \ + -e TARGET_STAGE="$TARGET_STAGE" \ + -e TLSVERIFY="$TLSVERIFY" \ -e YUM_REPOS_D_FETCHED="$YUM_REPOS_D_FETCHED" \ + -e YUM_REPOS_D_SRC="$YUM_REPOS_D_SRC" \ -e YUM_REPOS_D_TARGET="$YUM_REPOS_D_TARGET" \ - -e TARGET_STAGE="$TARGET_STAGE" \ - -e ENTITLEMENT_SECRET="$ENTITLEMENT_SECRET" \ - -e BUILD_ARGS_FILE="$BUILD_ARGS_FILE" \ -e COMMIT_SHA="$COMMIT_SHA" \ -v "$BUILD_DIR/volumes/shared:/shared:Z" \ -v "$BUILD_DIR/volumes/workdir:/var/workdir:Z" \ -v "$BUILD_DIR/volumes/etc-pki-entitlement:/entitlement:Z" \ + -v "$BUILD_DIR/volumes/trusted-ca:/mnt/trusted-ca:Z" \ -v "$BUILD_DIR/.docker/:/root/.docker:Z" \ -v "$BUILD_DIR/tekton-results/:/tekton/results:Z" \ -v $BUILD_DIR/scripts:/script:Z \ @@ -381,8 +399,9 @@ spec: name: varlibcontainers - mountPath: /entitlement name: etc-pki-entitlement - - mountPath: /shared - name: shared + - mountPath: /mnt/trusted-ca + name: trusted-ca + readOnly: true - mountPath: /ssh name: ssh readOnly: true @@ -458,9 +477,9 @@ spec: image: quay.io/redhat-appstudio/cachi2:0.7.0@sha256:1fc772aa3636fd0b43d62120d832e5913843e028e8cac42814b487c3a0a32bd8 name: merge-cachi2-sbom script: | - if [ -f "/var/workdir/sbom-cachi2.json" ]; then + if [ -f "sbom-cachi2.json" ]; then echo "Merging contents of sbom-cachi2.json into sbom-cyclonedx.json" - /src/utils/merge_syft_sbom.py sbom-cachi2.json sbom-cyclonedx.json > sbom-temp.json + /src/utils/merge_syft_sbom.py sbom-cachi2.json sbom-cyclonedx.json >sbom-temp.json mv sbom-temp.json sbom-cyclonedx.json else echo "Skipping step since no Cachi2 SBOM was produced" @@ -549,16 +568,23 @@ spec: name: upload-sbom workingDir: /var/workdir volumes: - - emptyDir: {} - name: varlibcontainers - - emptyDir: {} - name: shared - - emptyDir: {} - name: workdir - name: etc-pki-entitlement secret: optional: true secretName: $(params.ENTITLEMENT_SECRET) + - emptyDir: {} + name: shared + - configMap: + items: + - key: $(params.caTrustConfigMapKey) + path: ca-bundle.crt + name: $(params.caTrustConfigMapName) + optional: true + name: trusted-ca + - emptyDir: {} + name: varlibcontainers + - emptyDir: {} + name: workdir - name: ssh secret: optional: false diff --git a/task/git-clone-oci-ta/0.1/README.md b/task/git-clone-oci-ta/0.1/README.md index fe1cbd9a9..d87ea24e7 100644 --- a/task/git-clone-oci-ta/0.1/README.md +++ b/task/git-clone-oci-ta/0.1/README.md @@ -5,34 +5,34 @@ The git-clone-oci-ta Task will clone a repo from the provided url and store it a ## Parameters |name|description|default value|required| |---|---|---|---| -|url|Repository URL to clone from.||true| -|revision|Revision to checkout. (branch, tag, sha, ref, etc...)|""|false| -|refspec|Refspec to fetch before checking out revision.|""|false| -|submodules|Initialize and fetch git submodules.|true|false| +|caTrustConfigMapKey|The name of the key in the ConfigMap that contains the CA bundle data.|ca-bundle.crt|false| +|caTrustConfigMapName|The name of the ConfigMap to read CA bundle data from.|trusted-ca|false| |depth|Perform a shallow clone, fetching only the most recent N commits.|1|false| -|sslVerify|Set the `http.sslVerify` global git config. Setting this to `false` is not advised unless you are sure that you trust your git remote.|true|false| -|sparseCheckoutDirectories|Define the directory patterns to match or exclude when performing a sparse checkout.|""|false| +|enableSymlinkCheck|Check symlinks in the repo. If they're pointing outside of the repo, the build will fail. |true|false| +|fetchTags|Fetch all tags for the repo.|false|false| |httpProxy|HTTP proxy server for non-SSL requests.|""|false| |httpsProxy|HTTPS proxy server for SSL requests.|""|false| |noProxy|Opt out of proxying HTTP/HTTPS requests.|""|false| -|verbose|Log the commands that are executed during `git-clone`'s operation.|false|false| +|ociArtifactExpiresAfter|Expiration date for the trusted artifacts created in the OCI repository. An empty string means the artifacts do not expire.|""|false| +|ociStorage|The OCI repository where the Trusted Artifacts are stored.||true| +|refspec|Refspec to fetch before checking out revision.|""|false| +|revision|Revision to checkout. (branch, tag, sha, ref, etc...)|""|false| +|sparseCheckoutDirectories|Define the directory patterns to match or exclude when performing a sparse checkout.|""|false| +|sslVerify|Set the `http.sslVerify` global git config. Setting this to `false` is not advised unless you are sure that you trust your git remote.|true|false| +|submodules|Initialize and fetch git submodules.|true|false| +|url|Repository URL to clone from.||true| |userHome|Absolute path to the user's home directory. Set this explicitly if you are running the image as a non-root user. |/tekton/home|false| -|enableSymlinkCheck|Check symlinks in the repo. If they're pointing outside of the repo, the build will fail. |true|false| -|fetchTags|Fetch all tags for the repo.|false|false| -|caTrustConfigMapName|The name of the ConfigMap to read CA bundle data from.|trusted-ca|false| -|caTrustConfigMapKey|The name of the key in the ConfigMap that contains the CA bundle data.|ca-bundle.crt|false| -|ociStorage|The OCI repository where the clone repository will be stored.||true| -|ociArtifactExpiresAfter|Expiration date for the artifacts created in the OCI repository.|""|false| +|verbose|Log the commands that are executed during `git-clone`'s operation.|false|false| ## Results |name|description| |---|---| +|SOURCE_ARTIFACT|The Trusted Artifact URI pointing to the artifact with the application source code.| |commit|The precise commit SHA that was fetched by this Task.| |url|The precise URL that was fetched by this Task.| -|sourceArtifact|The OCI reference to the trusted source artifact containing the cloned git repo.| ## Workspaces |name|description|optional| |---|---|---| -|ssh-directory|A .ssh directory with private key, known_hosts, config, etc. Copied to the user's home before git commands are executed. Used to authenticate with the git remote when performing the clone. Binding a Secret to this Workspace is strongly recommended over other volume types. |true| |basic-auth|A Workspace containing a .gitconfig and .git-credentials file or username and password. These will be copied to the user's home before any git commands are run. Any other files in this Workspace are ignored. It is strongly recommended to use ssh-directory over basic-auth whenever possible and to bind a Secret to this Workspace over other volume types. |true| +|ssh-directory|A .ssh directory with private key, known_hosts, config, etc. Copied to the user's home before git commands are executed. Used to authenticate with the git remote when performing the clone. Binding a Secret to this Workspace is strongly recommended over other volume types. |true| diff --git a/task/git-clone-oci-ta/0.1/git-clone-oci-ta.yaml b/task/git-clone-oci-ta/0.1/git-clone-oci-ta.yaml index 0161d2e49..b7c05abfd 100644 --- a/task/git-clone-oci-ta/0.1/git-clone-oci-ta.yaml +++ b/task/git-clone-oci-ta/0.1/git-clone-oci-ta.yaml @@ -2,291 +2,289 @@ apiVersion: tekton.dev/v1 kind: Task metadata: - labels: - app.kubernetes.io/version: "0.1" + name: git-clone-oci-ta annotations: tekton.dev/categories: Git tekton.dev/displayName: git clone oci trusted artifacts tekton.dev/pipelines.minVersion: 0.21.0 tekton.dev/platforms: linux/amd64,linux/s390x,linux/ppc64le,linux/arm64 tekton.dev/tags: git - name: git-clone-oci-ta + labels: + app.kubernetes.io/version: "0.1" spec: - description: >- - The git-clone-oci-ta Task will clone a repo from the provided url and store it as a trusted - artifact in the provided OCI repository. + description: The git-clone-oci-ta Task will clone a repo from the provided + url and store it as a trusted artifact in the provided OCI repository. params: - - description: Repository URL to clone from. - name: url - type: string - - default: "" - description: Revision to checkout. (branch, tag, sha, ref, etc...) - name: revision - type: string - - default: "" - description: Refspec to fetch before checking out revision. - name: refspec - type: string - - default: "true" - description: Initialize and fetch git submodules. - name: submodules - type: string - - default: "1" - description: Perform a shallow clone, fetching only the most recent N commits. - name: depth - type: string - - default: "true" - description: Set the `http.sslVerify` global git config. Setting this to `false` is not advised unless you are sure that you trust your git remote. - name: sslVerify - type: string - - default: "" - description: Define the directory patterns to match or exclude when performing a sparse checkout. - name: sparseCheckoutDirectories - type: string - - default: "" - description: HTTP proxy server for non-SSL requests. - name: httpProxy - type: string - - default: "" - description: HTTPS proxy server for SSL requests. - name: httpsProxy - type: string - - default: "" - description: Opt out of proxying HTTP/HTTPS requests. - name: noProxy - type: string - - default: "false" - description: Log the commands that are executed during `git-clone`'s operation. - name: verbose - type: string - - default: /tekton/home - description: | - Absolute path to the user's home directory. Set this explicitly if you are running the image as a non-root user. - name: userHome - type: string - - default: "true" - description: | - Check symlinks in the repo. If they're pointing outside of the repo, the build will fail. - name: enableSymlinkCheck - type: string - - default: "false" - description: Fetch all tags for the repo. - name: fetchTags - type: string - - name: caTrustConfigMapName - type: string - description: The name of the ConfigMap to read CA bundle data from. - default: trusted-ca - - name: caTrustConfigMapKey - type: string - description: The name of the key in the ConfigMap that contains the CA bundle data. - default: ca-bundle.crt - - name: ociStorage - type: string - description: The OCI repository where the Trusted Artifacts are stored. - - name: ociArtifactExpiresAfter - type: string - description: >- - Expiration date for the trusted artifacts created in the OCI repository. An empty string means - the artifacts do not expire. - default: "" - + - name: caTrustConfigMapKey + description: The name of the key in the ConfigMap that contains the + CA bundle data. + type: string + default: ca-bundle.crt + - name: caTrustConfigMapName + description: The name of the ConfigMap to read CA bundle data from. + type: string + default: trusted-ca + - name: depth + description: Perform a shallow clone, fetching only the most recent + N commits. + type: string + default: "1" + - name: enableSymlinkCheck + description: | + Check symlinks in the repo. If they're pointing outside of the repo, the build will fail. + type: string + default: "true" + - name: fetchTags + description: Fetch all tags for the repo. + type: string + default: "false" + - name: httpProxy + description: HTTP proxy server for non-SSL requests. + type: string + default: "" + - name: httpsProxy + description: HTTPS proxy server for SSL requests. + type: string + default: "" + - name: noProxy + description: Opt out of proxying HTTP/HTTPS requests. + type: string + default: "" + - name: ociArtifactExpiresAfter + description: Expiration date for the trusted artifacts created in the + OCI repository. An empty string means the artifacts do not expire. + type: string + default: "" + - name: ociStorage + description: The OCI repository where the Trusted Artifacts are stored. + type: string + - name: refspec + description: Refspec to fetch before checking out revision. + type: string + default: "" + - name: revision + description: Revision to checkout. (branch, tag, sha, ref, etc...) + type: string + default: "" + - name: sparseCheckoutDirectories + description: Define the directory patterns to match or exclude when + performing a sparse checkout. + type: string + default: "" + - name: sslVerify + description: Set the `http.sslVerify` global git config. Setting this + to `false` is not advised unless you are sure that you trust your + git remote. + type: string + default: "true" + - name: submodules + description: Initialize and fetch git submodules. + type: string + default: "true" + - name: url + description: Repository URL to clone from. + type: string + - name: userHome + description: | + Absolute path to the user's home directory. Set this explicitly if you are running the image as a non-root user. + type: string + default: /tekton/home + - name: verbose + description: Log the commands that are executed during `git-clone`'s + operation. + type: string + default: "false" results: - - description: The precise commit SHA that was fetched by this Task. - name: commit - - description: The precise URL that was fetched by this Task. - name: url - - description: The Trusted Artifact URI pointing to the artifact with the application source code. - name: SOURCE_ARTIFACT - type: string + - name: SOURCE_ARTIFACT + description: The Trusted Artifact URI pointing to the artifact with + the application source code. + type: string + - name: commit + description: The precise commit SHA that was fetched by this Task. + - name: url + description: The precise URL that was fetched by this Task. + volumes: + - name: trusted-ca + configMap: + items: + - key: $(params.caTrustConfigMapKey) + path: ca-bundle.crt + name: $(params.caTrustConfigMapName) + optional: true + - name: workdir + emptyDir: {} + workspaces: + - name: basic-auth + description: | + A Workspace containing a .gitconfig and .git-credentials file or username and password. + These will be copied to the user's home before any git commands are run. Any + other files in this Workspace are ignored. It is strongly recommended + to use ssh-directory over basic-auth whenever possible and to bind a + Secret to this Workspace over other volume types. + optional: true + - name: ssh-directory + description: | + A .ssh directory with private key, known_hosts, config, etc. Copied to + the user's home before git commands are executed. Used to authenticate + with the git remote when performing the clone. Binding a Secret to this + Workspace is strongly recommended over other volume types. + optional: true steps: - - name: clone - env: - - name: HOME - value: $(params.userHome) - - name: PARAM_URL - value: $(params.url) - - name: PARAM_REVISION - value: $(params.revision) - - name: PARAM_REFSPEC - value: $(params.refspec) - - name: PARAM_SUBMODULES - value: $(params.submodules) - - name: PARAM_DEPTH - value: $(params.depth) - - name: PARAM_SSL_VERIFY - value: $(params.sslVerify) - - name: PARAM_HTTP_PROXY - value: $(params.httpProxy) - - name: PARAM_HTTPS_PROXY - value: $(params.httpsProxy) - - name: PARAM_NO_PROXY - value: $(params.noProxy) - - name: PARAM_VERBOSE - value: $(params.verbose) - - name: PARAM_SPARSE_CHECKOUT_DIRECTORIES - value: $(params.sparseCheckoutDirectories) - - name: PARAM_USER_HOME - value: $(params.userHome) - - name: PARAM_FETCH_TAGS - value: $(params.fetchTags) - - name: WORKSPACE_SSH_DIRECTORY_BOUND - value: $(workspaces.ssh-directory.bound) - - name: WORKSPACE_SSH_DIRECTORY_PATH - value: $(workspaces.ssh-directory.path) - - name: WORKSPACE_BASIC_AUTH_DIRECTORY_BOUND - value: $(workspaces.basic-auth.bound) - - name: WORKSPACE_BASIC_AUTH_DIRECTORY_PATH - value: $(workspaces.basic-auth.path) - - name: CHECKOUT_DIR - value: /var/workdir/source - image: registry.redhat.io/openshift-pipelines/pipelines-git-init-rhel8:v1.8.2-8@sha256:a538c423e7a11aae6ae582a411fdb090936458075f99af4ce5add038bb6983e8 - computeResources: {} - securityContext: - runAsUser: 0 - volumeMounts: - - name: trusted-ca - mountPath: /mnt/trusted-ca - readOnly: true - - name: workdir - mountPath: /var/workdir - script: | - #!/usr/bin/env sh - set -eu + - name: clone + image: quay.io/konflux-ci/git-clone@sha256:005487d3967e7a90490f96b2ff3b0c6d0463b647d212cd809683b494e20146a8 + volumeMounts: + - mountPath: /mnt/trusted-ca + name: trusted-ca + readOnly: true + - mountPath: /var/workdir + name: workdir + env: + - name: HOME + value: $(params.userHome) + - name: PARAM_URL + value: $(params.url) + - name: PARAM_REVISION + value: $(params.revision) + - name: PARAM_REFSPEC + value: $(params.refspec) + - name: PARAM_SUBMODULES + value: $(params.submodules) + - name: PARAM_DEPTH + value: $(params.depth) + - name: PARAM_SSL_VERIFY + value: $(params.sslVerify) + - name: PARAM_HTTP_PROXY + value: $(params.httpProxy) + - name: PARAM_HTTPS_PROXY + value: $(params.httpsProxy) + - name: PARAM_NO_PROXY + value: $(params.noProxy) + - name: PARAM_VERBOSE + value: $(params.verbose) + - name: PARAM_SPARSE_CHECKOUT_DIRECTORIES + value: $(params.sparseCheckoutDirectories) + - name: PARAM_USER_HOME + value: $(params.userHome) + - name: PARAM_FETCH_TAGS + value: $(params.fetchTags) + - name: WORKSPACE_SSH_DIRECTORY_BOUND + value: $(workspaces.ssh-directory.bound) + - name: WORKSPACE_SSH_DIRECTORY_PATH + value: $(workspaces.ssh-directory.path) + - name: WORKSPACE_BASIC_AUTH_DIRECTORY_BOUND + value: $(workspaces.basic-auth.bound) + - name: WORKSPACE_BASIC_AUTH_DIRECTORY_PATH + value: $(workspaces.basic-auth.path) + - name: CHECKOUT_DIR + value: /var/workdir/source + script: | + #!/usr/bin/env sh + set -eu - if [ "${PARAM_VERBOSE}" = "true" ] ; then - set -x - fi - - if [ "${WORKSPACE_BASIC_AUTH_DIRECTORY_BOUND}" = "true" ] ; then - if [ -f "${WORKSPACE_BASIC_AUTH_DIRECTORY_PATH}/.git-credentials" ] && [ -f "${WORKSPACE_BASIC_AUTH_DIRECTORY_PATH}/.gitconfig" ]; then - cp "${WORKSPACE_BASIC_AUTH_DIRECTORY_PATH}/.git-credentials" "${PARAM_USER_HOME}/.git-credentials" - cp "${WORKSPACE_BASIC_AUTH_DIRECTORY_PATH}/.gitconfig" "${PARAM_USER_HOME}/.gitconfig" - # Compatibility with kubernetes.io/basic-auth secrets - elif [ -f "${WORKSPACE_BASIC_AUTH_DIRECTORY_PATH}/username" ] && [ -f "${WORKSPACE_BASIC_AUTH_DIRECTORY_PATH}/password" ]; then - HOSTNAME=$(echo $PARAM_URL | awk -F/ '{print $3}') - echo "https://$(cat ${WORKSPACE_BASIC_AUTH_DIRECTORY_PATH}/username):$(cat ${WORKSPACE_BASIC_AUTH_DIRECTORY_PATH}/password)@$HOSTNAME" > "${PARAM_USER_HOME}/.git-credentials" - echo -e "[credential \"https://$HOSTNAME\"]\n helper = store" > "${PARAM_USER_HOME}/.gitconfig" - else - echo "Unknown basic-auth workspace format" - exit 1 + if [ "${PARAM_VERBOSE}" = "true" ]; then + set -x fi - chmod 400 "${PARAM_USER_HOME}/.git-credentials" - chmod 400 "${PARAM_USER_HOME}/.gitconfig" - fi - - # Should be called after the gitconfig is copied from the repository secret - ca_bundle=/mnt/trusted-ca/ca-bundle.crt - if [ -f "$ca_bundle" ]; then - echo "INFO: Using mounted CA bundle: $ca_bundle" - git config --global http.sslCAInfo "$ca_bundle" - fi - if [ "${WORKSPACE_SSH_DIRECTORY_BOUND}" = "true" ] ; then - cp -R "${WORKSPACE_SSH_DIRECTORY_PATH}" "${PARAM_USER_HOME}"/.ssh - chmod 700 "${PARAM_USER_HOME}"/.ssh - chmod -R 400 "${PARAM_USER_HOME}"/.ssh/* - fi - - test -z "${PARAM_HTTP_PROXY}" || export HTTP_PROXY="${PARAM_HTTP_PROXY}" - test -z "${PARAM_HTTPS_PROXY}" || export HTTPS_PROXY="${PARAM_HTTPS_PROXY}" - test -z "${PARAM_NO_PROXY}" || export NO_PROXY="${PARAM_NO_PROXY}" + if [ "${WORKSPACE_BASIC_AUTH_DIRECTORY_BOUND}" = "true" ]; then + if [ -f "${WORKSPACE_BASIC_AUTH_DIRECTORY_PATH}/.git-credentials" ] && [ -f "${WORKSPACE_BASIC_AUTH_DIRECTORY_PATH}/.gitconfig" ]; then + cp "${WORKSPACE_BASIC_AUTH_DIRECTORY_PATH}/.git-credentials" "${PARAM_USER_HOME}/.git-credentials" + cp "${WORKSPACE_BASIC_AUTH_DIRECTORY_PATH}/.gitconfig" "${PARAM_USER_HOME}/.gitconfig" + # Compatibility with kubernetes.io/basic-auth secrets + elif [ -f "${WORKSPACE_BASIC_AUTH_DIRECTORY_PATH}/username" ] && [ -f "${WORKSPACE_BASIC_AUTH_DIRECTORY_PATH}/password" ]; then + HOSTNAME=$(echo $PARAM_URL | awk -F/ '{print $3}') + echo "https://$(cat ${WORKSPACE_BASIC_AUTH_DIRECTORY_PATH}/username):$(cat ${WORKSPACE_BASIC_AUTH_DIRECTORY_PATH}/password)@$HOSTNAME" >"${PARAM_USER_HOME}/.git-credentials" + echo -e "[credential \"https://$HOSTNAME\"]\n helper = store" >"${PARAM_USER_HOME}/.gitconfig" + else + echo "Unknown basic-auth workspace format" + exit 1 + fi + chmod 400 "${PARAM_USER_HOME}/.git-credentials" + chmod 400 "${PARAM_USER_HOME}/.gitconfig" + fi - /ko-app/git-init \ - -url="${PARAM_URL}" \ - -revision="${PARAM_REVISION}" \ - -refspec="${PARAM_REFSPEC}" \ - -path="${CHECKOUT_DIR}" \ - -sslVerify="${PARAM_SSL_VERIFY}" \ - -submodules="${PARAM_SUBMODULES}" \ - -depth="${PARAM_DEPTH}" \ - -sparseCheckoutDirectories="${PARAM_SPARSE_CHECKOUT_DIRECTORIES}" - cd "${CHECKOUT_DIR}" - RESULT_SHA="$(git rev-parse HEAD)" - EXIT_CODE="$?" - if [ "${EXIT_CODE}" != 0 ] ; then - exit "${EXIT_CODE}" - fi - printf "%s" "${RESULT_SHA}" > "$(results.commit.path)" - printf "%s" "${PARAM_URL}" > "$(results.url.path)" + # Should be called after the gitconfig is copied from the repository secret + ca_bundle=/mnt/trusted-ca/ca-bundle.crt + if [ -f "$ca_bundle" ]; then + echo "INFO: Using mounted CA bundle: $ca_bundle" + git config --global http.sslCAInfo "$ca_bundle" + fi - if [ "${PARAM_FETCH_TAGS}" = "true" ] ; then - echo "Fetching tags" - git fetch --tags - fi + if [ "${WORKSPACE_SSH_DIRECTORY_BOUND}" = "true" ]; then + cp -R "${WORKSPACE_SSH_DIRECTORY_PATH}" "${PARAM_USER_HOME}"/.ssh + chmod 700 "${PARAM_USER_HOME}"/.ssh + chmod -R 400 "${PARAM_USER_HOME}"/.ssh/* + fi - - name: symlink-check - image: registry.redhat.io/ubi9:9.2-696@sha256:089bd3b82a78ac45c0eed231bb58bfb43bfcd0560d9bba240fc6355502c92976 - env: - - name: PARAM_ENABLE_SYMLINK_CHECK - value: $(params.enableSymlinkCheck) - - name: CHECKOUT_DIR - value: /var/workdir/source - volumeMounts: - - name: workdir - mountPath: /var/workdir - computeResources: {} - script: | - #!/usr/bin/env bash - set -euo pipefail + test -z "${PARAM_HTTP_PROXY}" || export HTTP_PROXY="${PARAM_HTTP_PROXY}" + test -z "${PARAM_HTTPS_PROXY}" || export HTTPS_PROXY="${PARAM_HTTPS_PROXY}" + test -z "${PARAM_NO_PROXY}" || export NO_PROXY="${PARAM_NO_PROXY}" - check_symlinks() { - FOUND_SYMLINK_POINTING_OUTSIDE_OF_REPO=false - while read symlink - do - target=$(readlink -f "$symlink") - if ! [[ "$target" =~ ^$CHECKOUT_DIR ]]; then - echo "The cloned repository contains symlink pointing outside of the cloned repository: $symlink" - FOUND_SYMLINK_POINTING_OUTSIDE_OF_REPO=true - fi - done < <(find $CHECKOUT_DIR -type l -print) - if [ "$FOUND_SYMLINK_POINTING_OUTSIDE_OF_REPO" = true ] ; then - return 1 + /ko-app/git-init \ + -url="${PARAM_URL}" \ + -revision="${PARAM_REVISION}" \ + -refspec="${PARAM_REFSPEC}" \ + -path="${CHECKOUT_DIR}" \ + -sslVerify="${PARAM_SSL_VERIFY}" \ + -submodules="${PARAM_SUBMODULES}" \ + -depth="${PARAM_DEPTH}" \ + -sparseCheckoutDirectories="${PARAM_SPARSE_CHECKOUT_DIRECTORIES}" + cd "${CHECKOUT_DIR}" + RESULT_SHA="$(git rev-parse HEAD)" + EXIT_CODE="$?" + if [ "${EXIT_CODE}" != 0 ]; then + exit "${EXIT_CODE}" fi - } + printf "%s" "${RESULT_SHA}" >"$( results.commit.path)" + printf "%s" "${PARAM_URL}" >"$( results.url.path)" - if [ "${PARAM_ENABLE_SYMLINK_CHECK}" = "true" ] ; then - echo "Running symlink check" - check_symlinks - fi + if [ "${PARAM_FETCH_TAGS}" = "true" ]; then + echo "Fetching tags" + git fetch --tags + fi + securityContext: + runAsUser: 0 + - name: symlink-check + image: quay.io/konflux-ci/git-clone@sha256:005487d3967e7a90490f96b2ff3b0c6d0463b647d212cd809683b494e20146a8 + volumeMounts: + - mountPath: /var/workdir + name: workdir + env: + - name: PARAM_ENABLE_SYMLINK_CHECK + value: $(params.enableSymlinkCheck) + - name: CHECKOUT_DIR + value: /var/workdir/source + script: | + #!/usr/bin/env bash + set -euo pipefail - - name: create-trusted-artifact - image: quay.io/redhat-appstudio/build-trusted-artifacts:latest@sha256:4e39fb97f4444c2946944482df47b39c5bbc195c54c6560b0647635f553ab23d - env: - - name: IMAGE_EXPIRES_AFTER - value: $(params.ociArtifactExpiresAfter) - volumeMounts: - - name: workdir - mountPath: /var/workdir - args: - - create - - --store - - $(params.ociStorage) - - $(results.SOURCE_ARTIFACT.path)=/var/workdir/source + check_symlinks() { + FOUND_SYMLINK_POINTING_OUTSIDE_OF_REPO=false + while read symlink; do + target=$(readlink -f "$symlink") + if ! [[ "$target" =~ ^$CHECKOUT_DIR ]]; then + echo "The cloned repository contains symlink pointing outside of the cloned repository: $symlink" + FOUND_SYMLINK_POINTING_OUTSIDE_OF_REPO=true + fi + done < <(find $CHECKOUT_DIR -type l -print) + if [ "$FOUND_SYMLINK_POINTING_OUTSIDE_OF_REPO" = true ]; then + return 1 + fi + } - workspaces: - - description: | - A .ssh directory with private key, known_hosts, config, etc. Copied to - the user's home before git commands are executed. Used to authenticate - with the git remote when performing the clone. Binding a Secret to this - Workspace is strongly recommended over other volume types. - name: ssh-directory - optional: true - - description: | - A Workspace containing a .gitconfig and .git-credentials file or username and password. - These will be copied to the user's home before any git commands are run. Any - other files in this Workspace are ignored. It is strongly recommended - to use ssh-directory over basic-auth whenever possible and to bind a - Secret to this Workspace over other volume types. - name: basic-auth - optional: true - volumes: - - name: workdir - emptyDir: {} - - name: trusted-ca - configMap: - name: $(params.caTrustConfigMapName) - items: - - key: $(params.caTrustConfigMapKey) - path: ca-bundle.crt - optional: true + if [ "${PARAM_ENABLE_SYMLINK_CHECK}" = "true" ]; then + echo "Running symlink check" + check_symlinks + fi + - name: create-trusted-artifact + image: quay.io/redhat-appstudio/build-trusted-artifacts:latest@sha256:4e39fb97f4444c2946944482df47b39c5bbc195c54c6560b0647635f553ab23d + args: + - create + - --store + - $(params.ociStorage) + - $(results.SOURCE_ARTIFACT.path)=/var/workdir/source + volumeMounts: + - mountPath: /var/workdir + name: workdir + env: + - name: IMAGE_EXPIRES_AFTER + value: $(params.ociArtifactExpiresAfter) diff --git a/task/git-clone-oci-ta/0.1/recipe.yaml b/task/git-clone-oci-ta/0.1/recipe.yaml new file mode 100644 index 000000000..4b35d6970 --- /dev/null +++ b/task/git-clone-oci-ta/0.1/recipe.yaml @@ -0,0 +1,15 @@ +--- +base: ../../git-clone/0.1/git-clone.yaml +removeParams: + - gitInitImage + - deleteExisting + - subdirectory +addEnvironment: + - name: CHECKOUT_DIR + value: /var/workdir/source +add: + - create-source +removeWorkspaces: + - output +description: The git-clone-oci-ta Task will clone a repo from the provided url and store it as a trusted + artifact in the provided OCI repository. diff --git a/task/prefetch-dependencies-oci-ta/0.1/README.md b/task/prefetch-dependencies-oci-ta/0.1/README.md index d98fd692e..7bc339170 100644 --- a/task/prefetch-dependencies-oci-ta/0.1/README.md +++ b/task/prefetch-dependencies-oci-ta/0.1/README.md @@ -8,20 +8,20 @@ https://github.com/containerbuildsystem/cachi2#basic-usage. ## Parameters |name|description|default value|required| |---|---|---|---| -|input|Configures project packages that will have their dependencies prefetched.||true| -|source-artifact|The trusted artifact URI containing the application source code.||true| -|oci-storage|The OCI repository where the trusted artifacts with the modified cloned repository and the prefetched depedencies will be stored.||true| -|oci-artifact-expires-after|Expiration date for the trusted artifacts created in the OCI repository. An empty string means the artifacts do not expire.|""|false| +|SOURCE_ARTIFACT|The Trusted Artifact URI pointing to the artifact with the application source code.||true| +|caTrustConfigMapKey|The name of the key in the ConfigMap that contains the CA bundle data.|ca-bundle.crt|false| +|caTrustConfigMapName|The name of the ConfigMap to read CA bundle data from.|trusted-ca|false| |dev-package-managers|Enable in-development package managers. WARNING: the behavior may change at any time without notice. Use at your own risk. |false|false| +|input|Configures project packages that will have their dependencies prefetched.||true| |log-level|Set cachi2 log level (debug, info, warning, error)|info|false| -|caTrustConfigMapName|The name of the ConfigMap to read CA bundle data from.|trusted-ca|false| -|caTrustConfigMapKey|The name of the key in the ConfigMap that contains the CA bundle data.|ca-bundle.crt|false| +|ociArtifactExpiresAfter|Expiration date for the trusted artifacts created in the OCI repository. An empty string means the artifacts do not expire.|""|false| +|ociStorage|The OCI repository where the Trusted Artifacts are stored.||true| ## Results |name|description| |---|---| -|source-artifact|The trusted artifact URI containing the modified application source.| -|cachi2-artifact|The trusted artifact URI containing the fetched dependencies.| +|CACHI2_ARTIFACT|The Trusted Artifact URI pointing to the artifact with the prefetched dependencies.| +|SOURCE_ARTIFACT|The Trusted Artifact URI pointing to the artifact with the application source code.| ## Workspaces |name|description|optional| diff --git a/task/prefetch-dependencies-oci-ta/0.1/prefetch-dependencies-oci-ta.yaml b/task/prefetch-dependencies-oci-ta/0.1/prefetch-dependencies-oci-ta.yaml index 69eed7fdb..2bb99bca2 100644 --- a/task/prefetch-dependencies-oci-ta/0.1/prefetch-dependencies-oci-ta.yaml +++ b/task/prefetch-dependencies-oci-ta/0.1/prefetch-dependencies-oci-ta.yaml @@ -2,12 +2,12 @@ apiVersion: tekton.dev/v1 kind: Task metadata: + name: prefetch-dependencies-oci-ta + annotations: + tekton.dev/pipelines.minVersion: 0.12.1 + tekton.dev/tags: image-build, hacbs labels: app.kubernetes.io/version: "0.1" - annotations: - tekton.dev/pipelines.minVersion: "0.12.1" - tekton.dev/tags: "image-build, hacbs" - name: prefetch-dependencies-oci-ta spec: description: |- Task that uses Cachi2 to prefetch build dependencies. The fetched dependencies and the @@ -15,148 +15,150 @@ spec: For additional info on Cachi2, see docs at https://github.com/containerbuildsystem/cachi2#basic-usage. params: - - description: Configures project packages that will have their dependencies prefetched. - name: input - - description: The Trusted Artifact URI pointing to the artifact with the application source code. - name: SOURCE_ARTIFACT - type: string - - description: The OCI repository where the Trusted Artifacts are stored. - name: ociStorage - type: string - - description: >- - Expiration date for the trusted artifacts created in the OCI repository. An empty string means - the artifacts do not expire. - name: ociArtifactExpiresAfter - type: string - default: "" - - description: > - Enable in-development package managers. WARNING: the behavior may change at any time without - notice. Use at your own risk. - name: dev-package-managers - default: "false" - - description: Set cachi2 log level (debug, info, warning, error) - name: log-level - default: "info" - - name: caTrustConfigMapName - type: string - description: The name of the ConfigMap to read CA bundle data from. - default: trusted-ca - - name: caTrustConfigMapKey - type: string - description: The name of the key in the ConfigMap that contains the CA bundle data. - default: ca-bundle.crt + - name: SOURCE_ARTIFACT + description: The Trusted Artifact URI pointing to the artifact with + the application source code. + type: string + - name: caTrustConfigMapKey + description: The name of the key in the ConfigMap that contains the + CA bundle data. + type: string + default: ca-bundle.crt + - name: caTrustConfigMapName + description: The name of the ConfigMap to read CA bundle data from. + type: string + default: trusted-ca + - name: dev-package-managers + description: | + Enable in-development package managers. WARNING: the behavior may change at any time without notice. Use at your own risk. + default: "false" + - name: input + description: Configures project packages that will have their dependencies + prefetched. + - name: log-level + description: Set cachi2 log level (debug, info, warning, error) + default: info + - name: ociArtifactExpiresAfter + description: Expiration date for the trusted artifacts created in the + OCI repository. An empty string means the artifacts do not expire. + type: string + default: "" + - name: ociStorage + description: The OCI repository where the Trusted Artifacts are stored. + type: string results: - - description: The Trusted Artifact URI pointing to the artifact with the application source code. - name: SOURCE_ARTIFACT + - name: CACHI2_ARTIFACT + description: The Trusted Artifact URI pointing to the artifact with + the prefetched dependencies. type: string - - description: The Trusted Artifact URI pointing to the artifact with the prefetched dependencies. - name: CACHI2_ARTIFACT + - name: SOURCE_ARTIFACT + description: The Trusted Artifact URI pointing to the artifact with + the application source code. type: string + volumes: + - name: trusted-ca + configMap: + items: + - key: $(params.caTrustConfigMapKey) + path: ca-bundle.crt + name: $(params.caTrustConfigMapName) + optional: true + - name: workdir + emptyDir: {} + workspaces: + - name: git-basic-auth + description: | + A Workspace containing a .gitconfig and .git-credentials file or username and password. + These will be copied to the user's home before any cachi2 commands are run. Any + other files in this Workspace are ignored. It is strongly recommended + to bind a Secret to this Workspace over other volume types. + optional: true stepTemplate: volumeMounts: - mountPath: /var/workdir name: workdir steps: - - image: quay.io/redhat-appstudio/build-trusted-artifacts:latest@sha256:4e39fb97f4444c2946944482df47b39c5bbc195c54c6560b0647635f553ab23d - name: use-trusted-artifact - args: - - use - - $(params.SOURCE_ARTIFACT)=/var/workdir/source - - image: quay.io/redhat-appstudio/cachi2:0.7.0@sha256:1fc772aa3636fd0b43d62120d832e5913843e028e8cac42814b487c3a0a32bd8 - name: prefetch-dependencies - env: - - name: INPUT - value: $(params.input) - - name: DEV_PACKAGE_MANAGERS - value: $(params.dev-package-managers) - - name: LOG_LEVEL - value: $(params.log-level) - - name: WORKSPACE_GIT_AUTH_BOUND - value: $(workspaces.git-basic-auth.bound) - - name: WORKSPACE_GIT_AUTH_PATH - value: $(workspaces.git-basic-auth.path) - volumeMounts: - - name: trusted-ca - mountPath: /mnt/trusted-ca - readOnly: true - script: | - if [ -z "${INPUT}" ] - then - # Confirm input was provided though it's likely the whole task would be skipped if it wasn't - echo "No prefetch will be performed because no input was provided for cachi2 fetch-deps" - exit 0 - fi - - if [ "$DEV_PACKAGE_MANAGERS" = "true" ]; then - dev_pacman_flag=--dev-package-managers - else - dev_pacman_flag="" - fi + - name: use-trusted-artifact + image: quay.io/redhat-appstudio/build-trusted-artifacts:latest@sha256:4e39fb97f4444c2946944482df47b39c5bbc195c54c6560b0647635f553ab23d + args: + - use + - $(params.SOURCE_ARTIFACT)=/var/workdir/source + - name: prefetch-dependencies + image: quay.io/redhat-appstudio/cachi2:0.7.0@sha256:1fc772aa3636fd0b43d62120d832e5913843e028e8cac42814b487c3a0a32bd8 + volumeMounts: + - mountPath: /mnt/trusted-ca + name: trusted-ca + readOnly: true + env: + - name: INPUT + value: $(params.input) + - name: DEV_PACKAGE_MANAGERS + value: $(params.dev-package-managers) + - name: LOG_LEVEL + value: $(params.log-level) + - name: WORKSPACE_GIT_AUTH_BOUND + value: $(workspaces.git-basic-auth.bound) + - name: WORKSPACE_GIT_AUTH_PATH + value: $(workspaces.git-basic-auth.path) + script: | + if [ -z "${INPUT}" ]; then + # Confirm input was provided though it's likely the whole task would be skipped if it wasn't + echo "No prefetch will be performed because no input was provided for cachi2 fetch-deps" + exit 0 + fi - # Copied from https://github.com/konflux-ci/build-definitions/blob/main/task/git-clone/0.1/git-clone.yaml - if [ "${WORKSPACE_GIT_AUTH_BOUND}" = "true" ] ; then - if [ -f "${WORKSPACE_GIT_AUTH_PATH}/.git-credentials" ] && [ -f "${WORKSPACE_GIT_AUTH_PATH}/.gitconfig" ]; then - cp "${WORKSPACE_GIT_AUTH_PATH}/.git-credentials" "${HOME}/.git-credentials" - cp "${WORKSPACE_GIT_AUTH_PATH}/.gitconfig" "${HOME}/.gitconfig" - # Compatibility with kubernetes.io/basic-auth secrets - elif [ -f "${WORKSPACE_GIT_AUTH_PATH}/username" ] && [ -f "${WORKSPACE_GIT_AUTH_PATH}/password" ]; then - HOSTNAME=$(cd "/var/workdir/source" && git remote get-url origin | awk -F/ '{print $3}') - echo "https://$(cat ${WORKSPACE_GIT_AUTH_PATH}/username):$(cat ${WORKSPACE_GIT_AUTH_PATH}/password)@$HOSTNAME" > "${HOME}/.git-credentials" - echo -e "[credential \"https://$HOSTNAME\"]\n helper = store" > "${HOME}/.gitconfig" + if [ "$DEV_PACKAGE_MANAGERS" = "true" ]; then + dev_pacman_flag=--dev-package-managers else - echo "Unknown git-basic-auth workspace format" - exit 1 + dev_pacman_flag="" fi - chmod 400 "${HOME}/.git-credentials" - chmod 400 "${HOME}/.gitconfig" - fi - ca_bundle=/mnt/trusted-ca/ca-bundle.crt - if [ -f "$ca_bundle" ]; then - echo "INFO: Using mounted CA bundle: $ca_bundle" - cp -vf $ca_bundle /etc/pki/ca-trust/source/anchors - update-ca-trust - fi + # Copied from https://github.com/konflux-ci/build-definitions/blob/main/task/git-clone/0.1/git-clone.yaml + if [ "${WORKSPACE_GIT_AUTH_BOUND}" = "true" ]; then + if [ -f "${WORKSPACE_GIT_AUTH_PATH}/.git-credentials" ] && [ -f "${WORKSPACE_GIT_AUTH_PATH}/.gitconfig" ]; then + cp "${WORKSPACE_GIT_AUTH_PATH}/.git-credentials" "${HOME}/.git-credentials" + cp "${WORKSPACE_GIT_AUTH_PATH}/.gitconfig" "${HOME}/.gitconfig" + # Compatibility with kubernetes.io/basic-auth secrets + elif [ -f "${WORKSPACE_GIT_AUTH_PATH}/username" ] && [ -f "${WORKSPACE_GIT_AUTH_PATH}/password" ]; then + HOSTNAME=$(cd "/var/workdir/source" && git remote get-url origin | awk -F/ '{print $3}') + echo "https://$(cat ${WORKSPACE_GIT_AUTH_PATH}/username):$(cat ${WORKSPACE_GIT_AUTH_PATH}/password)@$HOSTNAME" >"${HOME}/.git-credentials" + echo -e "[credential \"https://$HOSTNAME\"]\n helper = store" >"${HOME}/.gitconfig" + else + echo "Unknown git-basic-auth workspace format" + exit 1 + fi + chmod 400 "${HOME}/.git-credentials" + chmod 400 "${HOME}/.gitconfig" + fi - cachi2 --log-level="$LOG_LEVEL" fetch-deps \ - $dev_pacman_flag \ - --source=/var/workdir/source \ - --output=/var/workdir/cachi2/output \ - "${INPUT}" + ca_bundle=/mnt/trusted-ca/ca-bundle.crt + if [ -f "$ca_bundle" ]; then + echo "INFO: Using mounted CA bundle: $ca_bundle" + cp -vf $ca_bundle /etc/pki/ca-trust/source/anchors + update-ca-trust + fi - cachi2 --log-level="$LOG_LEVEL" generate-env /var/workdir/cachi2/output \ - --format env \ - --for-output-dir=/cachi2/output \ - --output /var/workdir/cachi2/cachi2.env + cachi2 --log-level="$LOG_LEVEL" fetch-deps \ + $dev_pacman_flag \ + --source=/var/workdir/source \ + --output=/var/workdir/cachi2/output \ + "${INPUT}" - cachi2 --log-level="$LOG_LEVEL" inject-files /var/workdir/cachi2/output \ - --for-output-dir=/cachi2/output - - image: quay.io/redhat-appstudio/build-trusted-artifacts:latest@sha256:4e39fb97f4444c2946944482df47b39c5bbc195c54c6560b0647635f553ab23d - name: create-trusted-artifact - env: - - name: IMAGE_EXPIRES_AFTER - value: $(params.ociArtifactExpiresAfter) - args: - - create - - --store - - $(params.ociStorage) - - $(results.SOURCE_ARTIFACT.path)=/var/workdir/source - - $(results.CACHI2_ARTIFACT.path)=/var/workdir/cachi2 - workspaces: - - name: git-basic-auth - description: | - A Workspace containing a .gitconfig and .git-credentials file or username and password. - These will be copied to the user's home before any cachi2 commands are run. Any - other files in this Workspace are ignored. It is strongly recommended - to bind a Secret to this Workspace over other volume types. - optional: true - volumes: - - name: workdir - emptyDir: {} - - name: trusted-ca - configMap: - name: $(params.caTrustConfigMapName) - items: - - key: $(params.caTrustConfigMapKey) - path: ca-bundle.crt - optional: true + cachi2 --log-level="$LOG_LEVEL" generate-env /var/workdir/cachi2/output \ + --format env \ + --for-output-dir=/cachi2/output \ + --output /var/workdir/cachi2/cachi2.env + + cachi2 --log-level="$LOG_LEVEL" inject-files /var/workdir/cachi2/output \ + --for-output-dir=/cachi2/output + - name: create-trusted-artifact + image: quay.io/redhat-appstudio/build-trusted-artifacts:latest@sha256:4e39fb97f4444c2946944482df47b39c5bbc195c54c6560b0647635f553ab23d + args: + - create + - --store + - $(params.ociStorage) + - $(results.SOURCE_ARTIFACT.path)=/var/workdir/source + - $(results.CACHI2_ARTIFACT.path)=/var/workdir/cachi2 + env: + - name: IMAGE_EXPIRES_AFTER + value: $(params.ociArtifactExpiresAfter) diff --git a/task/prefetch-dependencies-oci-ta/0.1/recipe.yaml b/task/prefetch-dependencies-oci-ta/0.1/recipe.yaml new file mode 100644 index 000000000..dbed9f6e6 --- /dev/null +++ b/task/prefetch-dependencies-oci-ta/0.1/recipe.yaml @@ -0,0 +1,16 @@ +--- +base: ../../prefetch-dependencies/0.1/prefetch-dependencies.yaml +add: + - use-source + - create-source + - create-cachi2 +description: |- + Task that uses Cachi2 to prefetch build dependencies. The fetched dependencies and the + application source code are stored as a trusted artifact in the provided OCI repository. + For additional info on Cachi2, see docs at + https://github.com/containerbuildsystem/cachi2#basic-usage. +preferStepTemplate: true +removeWorkspaces: + - source +replacements: + workspaces.source.path: /var/workdir diff --git a/task/sast-snyk-check-oci-ta/0.1/README.md b/task/sast-snyk-check-oci-ta/0.1/README.md index 227286f85..77cdd4e86 100644 --- a/task/sast-snyk-check-oci-ta/0.1/README.md +++ b/task/sast-snyk-check-oci-ta/0.1/README.md @@ -11,9 +11,9 @@ See https://snyk.io/product/snyk-code/ and https://snyk.io/ for more information ## Parameters |name|description|default value|required| |---|---|---|---| -|SOURCE_ARTIFACT|The trusted artifact URI containing the application source code.||true| -|SNYK_SECRET|Name of secret which contains Snyk token.|snyk-secret|false| |ARGS|Append arguments.|--all-projects --exclude=test*,vendor,deps|false| +|SNYK_SECRET|Name of secret which contains Snyk token.|snyk-secret|false| +|SOURCE_ARTIFACT|The Trusted Artifact URI pointing to the artifact with the application source code.||true| ## Results |name|description| diff --git a/task/sast-snyk-check-oci-ta/0.1/recipe.yaml b/task/sast-snyk-check-oci-ta/0.1/recipe.yaml new file mode 100644 index 000000000..9ab563724 --- /dev/null +++ b/task/sast-snyk-check-oci-ta/0.1/recipe.yaml @@ -0,0 +1,28 @@ +--- +base: ../../sast-snyk-check/0.1/sast-snyk-check.yaml +add: + - use-source +description: >- + Scans source code for security vulnerabilities, including common issues such as SQL injection, + cross-site scripting (XSS), and code injection attacks using Snyk Code, a Static Application + Security Testing (SAST) tool. + + + Follow the steps given + [here](https://redhat-appstudio.github.io/docs.appstudio.io/Documentation/main/how-to-guides/testing_applications/enable_snyk_check_for_a_product/) + to obtain a snyk-token and to enable the snyk task in a Pipeline. + + + The snyk binary used in this Task comes from a container image defined in + https://github.com/konflux-ci/konflux-test + + + See https://snyk.io/product/snyk-code/ and https://snyk.io/ for more information about the snyk + tool. +preferStepTemplate: true +removeWorkspaces: + - workspace +replacements: + workspaces.workspace.path: /var/workdir +regexReplacements: + hacbs/\$\(context.task.name\): source diff --git a/task/sast-snyk-check-oci-ta/0.1/sast-snyk-check-oci-ta.yaml b/task/sast-snyk-check-oci-ta/0.1/sast-snyk-check-oci-ta.yaml index 7bd2be640..a35c8abf0 100644 --- a/task/sast-snyk-check-oci-ta/0.1/sast-snyk-check-oci-ta.yaml +++ b/task/sast-snyk-check-oci-ta/0.1/sast-snyk-check-oci-ta.yaml @@ -2,49 +2,41 @@ apiVersion: tekton.dev/v1 kind: Task metadata: + name: sast-snyk-check-oci-ta + annotations: + tekton.dev/pipelines.minVersion: 0.12.1 + tekton.dev/tags: appstudio, hacbs labels: app.kubernetes.io/version: "0.1" - annotations: - tekton.dev/pipelines.minVersion: "0.12.1" - tekton.dev/tags: "appstudio, hacbs" - name: sast-snyk-check-oci-ta spec: - description: >- - Scans source code for security vulnerabilities, including common issues such as SQL injection, - cross-site scripting (XSS), and code injection attacks using Snyk Code, a Static Application - Security Testing (SAST) tool. - + description: |- + Scans source code for security vulnerabilities, including common issues such as SQL injection, cross-site scripting (XSS), and code injection attacks using Snyk Code, a Static Application Security Testing (SAST) tool. - Follow the steps given - [here](https://redhat-appstudio.github.io/docs.appstudio.io/Documentation/main/how-to-guides/testing_applications/enable_snyk_check_for_a_product/) - to obtain a snyk-token and to enable the snyk task in a Pipeline. + Follow the steps given [here](https://redhat-appstudio.github.io/docs.appstudio.io/Documentation/main/how-to-guides/testing_applications/enable_snyk_check_for_a_product/) to obtain a snyk-token and to enable the snyk task in a Pipeline. + The snyk binary used in this Task comes from a container image defined in https://github.com/konflux-ci/konflux-test - The snyk binary used in this Task comes from a container image defined in - https://github.com/konflux-ci/konflux-test - - - See https://snyk.io/product/snyk-code/ and https://snyk.io/ for more information about the snyk - tool. - results: - - description: Tekton task test output. - name: TEST_OUTPUT + See https://snyk.io/product/snyk-code/ and https://snyk.io/ for more information about the snyk tool. params: - - name: SOURCE_ARTIFACT + - name: ARGS + description: Append arguments. type: string - description: The Trusted Artifact URI pointing to the artifact with the application source code. + default: --all-projects --exclude=test*,vendor,deps - name: SNYK_SECRET description: Name of secret which contains Snyk token. default: snyk-secret - - name: ARGS + - name: SOURCE_ARTIFACT + description: The Trusted Artifact URI pointing to the artifact with + the application source code. type: string - description: Append arguments. - default: "--all-projects --exclude=test*,vendor,deps" + results: + - name: TEST_OUTPUT + description: Tekton task test output. volumes: - name: snyk-secret secret: - secretName: $(params.SNYK_SECRET) optional: true + secretName: $(params.SNYK_SECRET) - name: workdir emptyDir: {} stepTemplate: @@ -61,8 +53,8 @@ spec: image: quay.io/redhat-appstudio/konflux-test:v1.4.0@sha256:54d49b37c9a2e280d42961a57e4f7a16c171d6b065559f1329b548db85300bea workingDir: /var/workdir/source volumeMounts: - - name: snyk-secret - mountPath: "/etc/secrets" + - mountPath: /etc/secrets + name: snyk-secret readOnly: true env: - name: SNYK_SECRET @@ -91,7 +83,7 @@ spec: SNYK_EXIT_CODE=0 SOURCE_CODE_DIR=/var/workdir/source - snyk code test $ARGS $SOURCE_CODE_DIR --sarif-file-output=sast_snyk_check_out.json 1>&2>> stdout.txt || SNYK_EXIT_CODE=$? + snyk code test $ARGS $SOURCE_CODE_DIR --sarif-file-output=sast_snyk_check_out.json 1>&2 >>stdout.txt || SNYK_EXIT_CODE=$? test_not_skipped=0 SKIP_MSG="We found 0 supported files" grep -q "$SKIP_MSG" stdout.txt || test_not_skipped=$? diff --git a/task/source-build-oci-ta/0.1/README.md b/task/source-build-oci-ta/0.1/README.md index 6f7b3ee2c..43bf1b2d4 100644 --- a/task/source-build-oci-ta/0.1/README.md +++ b/task/source-build-oci-ta/0.1/README.md @@ -5,15 +5,15 @@ Source image build. ## Parameters |name|description|default value|required| |---|---|---|---| -|BINARY_IMAGE|Binary image name from which to generate the source image name.||true| |BASE_IMAGES|Base images used to build the binary image. Each image per line in the same order of FROM instructions specified in a multistage Dockerfile. Default to an empty string, which means to skip handling a base image.|""|false| -|SOURCE_ARTIFACT|The trusted artifact URI containing the application source code.||true| -|CACHI2_ARTIFACT|The trusted artifact URI containing the prefetched dependencies.|""|false| +|BINARY_IMAGE|Binary image name from which to generate the source image name.||true| +|CACHI2_ARTIFACT|The Trusted Artifact URI pointing to the artifact with the prefetched dependencies.|""|false| +|SOURCE_ARTIFACT|The Trusted Artifact URI pointing to the artifact with the application source code.||true| ## Results |name|description| |---|---| |BUILD_RESULT|Build result.| -|SOURCE_IMAGE_URL|The source image url.| |SOURCE_IMAGE_DIGEST|The source image digest.| +|SOURCE_IMAGE_URL|The source image url.| diff --git a/task/source-build-oci-ta/0.1/recipe.yaml b/task/source-build-oci-ta/0.1/recipe.yaml new file mode 100644 index 000000000..1211dc3ee --- /dev/null +++ b/task/source-build-oci-ta/0.1/recipe.yaml @@ -0,0 +1,15 @@ +--- +base: ../../source-build/0.1/source-build.yaml +add: + - use-source + - use-cachi2 +removeWorkspaces: + - workspace +removeVolumes: + - source-build-work-place +regexReplacements: + \/var\/source-build: /var/workdir + \/workspace\/workspace: /var/workdir +preferStepTemplate: true +replacements: + workspaces.workspace.path: /var/workdir diff --git a/task/source-build-oci-ta/0.1/source-build-oci-ta.yaml b/task/source-build-oci-ta/0.1/source-build-oci-ta.yaml index de09be39c..44c9d6455 100644 --- a/task/source-build-oci-ta/0.1/source-build-oci-ta.yaml +++ b/task/source-build-oci-ta/0.1/source-build-oci-ta.yaml @@ -3,46 +3,48 @@ apiVersion: tekton.dev/v1 kind: Task metadata: name: source-build-oci-ta + annotations: + tekton.dev/pipelines.minVersion: 0.12.1 + tekton.dev/tags: appstudio labels: app.kubernetes.io/version: "0.1" - annotations: - tekton.dev/pipelines.minVersion: "0.12.1" - tekton.dev/tags: "appstudio" spec: description: Source image build. params: - - name: BINARY_IMAGE - description: Binary image name from which to generate the source image name. - type: string - name: BASE_IMAGES - description: >- - Base images used to build the binary image. Each image per line in the same order of FROM - instructions specified in a multistage Dockerfile. Default to an empty string, which means - to skip handling a base image. + description: Base images used to build the binary image. Each image + per line in the same order of FROM instructions specified in a multistage + Dockerfile. Default to an empty string, which means to skip handling + a base image. type: string default: "" - - name: SOURCE_ARTIFACT - description: The Trusted Artifact URI pointing to the artifact with the application source code. + - name: BINARY_IMAGE + description: Binary image name from which to generate the source image + name. type: string - name: CACHI2_ARTIFACT - description: The Trusted Artifact URI pointing to the artifact with the prefetched dependencies. + description: The Trusted Artifact URI pointing to the artifact with + the prefetched dependencies. type: string default: "" - + - name: SOURCE_ARTIFACT + description: The Trusted Artifact URI pointing to the artifact with + the application source code. + type: string results: - name: BUILD_RESULT description: Build result. - - name: SOURCE_IMAGE_URL - description: The source image url. - name: SOURCE_IMAGE_DIGEST description: The source image digest. + - name: SOURCE_IMAGE_URL + description: The source image url. volumes: - name: workdir emptyDir: {} stepTemplate: volumeMounts: - - name: workdir - mountPath: /var/workdir + - mountPath: /var/workdir + name: workdir steps: - name: use-trusted-artifact image: quay.io/redhat-appstudio/build-trusted-artifacts:latest@sha256:4e39fb97f4444c2946944482df47b39c5bbc195c54c6560b0647635f553ab23d @@ -52,35 +54,24 @@ spec: - $(params.CACHI2_ARTIFACT)=/var/workdir/cachi2 - name: build image: quay.io/redhat-appstudio/build-definitions-source-image-build-utils@sha256:cd87bbe51f1c22ff7578f5c9caf19db4f9ee7aefd0307288383b9bd478cdf856 - computeResources: - limits: - memory: 2Gi - requests: - memory: 512Mi - cpu: 250m - workingDir: "/var/workdir" - securityContext: - runAsUser: 0 - capabilities: - add: - - SETFCAP + workingDir: /var/workdir env: - name: BINARY_IMAGE - value: "$(params.BINARY_IMAGE)" + value: $(params.BINARY_IMAGE) - name: SOURCE_DIR - value: "/var/workdir/source" + value: /var/workdir/source - name: BASE_IMAGES - value: "$(params.BASE_IMAGES)" + value: $(params.BASE_IMAGES) - name: RESULT_FILE - value: "$(results.BUILD_RESULT.path)" + value: $(results.BUILD_RESULT.path) - name: CACHI2_ARTIFACTS_DIR - value: "/var/workdir/cachi2" + value: /var/workdir/cachi2 - name: RESULT_SOURCE_IMAGE_URL - value: "$(results.SOURCE_IMAGE_URL.path)" + value: $(results.SOURCE_IMAGE_URL.path) - name: RESULT_SOURCE_IMAGE_DIGEST - value: "$(results.SOURCE_IMAGE_DIGEST.path)" + value: $(results.SOURCE_IMAGE_DIGEST.path) - name: WS_BUILD_RESULT_FILE - value: "/var/workdir/source_build_result.json" + value: /var/workdir/source_build_result.json script: | #!/usr/bin/env bash set -euo pipefail @@ -110,3 +101,14 @@ spec: cat "$RESULT_FILE" | jq -r ".image_digest" >"$RESULT_SOURCE_IMAGE_DIGEST" cp "$RESULT_FILE" "$WS_BUILD_RESULT_FILE" + computeResources: + limits: + memory: 2Gi + requests: + cpu: 250m + memory: 512Mi + securityContext: + capabilities: + add: + - SETFCAP + runAsUser: 0