diff --git a/.act.secrets.template b/.act.secrets.template new file mode 100644 index 0000000000..7b797175e0 --- /dev/null +++ b/.act.secrets.template @@ -0,0 +1,7 @@ +# vim:ft=env +DOCKERHUB_USERNAME= +DOCKERHUB_TOKEN= +GHCR_ACCOUNT= +GHCR_TOKEN= +GITHUB_TOKEN= + diff --git a/.actrc b/.actrc new file mode 100644 index 0000000000..684807588c --- /dev/null +++ b/.actrc @@ -0,0 +1,9 @@ +--rm +--reuse +--container-options=--privileged +--pull=false +--platform=ubuntu-latest=catthehacker/ubuntu:custom-20.04 +--container-architecture=linux/amd64 +--workflows=.github/workflows +--secret-file=./.act.secrets + diff --git a/.env.example b/.env.example index 5761f81095..00362bd6cc 100644 --- a/.env.example +++ b/.env.example @@ -53,4 +53,4 @@ INTEGRATION_POSTGRES_PORT=127.0.0.1:65432 # Integration Neo4j INTEGRATION_NEO4J_AUTH=neo4j/bloodhoundcommunityedition INTEGRATION_NEO4J_PORT=127.0.0.1:37687 -INTEGRATION_NEO4J_WEB_PORT=127.0.0.1:37474 \ No newline at end of file +INTEGRATION_NEO4J_WEB_PORT=127.0.0.1:37474 diff --git a/.github/actions/build-container-image/action.yml b/.github/actions/build-container-image/action.yml new file mode 100644 index 0000000000..bf2eb5d2eb --- /dev/null +++ b/.github/actions/build-container-image/action.yml @@ -0,0 +1,189 @@ +# Copyright 2024 Specter Ops, Inc. +# +# Licensed under the Apache License, Version 2.0 +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 + +--- +name: Build and Publish Container Image + +description: |- + This composite action builds a container image based on the specified Dockerfile and metadata. + It can optionally push the built image to a container registry. + Ensure you have the necessary Docker and QEMU setup steps in your workflow for cross-platform builds. + +inputs: + image_labels: + required: true + default: "false" + description: > + A JSON object containing image labels and metadata. + These labels help describe the image and can include information like version, author, and licenses. + + There are given predefined values that can be overwritten: + org.opencontainers.image.authors=https://github.com/orgs/SpecterOps/teams/bloodhound-engineering + org.opencontainers.image.licenses=Commercial Standard License + org.opencontainers.image.vendor=SpecterOps + image_tags: + required: true + default: "false" + description: > + A comma-separated list of tags to assign to the built image. + These tags help identify different versions or variants of the image. + image_metadata_json: + required: true + default: "false" + description: | + The metadata required to build the container image. + This should be the JSON output from a previous 'generate-metadata' action. + + See: https://github.com/docker/metadata-action#json-output-object + image_provenance: + required: true + default: "false" + description: > + Whether to include image provenance information in the image metadata. + Provenance information provides details about how the image was built and can be useful for auditing. + image_sbom: + required: true + default: "false" + description: > + Whether to include a Software Bill of Materials (SBOM) in the image metadata. + An SBOM lists all the software components used in the image, enhancing transparency and security. + dockerfile: + default: Dockerfile + description: > + The name of the Dockerfile used for building the container image. + If not specified, it defaults to 'Dockerfile' in the repository root. + + Example: 'Dockerfile.prod' for a production-specific Dockerfile. + build_context: + default: "{{defaultContext}}" + description: |- + Build's context is the set of files located in the specified PATH or URL (default Git context) + build_target: + description: > + The build stage target for multi-stage Docker builds, if applicable. + Specify this if your Dockerfile has multiple stages, and you want to build a specific one. + + Example: 'production' for a multi-stage Dockerfile with a 'production' stage. + build_args: + description: > + Additional build arguments to pass to the Docker build process. + These arguments can be used to customize the build based on your requirements. + + Predefined values may already be present, and any inputs provided here will be appended. + + Example: 'MY_VARIABLE=value' to set an environment variable during the build. + build_contexts: + description: > + Additional build contexts to pass to Docker build process. + + Define additional build context with specified contents. In Dockerfile the + context can be accessed when FROM name or --from=name is used. When + Dockerfile defines a stage with the same name it is overwritten. + + Example: 'name=path' + build_outputs: + description: > + Set build additional build outputs. + cache_from: + description: > + The source image repository from which to cache layers during the build. + This can help improve build speed by reusing layers from a previously built image. + + Default: type=gha + + Example: 'docker.io/my-app:cache' to cache from a specific image. + default: |- + type=gha + cache_to: + description: > + The destination image cache settings to optimize the caching strategy during the build. + This input specifies where to store cached layers and how they are scoped. + + Default: type=gha,mode=max + + Example: "type=gha,mode=max,scope=\$\{\{ github.workflow \}\}" + default: |- + type=gha,mode=max + push_image: + required: true + default: "false" + description: > + Whether to push the built container image to the registry after building. + Set this to 'true' if you want to automatically push the image. + + Example: 'true' to push the image to the registry, 'false' to skip pushing. + +runs: + using: composite + steps: + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + with: + platforms: linux/amd64,linux/arm64 + + - name: Set up buildx + id: buildx + uses: docker/setup-buildx-action@v3 + with: + platforms: linux/amd64,linux/arm64 + + - name: Build + uses: docker/build-push-action@v6 + with: + context: ${{ inputs.build_context }} + file: ${{ inputs.dockerfile }} + target: ${{ inputs.build_target }} + build-args: | + BUILDTIME=${{ fromJSON(inputs.image_metadata_json).labels['org.opencontainers.image.created'] }} + VERSION=${{ fromJSON(inputs.image_metadata_json).labels['org.opencontainers.image.version'] }} + REVISION=${{ fromJSON(inputs.image_metadata_json).labels['org.opencontainers.image.revision'] }} + ${{ inputs.build_args }} + labels: | + org.opencontainers.image.authors=https://github.com/orgs/SpecterOps/teams/bloodhound-engineering + org.opencontainers.image.licenses=Commercial Standard License + org.opencontainers.image.vendor=SpecterOps + ${{ inputs.image_labels }} + build-contexts: | + ${{ inputs.build_contexts }} + provenance: ${{ inputs.image_provenance }} + sbom: ${{ inputs.image_sbom }} + cache-from: | + ${{ inputs.cache_from }} + cache-to: | + ${{ inputs.cache_to }} + tags: | + ${{ inputs.image_tags }} + outputs: | + type=docker + ${{ inputs.build_outputs }} + + - name: Push Images to Registry + if: ${{ contains(inputs.push_image, 'true') }} + shell: bash + run: | + echo "::group::Push Images" + # Read each line as an image tag and push it + while IFS= read -r tag; do + # Remove leading/trailing whitespace if any + tag="$(echo -e "${tag}" | tr -d '[:space:]')" + + notice_title="Pushing ${tag}" + + echo "::notice title=$notice_title" + docker push "${tag}" + echo "::notice Finished pushing image" + done <<< "${{ inputs.image_tags }}" + echo "::endgroup::" diff --git a/.github/actions/container-image-metadata/action.yml b/.github/actions/container-image-metadata/action.yml new file mode 100644 index 0000000000..1c4c3b4821 --- /dev/null +++ b/.github/actions/container-image-metadata/action.yml @@ -0,0 +1,123 @@ +# Copyright 2024 Specter Ops, Inc. +# +# Licensed under the Apache License, Version 2.0 +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 + +--- +name: Generate Container Image Metadata + +description: | + This composite action generates metadata for a container image and extracts useful information, + such as JSON data, tags, labels, revision, version, and the container image reference. + The metadata is essential for tracking and managing container images effectively. + +inputs: + container_registry: + default: docker.io + required: true + description: > + The name of the container image registry where the image will be hosted. + + Example: 'docker.io' for Docker Hub or a custom registry URL. + + image_repository: + required: true + description: > + The name of the repository where the container image will be stored within the registry. + + Example: 'my-app' or 'username/my-app' if it's a user-specific repository. + + image_flavor: + description: > + See: https://github.com/docker/metadata-action#flavor-input + + image_tags: + description: > + See: https://github.com/docker/metadata-action#tags-input + +outputs: + json: + value: ${{ steps.generate-metadata.outputs.json }} + description: > + The JSON metadata for the container image, including details about the image and its layers. + + tags: + value: ${{ steps.generate-metadata.outputs.tags }} + description: > + A list of tags associated with the container image, which may include version and branch information. + + labels: + value: ${{ steps.generate-metadata.outputs.labels }} + description: > + Custom labels associated with the container image, providing additional information and metadata. + + revision: + value: ${{ fromJSON(steps.generate-metadata.outputs.json).labels['org.opencontainers.image.revision'] }} + description: > + The revision of the container image, if available, typically extracted from metadata labels. + + version: + value: ${{ steps.generate-metadata.outputs.version }} + description: > + The version of the container image, often derived from tags or other versioning patterns. + + image_reference: + value: ${{ steps.set-image-reference.outputs.image_reference }} + description: > + The full image reference, including registry, repository, and tag. + This fully qualified name is used to pull or locate a specific image + from a particular registry (e.g., docker.io/myrepo/myimage:tag). + + image_name: + value: ${{ steps.set-image-reference.outputs.image_name }} + description: > + The image name with repository and tag, typically used locally or + with the default registry. This shorthand version omits the registry + and assumes the default registry if unspecified (e.g., myimage:tag). + +runs: + using: composite + steps: + - name: Downcase container registry name. + id: lower-container-registry + uses: ASzc/change-string-case-action@v6 + with: + string: ${{ inputs.container_registry }} + + - name: Downcase repository name + id: lower-repo + uses: ASzc/change-string-case-action@v6 + with: + string: ${{ inputs.image_repository }} + + - name: Generate metadata + id: generate-metadata + uses: docker/metadata-action@v5 + with: + images: + ${{ steps.lower-container-registry.outputs.lowercase }}/${{ steps.lower-repo.outputs.lowercase }} + flavor: ${{ inputs.image_flavor }} + tags: |- + type=raw,value=sha-{{sha}}-{{date 'YYYYMMDD-HHmmss'}},priority=1500 + type=sha,format=long,priority=1450 + ${{ inputs.image_tags }} + + - name: Set Container Image Reference + id: set-image-reference + shell: bash + run: |- + image_reference=${{ fromJSON(steps.generate-metadata.outputs.json).tags[0] }} + echo "image_reference=$image_reference" >> $GITHUB_OUTPUT + image_name=$(echo "$image_reference" | sed 's/.*\///') + echo "image_name=$image_name" >> $GITHUB_OUTPUT diff --git a/.github/actions/container-registry-authentication/action.yml b/.github/actions/container-registry-authentication/action.yml new file mode 100644 index 0000000000..01f0a4dfbe --- /dev/null +++ b/.github/actions/container-registry-authentication/action.yml @@ -0,0 +1,52 @@ +# Copyright 2024 Specter Ops, Inc. +# +# Licensed under the Apache License, Version 2.0 +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 + +--- +name: Container Registry Authentication + +description: | + This composite action authenticates your GitHub Actions workflow with a container registry. It + allows your workflow to securely push container images to the registry using the provided registry + account and token. + +inputs: + registry_account: + required: true + description: | + The container registry account or username. + + Example: 'myusername' or 'myorg'. + registry_token: + required: true + description: | + The personal access token (PAT) or secret token for + authenticating with the GitHub Container Registry. + Ensure this token has the necessary permissions + to push container images to the specified registry. + container_registry: + required: false + description: | + The container registry that will be authenticated against. + +runs: + using: composite + steps: + - name: Authenticate To Registry + uses: docker/login-action@v3 + with: + registry: ${{ inputs.container_registry }} + username: ${{ inputs.registry_account }} + password: ${{ inputs.registry_token }} diff --git a/.github/workflows/build-container-images.yml b/.github/workflows/build-container-images.yml new file mode 100644 index 0000000000..585b4f7624 --- /dev/null +++ b/.github/workflows/build-container-images.yml @@ -0,0 +1,84 @@ +# Copyright 2024 Specter Ops, Inc. +# +# Licensed under the Apache License, Version 2.0 +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 + +--- +name: Build Container Images +run-name: Build Container Images started by @${{ github.actor }} for ${{ github.ref_name }} + +on: + workflow_call: + inputs: + push_image: + type: boolean + required: true + description: |- + Controls whether to automatically push the built container image to the registry. + Enable this when you want to: + - Automatically deploy images in CI/CD pipelines + - Make images immediately available for testing/staging + - Ensure consistent image availability across environments + + Set to false when: + - Running local or development builds + - Performing security scans before publishing + - Testing build configurations without deployment + + Example: 'true' to push the image to the registry, 'false' to skip pushing. + image_flavors: + type: string + description: |- + Defines variations of the same image for different use cases or environments. + Use image flavors to: + - Create specialized builds (e.g., alpine, slim, full) + - Target different architectures or platforms + - Support multiple runtime configurations + - Maintain backwards compatibility with legacy systems + secrets: + dockerhub_account: + required: true + dockerhub_token: + required: true + ghcr_account: + required: true + ghcr_token: + required: true + gh_access_token: + required: true + outputs: + bloodhound_image_tar_path: + value: ${{ jobs.bloodhound.outputs.image_tar_path }} + bloodhound_image_tar_artifact_name: + value: ${{ jobs.bloodhound.outputs.image_tar_artifact_name }} + +jobs: + bloodhound: + name: Build BloodHound Image + uses: ./.github/workflows/reusable.build-container-image.yml + secrets: + dockerhub_account: ${{ secrets.dockerhub_account }} + dockerhub_token: ${{ secrets.dockerhub_token }} + ghcr_account: ${{ secrets.ghcr_account }} + ghcr_token: ${{ secrets.ghcr_token }} + gh_access_token: ${{ secrets.gh_access_token }} + with: + image_repository: specterops/bloodhound + build_target: dev + dockerfile: dockerfiles/bloodhound.Dockerfile + push_image: ${{ inputs.push_image }} + image_cache_from: |- + type=registry,ref=specterops/bloodhound:buildcache + image_cache_to: |- + type=registry,ref=specterops/bloodhound:buildcache,mode=max diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000000..ed22250621 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,80 @@ +# Copyright 2024 Specter Ops, Inc. +# +# Licensed under the Apache License, Version 2.0 +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 + +--- +name: Continuous Integration (CI) + +on: + pull_request: + branches: + - main + - develop + types: + - assigned + - opened + - synchronize + - reopened + - closed + # https://stephencharlesweiss.com/github-actions-run-on-merge-only + push: + branches: + - main + - dev + +permissions: write-all + +jobs: + cla-check: + name: CLA Check + uses: ./.github/workflows/reusable.cla.yml + secrets: + gh_access_token: ${{ secrets.GITHUB_TOKEN }} + gh_repo_scope: ${{ secrets.REPO_SCOPE }} + + build-container-images: + needs: cla-check + name: Build Container Images + uses: ./.github/workflows/build-container-images.yml + with: + push_image: false + secrets: + dockerhub_account: ${{ secrets.DOCKERHUB_USERNAME }} + dockerhub_token: ${{ secrets.DOCKERHUB_TOKEN }} + ghcr_account: ${{ github.actor }} + ghcr_token: ${{ secrets.GITHUB_TOKEN }} + gh_access_token: ${{ secrets.GITHUB_TOKEN }} + + static-code-analysis: + name: Static Code Analysis + needs: [cla-check, build-container-images] + uses: ./.github/workflows/static-code-analysis.yml + with: + bloodhound_image_tar_artifact_name: ${{ needs.build-container-images.outputs.bloodhound_image_tar_artifact_name }} + bloodhound_image_tar_path: ${{ needs.build-container-images.outputs.bloodhound_image_tar_path }} + secrets: + dockerhub_account: ${{ secrets.DOCKERHUB_USERNAME }} + dockerhub_token: ${{ secrets.DOCKERHUB_TOKEN }} + ghcr_account: ${{ github.actor }} + ghcr_token: ${{ secrets.GITHUB_TOKEN }} + gh_access_token: ${{ secrets.GITHUB_TOKEN }} + + testing: + name: Code Testing + needs: [cla-check, build-container-images] + uses: ./.github/workflows/testing.yml + with: + bloodhound_image_tar_artifact_name: ${{ needs.build-container-images.outputs.bloodhound_image_tar_artifact_name }} + bloodhound_image_tar_path: ${{ needs.build-container-images.outputs.bloodhound_image_tar_path }} diff --git a/.github/workflows/cla.yml b/.github/workflows/cla.yml deleted file mode 100644 index 262e05591b..0000000000 --- a/.github/workflows/cla.yml +++ /dev/null @@ -1,39 +0,0 @@ -# Copyright 2023 Specter Ops, Inc. -# -# Licensed under the Apache License, Version 2.0 -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -# SPDX-License-Identifier: Apache-2.0 - -name: "CLA Assistant" -on: - issue_comment: - types: [created] - pull_request_target: - types: [opened, closed, synchronize] - -jobs: - CLAssistant: - runs-on: ubuntu-latest - steps: - - name: "CLA Assistant" - if: (github.event.comment.body == 'recheck' || github.event.comment.body == 'I have read the CLA Document and I hereby sign the CLA') || github.event_name == 'pull_request_target' - uses: contributor-assistant/github-action@v2.2.1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - PERSONAL_ACCESS_TOKEN: ${{ secrets.REPO_SCOPE }} - with: - path-to-signatures: "signatures.json" - path-to-document: "https://github.com/BloodHoundAD/CLA/blob/main/ICLA.md" - branch: "main" - remote-organization-name: BloodHoundAD - remote-repository-name: CLA diff --git a/.github/workflows/reusable.build-container-image.yml b/.github/workflows/reusable.build-container-image.yml new file mode 100644 index 0000000000..35d3c3ae06 --- /dev/null +++ b/.github/workflows/reusable.build-container-image.yml @@ -0,0 +1,307 @@ +# Copyright 2024 Specter Ops, Inc. +# +# Licensed under the Apache License, Version 2.0 +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 + +name: Container Image Build Pipeline +run-name: Building Container Image for ${{ inputs.image_repository }} by @${{ github.actor }} on ${{ github.ref_name }} + +on: + workflow_dispatch: + inputs: + image_repository: + type: string + required: true + description: > + The name of the repository where the container image will be stored in the container registry. + This repository name uniquely identifies the image within the registry. + Combine this with the 'container_registry' input to form the full URL for the image. + + Example: 'my-app' for a repository named 'my-app' in the container registry. + dockerfile: + type: string + description: > + The name of the Dockerfile used for building the container image. + If not specified, it defaults to 'Dockerfile' in the repository root. + + Example: 'Dockerfile.prod' for a production-specific Dockerfile. + build_target: + type: string + description: |- + The build stage target for multi-stage Docker builds, if applicable. + Specify this if your Dockerfile has multiple stages, and you want to + build a specific one. + + Example: 'production' for a multi-stage Dockerfile with a 'production' + stage. + image_flavors: + type: string + description: |- + Additional image flavor information or tags. + image_cache_from: + type: string + description: > + The source image repository from which to cache layers during the build. + This can help improve build speed by reusing layers from a previously built image. + + Example: 'docker.io/my-app:cache' to cache from a specific image. + image_cache_to: + type: string + description: > + The destination image cache settings to optimize the caching strategy during the build. + This input specifies where to store cached layers and how they are scoped. + Values provided here will be appended to any default cache settings. + + Predefined values may already be present, and any inputs provided here will be appended. + + Example: "type=gha,mode=max,scope=\$\{\{ github.workflow \}\}" + timeout_minutes: + description: Job timeout configuration in minutes + type: number + default: 30 + push_image: + type: boolean + default: false + description: > + Whether to push the built container image to the registry after building. + Set this to 'true' if you want to automatically push the image. + + Example: 'true' to push the image to the registry, 'false' to skip pushing. + workflow_call: + inputs: + build_context: + type: string + description: | + Specifies the build context directory for Docker. + Choose your build context carefully to: + - Control which files are available during build + - Optimize build performance by limiting included files + - Ensure security by excluding sensitive files + - Support multi-stage builds with specific contexts + image_repository: + type: string + required: true + description: > + The name of the repository where the container image will be stored in the container registry. + This repository name uniquely identifies the image within the registry. + Combine this with the 'container_registry' input to form the full URL for the image. + + Example: 'my-app' for a repository named 'my-app' in the container registry. + dockerfile: + type: string + description: > + The name of the Dockerfile used for building the container image. + If not specified, it defaults to 'Dockerfile' in the repository root. + + Example: 'Dockerfile.prod' for a production-specific Dockerfile. + build_target: + type: string + description: |- + The build stage target for multi-stage Docker builds, if applicable. + Specify this if your Dockerfile has multiple stages, and you want to + build a specific one. + + Example: 'production' for a multi-stage Dockerfile with a 'production' + stage. + build_args: + type: string + description: |- + Build-time variables that customize the container build process. + Use build args to: + - Inject version information at build time + - Configure build-specific settings without modifying Dockerfile + - Support different configurations for dev/staging/prod + - Pass secrets safely during build (using --secret) + + Predefined values may already be present, and any inputs provided here will be appended. + + Example: 'VERSION=${GITHUB_SHA}' to embed git commit information + build_contexts: + type: string + description: |- + Additional named build contexts for multi-stage builds. + Use multiple build contexts when you need to: + - Separate build dependencies from runtime dependencies + - Include files from different locations without copying + - Optimize layer caching for different build stages + - Support complex multi-stage build patterns + + In Dockerfile, access these contexts using FROM name or --from=name. + Note: These contexts override same-named stages in the Dockerfile. + + Example: 'deps=/path/to/dependencies,assets=/path/to/static-files' + image_provenance: + type: string + default: "false" + description: |- + Controls inclusion of SLSA provenance in image metadata. + Enable provenance when you need to: + - Meet supply chain security requirements + - Provide audit trails for compliance + - Verify image build authenticity + - Support automated security policy enforcement + + Provenance data includes build source, tooling, and environment details. + image_sbom: + type: string + default: "false" + description: |- + Controls generation of Software Bill of Materials (SBOM) for the image. + Enable SBOM generation to: + - Track and audit all software dependencies + - Identify and respond to security vulnerabilities + - Meet compliance requirements for software transparency + - Support automated vulnerability scanning + - Enable dependency analysis and lifecycle management + image_flavor: + type: string + description: |- + Additional image flavor information or tags. + image_cache_from: + type: string + description: > + The source image repository from which to cache layers during the build. + This can help improve build speed by reusing layers from a previously built image. + + Example: 'docker.io/my-app:cache' to cache from a specific image. + image_cache_to: + type: string + description: > + The destination image cache settings to optimize the caching strategy during the build. + This input specifies where to store cached layers and how they are scoped. + Values provided here will be appended to any default cache settings. + + Predefined values may already be present, and any inputs provided here will be appended. + + Example: "type=gha,mode=max,scope=\$\{\{ github.workflow \}\}" + build_output_tar_dir: + type: string + description: > + The directory path where the tar file of the built image will be saved, + to be used as an artifact upload location with the `actions/upload-artifact@v4` GitHub Action. + This tar archive can then be retrieved from the workflow artifacts for further use or distribution. + default: "/tmp" + timeout_minutes: + description: Job timeout configuration in minutes + type: number + default: 30 + push_image: + type: boolean + default: false + description: |- + Whether to push the built container image to the registry after building. + Set this to 'true' if you want to automatically push the image. + + Example: 'true' to push the image to the registry, 'false' to skip pushing. + build_automation_ref: + type: string + description: |- + When the workflow is reused in another repo, we have to import the + .github/actions directory for repository. + secrets: + dockerhub_account: + required: true + dockerhub_token: + required: true + ghcr_account: + required: true + ghcr_token: + required: true + gh_access_token: + required: true + outputs: + image_reference: + value: ${{ jobs.build-container-image.outputs.image_reference }} + image_name: + value: ${{ jobs.build-container-image.outputs.image_name }} + image_tar_path: + value: ${{ jobs.build-container-image.outputs.image_tar_path }} + image_tar_artifact_name: + value: ${{ jobs.build-container-image.outputs.image_tar_artifact_name }} + +jobs: + build-container-image: + name: Build and Package ${{ inputs.image_repository }} Container + runs-on: ubuntu-latest + timeout-minutes: ${{ inputs.timeout_minutes }} + outputs: + image_reference: ${{ steps.container-image-metadata.outputs.image_reference }} + image_name: ${{ steps.container-image-metadata.outputs.image_name }} + image_tar_path: ${{ inputs.build_output_tar_dir }}/${{ steps.container-image-metadata.outputs.version }}.tar + image_tar_artifact_name: ${{ steps.container-image-metadata.outputs.version }} + steps: + - name: Checkout Source Code Repository + uses: actions/checkout@v4 + + - if: inputs.build_automation_ref != '' + name: Checkout Build Automation Workflows + uses: actions/checkout@v4 + with: + clean: false + repository: SpecterOps/BloodHound + ref: ${{ inputs.build_automation_ref }} + token: ${{ secrets.gh_access_token }} + sparse-checkout-cone-mode: false + sparse-checkout: |- + .github/actions + + - uses: ./.github/actions/container-registry-authentication + id: dockerhub-authentication + name: Authenticate with DockerHub Registry + with: + container_registry: docker.io + registry_account: ${{ secrets.dockerhub_account }} + registry_token: ${{ secrets.dockerhub_token }} + + - uses: ./.github/actions/container-registry-authentication + id: ghcr-authentication + name: Authenticate with GitHub Container Registry + with: + container_registry: ghcr.io + registry_account: ${{ secrets.ghcr_account }} + registry_token: ${{ secrets.ghcr_token }} + + - uses: ./.github/actions/container-image-metadata + id: container-image-metadata + with: + image_repository: ${{ inputs.image_repository }} + image_flavor: ${{ inputs.image_flavor }} + + - uses: ./.github/actions/build-container-image + id: build-container-image + with: + build_args: ${{ inputs.build_args }} + build_context: ${{ inputs.build_context }} + build_contexts: ${{ inputs.build_contexts }} + build_target: ${{ inputs.build_target }} + build_outputs: |- + type=docker,dest=${{ inputs.build_output_tar_dir }}/${{ steps.container-image-metadata.outputs.version }}.tar + cache_from: ${{ inputs.image_cache_from }} + cache_to: ${{ inputs.image_cache_to }} + dockerfile: ${{ inputs.dockerfile }} + image_labels: ${{ steps.container-image-metadata.outputs.labels }} + image_metadata_json: ${{ steps.container-image-metadata.outputs.json }} + image_provenance: ${{ inputs.image_provenance }} + image_sbom: ${{ inputs.image_sbom }} + image_tags: ${{ steps.container-image-metadata.outputs.tags }} + push_image: ${{ inputs.push_image }} + + - if: inputs.build_output_tar_dir != '' + name: Archive Container Image for Downstream Jobs + uses: actions/upload-artifact@v4 + with: + if-no-files-found: error + retention-days: 1 + name: ${{ steps.container-image-metadata.outputs.version }} + path: ${{ inputs.build_output_tar_dir }}/${{ steps.container-image-metadata.outputs.version }}.tar diff --git a/.github/workflows/reusable.cla.yml b/.github/workflows/reusable.cla.yml new file mode 100644 index 0000000000..270d337e62 --- /dev/null +++ b/.github/workflows/reusable.cla.yml @@ -0,0 +1,75 @@ +# Copyright 2024 Specter Ops, Inc. +# +# Licensed under the Apache License, Version 2.0 +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 + +name: CLA Assistant Reusable Workflow +on: + workflow_call: + inputs: + signatures_path: + type: string + default: "signatures.json" + description: |- + Location where CLA signatures are stored and tracked. + This file maintains the record of all contributors who have signed the agreement. + Customize this path when: + - Using a different storage location for signatures + - Managing multiple CLAs in the same repository + - Integrating with existing signature tracking systems + document_path: + type: string + default: "https://github.com/BloodHoundAD/CLA/blob/main/ICLA.md" + description: |- + URL to the Contributor License Agreement document that contributors must sign. + This document defines the terms under which contributions are accepted. + Customize this when: + - Using a different CLA version + - Implementing organization-specific agreements + - Supporting multiple languages or jurisdictions + branch: + type: string + default: "main" + description: "Branch name for the CLA repository" + remote_organization: + type: string + default: "BloodHoundAD" + description: "Organization name containing the CLA repository" + remote_repository: + type: string + default: "CLA" + description: "Name of the CLA repository" + secrets: + gh_access_token: + required: true + gh_repo_scope: + required: true + +jobs: + process-cla: + name: Process CLA + runs-on: ubuntu-latest + steps: + - name: CLA Assistant + if: (github.event.comment.body == 'recheck' || github.event.comment.body == 'I have read the CLA Document and I hereby sign the CLA') || github.event_name == 'pull_request_target' + uses: contributor-assistant/github-action@v2.2.1 + env: + GITHUB_TOKEN: ${{ secrets.gh_access_token }} + PERSONAL_ACCESS_TOKEN: ${{ secrets.gh_repo_scope }} + with: + path-to-signatures: ${{ inputs.signatures_path }} + path-to-document: ${{ inputs.document_path }} + branch: ${{ inputs.branch }} + remote-organization-name: ${{ inputs.remote_organization }} + remote-repository-name: ${{ inputs.remote_repository }} diff --git a/.github/workflows/reusable.lint-container-image.yml b/.github/workflows/reusable.lint-container-image.yml new file mode 100644 index 0000000000..f3169eae93 --- /dev/null +++ b/.github/workflows/reusable.lint-container-image.yml @@ -0,0 +1,104 @@ +# Copyright 2024 Specter Ops, Inc. +# +# Licensed under the Apache License, Version 2.0 +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 + +--- +name: Docker Image Linting +run-name: Docker Image Linting by @${{ github.actor }} for ${{ github.ref_name }} + +on: + workflow_call: + inputs: + build_automation_ref: + type: string + description: |- + When the workflow is reused in another repo, we have to import the .github/actions directory + for the cloudops-tools repository. + secrets: + dockerhub_account: + required: true + dockerhub_token: + required: true + ghcr_account: + required: true + ghcr_token: + required: true + gh_access_token: + required: true + +jobs: + find-dockerfiles: + name: Discover Dockerfile Locations + runs-on: ubuntu-latest + timeout-minutes: 30 + outputs: + file_paths: ${{ steps.find-files.outputs.file_paths }} + steps: + - name: Checkout Repository + uses: actions/checkout@v4 + + - if: inputs.build_automation_ref != '' + name: Checkout Reusable Workflows + uses: actions/checkout@v4 + with: + clean: false + repository: SpecterOps/build-automation + ref: ${{ inputs.build_automation_ref }} + token: ${{ secrets.gh_access_token }} + sparse-checkout-cone-mode: false + sparse-checkout: | + .github/workflows + .github/actions + + - uses: ./.github/actions/container-registry-authentication + name: Authenticate with DockerHub Registry + with: + container_registry: docker.io + registry_account: ${{ secrets.dockerhub_account }} + registry_token: ${{ secrets.dockerhub_token }} + + - name: Pull Build Automation Image + shell: bash + run: | + docker pull specterops/build-automation:berner-pre0.0 + + - name: Locate Dockerfile Paths + id: find-files + shell: bash + run: | + docker run --rm \ + --volume $GITHUB_WORKSPACE:/app \ + specterops/build-automation:berner-pre0.0 \ + find-files --format=json-array --output=file:///app/file_paths.txt . Dockerfile + + echo "$(cat $GITHUB_WORKSPACE/file_paths.txt)" >> $GITHUB_OUTPUT + + hadolint: + needs: find-dockerfiles + name: Run Hadolint Analysis + runs-on: ubuntu-latest + timeout-minutes: 30 + strategy: + matrix: + paths: ${{ fromJson(needs.find-dockerfiles.outputs.file_paths) }} + steps: + - name: Checkout Repository + uses: actions/checkout@v4 + + - name: Lint Dockerfile + uses: hadolint/hadolint-action@v3.1.0 + with: + dockerfile: ${{ matrix.paths }} + recursive: false diff --git a/.github/workflows/reusable.vulnerability-scan.yml b/.github/workflows/reusable.vulnerability-scan.yml new file mode 100644 index 0000000000..d9e65afa42 --- /dev/null +++ b/.github/workflows/reusable.vulnerability-scan.yml @@ -0,0 +1,103 @@ +# Copyright 2024 Specter Ops, Inc. +# +# Licensed under the Apache License, Version 2.0 +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 + +name: Security Vulnerability Analysis +run-name: Security Vulnerability Analysis started by @${{ github.actor }} for ${{ github.ref_name }} + +on: + workflow_call: + inputs: + scan_type: + type: string + description: |- + Controls the scope and target of the vulnerability scan to match your security needs. + Different scan types serve different security assessment purposes: + - 'repo': Comprehensive scan of the entire repository to catch all potential vulnerabilities + - 'fs': Targeted scan of specific directories when you need to check particular components + - 'image': Container-specific vulnerabilities scan for Docker images + - 'config': Focus on misconfigurations in infrastructure-as-code files + + Defaults to 'repo' for maximum coverage + default: repo + scan_ref: + type: string + description: |- + The target directory or path to scan for vulnerabilities. + For image scans, specify the image reference. + For filesystem scans, specify the directory path. + + Default: './' (current directory) + default: ./ + severity: + type: string + description: |- + Determines which security findings to report based on their impact level. + Filter vulnerabilities to focus on the most important issues first: + - CRITICAL: Severe vulnerabilities requiring immediate attention + - HIGH: Significant security risks that should be addressed soon + - MEDIUM: Moderate risks that should be planned for remediation + - LOW: Minor issues that pose minimal risk + - UNKNOWN: Issues with undetermined impact + + Default: 'CRITICAL,HIGH' to prioritize the most severe security issues + default: CRITICAL,HIGH + exit_code: + type: string + description: |- + Exit code to return when vulnerabilities matching the specified severity criteria are found. + Use '0' to always pass the workflow regardless of findings. + + Default: '1' (fail on findings) + default: '1' + ignore_unfixed: + type: boolean + description: |- + Controls whether to include vulnerabilities that currently have no available fixes. + Enable this when you want to: + - Focus on actionable items that can be immediately addressed + - Reduce noise in security reports + - Prioritize fixable vulnerabilities first + + Set to false to maintain awareness of all vulnerabilities, even those without current patches. + Default: false + default: false + trivy_db_repository: + type: string + default: ghcr.io/aquasecurity/trivy-db,public.ecr.aws/aquasecurity/trivy-db + trivy_java_db_repository: + type: string + default: ghcr.io/aquasecurity/trivy-java-db,public.ecr.aws/aquasecurity/trivy-java-db + +jobs: + trivy-scan: + name: Trivy Vulnerability Analysis + runs-on: ubuntu-latest + timeout-minutes: 30 + steps: + - name: Checkout Repository + uses: actions/checkout@v4 + + - name: Execute Trivy Security Scan + uses: aquasecurity/trivy-action@0.29.0 + with: + scan-type: ${{ inputs.scan_type }} + scan-ref: ${{ inputs.scan_ref }} + severity: ${{ inputs.severity }} + exit-code: ${{ inputs.exit_code }} + ignore-unfixed: ${{ inputs.ignore_unfixed }} + env: + TRIVY_DB_REPOSITORY: ${{ inputs.trivy_db_repository }} + TRIVY_JAVA_DB_REPOSITORY: ${{ inputs.trivy_java_db_repository }} diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml deleted file mode 100644 index 2600142943..0000000000 --- a/.github/workflows/run-tests.yml +++ /dev/null @@ -1,71 +0,0 @@ -# Copyright 2023 Specter Ops, Inc. -# -# Licensed under the Apache License, Version 2.0 -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -# SPDX-License-Identifier: Apache-2.0 - -name: Run Tests - -on: - push: - branches: [main] - pull_request: - types: [opened, synchronize] - -jobs: - run-tests: - runs-on: ubuntu-latest - - steps: - - name: Checkout source code for this repository - uses: actions/checkout@v3 - - - name: Set up Docker Compose - run: | - sudo apt-get update -y - sudo apt-get install -y docker-compose - docker-compose version - - - name: Start PostgreSQL and Neo4j Containers - run: | - docker-compose -f docker-compose.testing.yml up -d - - - name: Install Go - uses: actions/setup-go@v4 - with: - go-version: '^1.23.0' - - - name: Install Python - uses: actions/setup-python@v4 - with: - python-version: '3.10' - - - name: Run Tests - run: | - export INTEGRATION_CONFIG_PATH=$(pwd)/.github/config/integration.config.json - python packages/python/beagle/main.py test -avi - - - name: Neo4j Debug Logs - if: failure() - run: | - docker-compose -f docker-compose.testing.yml exec -T testgraph cat /logs/debug.log - - - name: Postgres Debug Logs - if: failure() - run: | - docker-compose -f docker-compose.testing.yml logs testdb - - - name: Stop and Remove Containers - if: ${{ ! cancelled() }} - run: | - docker-compose -f docker-compose.testing.yml down diff --git a/.github/workflows/static-code-analysis.yml b/.github/workflows/static-code-analysis.yml index 35747cb419..63a32e409d 100644 --- a/.github/workflows/static-code-analysis.yml +++ b/.github/workflows/static-code-analysis.yml @@ -14,40 +14,86 @@ # # SPDX-License-Identifier: Apache-2.0 +--- name: Static Code Analysis +run-name: Code Anaylsis started by @${{ github.actor }} for ${{ github.ref_name }} on: - push: - branches: [main] - pull_request: - types: [opened, synchronize] + workflow_call: + inputs: + bloodhound_image_tar_artifact_name: + type: string + required: true + bloodhound_image_tar_path: + type: string + required: true + secrets: + dockerhub_account: + required: true + dockerhub_token: + required: true + ghcr_account: + required: true + ghcr_token: + required: true + gh_access_token: + required: true jobs: - run-analysis: - runs-on: ubuntu-latest + lint-container-images: + name: Analyze Dockerfiles + uses: ./.github/workflows/reusable.lint-container-image.yml + secrets: + dockerhub_account: ${{ secrets.dockerhub_account }} + dockerhub_token: ${{ secrets.dockerhub_token }} + ghcr_account: ${{ github.actor }} + ghcr_token: ${{ secrets.github_token }} + gh_access_token: ${{ secrets.gh_access_token }} - steps: - - name: Checkout source code for this repository - uses: actions/checkout@v3 + trivy-scan: + name: Analyze Security Vulnerabilities + uses: ./.github/workflows/reusable.vulnerability-scan.yml - - name: Install Go - uses: actions/setup-go@v4 + golangci-lint: + name: Analyze Golang Code + runs-on: ubuntu-latest + steps: + - name: Download BloodHound Docker Image Artifact + uses: actions/download-artifact@v4 with: - go-version: "^1.23.0" + name: ${{ inputs.bloodhound_image_tar_artifact_name }} + path: /tmp - - name: Install Node - uses: actions/setup-node@v4 - with: - node-version: 22 + - name: Load BloodHound Docker Image + shell: bash + run: |- + docker load --input "/tmp/${{ inputs.bloodhound_image_tar_artifact_name }}.tar" + docker image ls - - name: Install Yarn - run: | - npm install --global yarn + - name: Run golangci-lint Analysis + shell: bash + run: |- + docker run --rm specterops/bloodhound:${{ inputs.bloodhound_image_tar_artifact_name }} \ + golangci-lint + + eslint: + runs-on: ubuntu-latest + name: Analyze JavaScript/TypeScript Code + steps: + - name: Download BloodHound Docker Image Artifact + uses: actions/download-artifact@v4 + with: + name: ${{ inputs.bloodhound_image_tar_artifact_name }} + path: /tmp - - name: Install Deps - run: | - go run github.com/specterops/bloodhound/packages/go/stbernard deps + - name: Load BloodHound Docker Image + shell: bash + run: |- + docker load --input "/tmp/${{ inputs.bloodhound_image_tar_artifact_name }}.tar" + docker image ls - - name: Run Analysis - run: | - go run github.com/specterops/bloodhound/packages/go/stbernard analysis + - name: Run ESLint Analysis + shell: bash + run: |- + docker run --rm specterops/bloodhound:${{ inputs.bloodhound_image_tar_artifact_name }} \ + yarn run lint diff --git a/.github/workflows/testing.yml b/.github/workflows/testing.yml new file mode 100644 index 0000000000..54364b8abb --- /dev/null +++ b/.github/workflows/testing.yml @@ -0,0 +1,78 @@ +# Copyright 2024 Specter Ops, Inc. +# +# Licensed under the Apache License, Version 2.0 +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 + +--- +name: BloodHound Test Suite +run-name: BloodHound Test Suite started by @${{ github.actor }} for ${{ github.ref_name }} + +on: + workflow_call: + inputs: + bloodhound_image_tar_artifact_name: + type: string + required: true + bloodhound_image_tar_path: + type: string + required: true + +jobs: + integration_tests: + runs-on: ubuntu-latest + name: Run Integration Tests + services: + postgres: + image: postgres:16 + env: + PGUSER: bloodhound + POSTGRES_USER: bloodhound + POSTGRES_PASSWORD: bloodhound + POSTGRES_DB: bloodhound + options: >- + --health-cmd "psql -h localhost -U bloodhound -c select 1 -d bloodhound" + --health-interval 10s + --health-timeout 5s + --health-retries 5 + neo4j: + image: neo4j:4.4.32 + env: + NEO4J_AUTH: neo4j/bloodhoundcommunityedition + NEO4J_dbms_security_auth__enabled: false + NEO4J_server_logs_debug_enabled: true + options: >- + --health-cmd "wget -O /dev/null -q http://localhost:7474" + --health-interval 10s + --health-timeout 5s + --health-retries 5 + + steps: + - name: Download BloodHound Container Image + uses: actions/download-artifact@v4 + with: + name: ${{ inputs.bloodhound_image_tar_artifact_name }} + path: /tmp + + - name: Load BloodHound Container Image + shell: bash + run: |- + docker load --input "/tmp/${{ inputs.bloodhound_image_tar_artifact_name }}.tar" + docker image ls + + - name: Execute Integration Test Suite + shell: bash + run: |- + docker run --rm specterops/bloodhound:${{ inputs.bloodhound_image_tar_artifact_name }} \ + go work use && \ + go list -f '{{.Dir}}/...' -m | xargs go test diff --git a/.github/workflows/vuln-scan.yml b/.github/workflows/vuln-scan.yml deleted file mode 100644 index fc540eaf90..0000000000 --- a/.github/workflows/vuln-scan.yml +++ /dev/null @@ -1,44 +0,0 @@ -# Copyright 2024 Specter Ops, Inc. -# -# Licensed under the Apache License, Version 2.0 -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -# SPDX-License-Identifier: Apache-2.0 - -name: Vulnerability Scan - -on: - push: - branches: [main] - pull_request: - types: [opened, synchronize] - -jobs: - run-analysis: - runs-on: ubuntu-latest - - steps: - - name: Checkout source code for this repository - uses: actions/checkout@v3 - - - name: Run vulnerability scanner - uses: aquasecurity/trivy-action@0.28.0 - with: - scan-type: 'repo' - scan-ref: './' - severity: 'CRITICAL,HIGH' - exit-code: '1' - ignore-unfixed: true - env: - TRIVY_DB_REPOSITORY: ghcr.io/aquasecurity/trivy-db,public.ecr.aws/aquasecurity/trivy-db - TRIVY_JAVA_DB_REPOSITORY: ghcr.io/aquasecurity/trivy-java-db,public.ecr.aws/aquasecurity/trivy-java-db - diff --git a/.gitignore b/.gitignore index ca0085843f..510a399a6f 100644 --- a/.gitignore +++ b/.gitignore @@ -449,4 +449,7 @@ local-harnesses/* !local-harnesses/*.template # folder used by antlr4 VSCode extension -.antlr \ No newline at end of file +.antlr + +# Act secrets +*.secrets diff --git a/dockerfiles/bloodhound.Dockerfile b/dockerfiles/bloodhound.Dockerfile index 74cdfbca2a..7e39e39443 100644 --- a/dockerfiles/bloodhound.Dockerfile +++ b/dockerfiles/bloodhound.Dockerfile @@ -25,6 +25,8 @@ ARG AZUREHOUND_VERSION=v2.2.1 ################ FROM --platform=$BUILDPLATFORM docker.io/library/golang:1.23-alpine3.20 AS godeps +RUN go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.62.2 + ######## # Builder init ################ @@ -36,7 +38,10 @@ ENV SB_VERSION=${version} ENV CHECKOUT_HASH=${checkout_hash} WORKDIR /bloodhound -RUN apk add --update --no-cache git +RUN apk add \ + --update \ + --no-cache \ + git=2.45.2-r0 COPY --from=godeps /usr/local/go/ /usr/local/go/ ENV PATH="/usr/local/go/bin:${PATH}" @@ -56,6 +61,13 @@ WORKDIR /bloodhound RUN go run github.com/specterops/bloodhound/packages/go/stbernard build --os ${TARGETOS} --arch ${TARGETARCH} +######## +# dev/ci +################ +FROM builder AS dev + +RUN yarn add node-jq@6.0.1 + ######## # Package other assets ################ @@ -66,17 +78,21 @@ ARG AZUREHOUND_VERSION WORKDIR /tmp/sharphound # Make some additional directories for minimal container to copy -RUN mkdir -p /opt/bloodhound /etc/bloodhound /var/log -RUN apk --no-cache add p7zip +RUN mkdir -p \ + /opt/bloodhound \ + /etc/bloodhound \ + /var/log && \ + apk add --update --no-cache add p7zip=23.01-r0 # Package Sharphound -RUN wget https://github.com/BloodHoundAD/SharpHound/releases/download/$SHARPHOUND_VERSION/SharpHound-$SHARPHOUND_VERSION.zip -O sharphound-$SHARPHOUND_VERSION.zip -RUN sha256sum sharphound-$SHARPHOUND_VERSION.zip > sharphound-$SHARPHOUND_VERSION.zip.sha256 +RUN wget --progress=dot:giga \ + https://github.com/BloodHoundAD/SharpHound/releases/download/$SHARPHOUND_VERSION/SharpHound-$SHARPHOUND_VERSION.zip -O sharphound-$SHARPHOUND_VERSION.zip && \ + sha256sum sharphound-$SHARPHOUND_VERSION.zip > sharphound-$SHARPHOUND_VERSION.zip.sha256 WORKDIR /tmp/azurehound # Package Azurehound -RUN wget \ +RUN wget --progress=dot:giga \ https://github.com/BloodHoundAD/AzureHound/releases/download/$AZUREHOUND_VERSION/azurehound-darwin-amd64.zip \ https://github.com/BloodHoundAD/AzureHound/releases/download/$AZUREHOUND_VERSION/azurehound-darwin-amd64.zip.sha256 \ https://github.com/BloodHoundAD/AzureHound/releases/download/$AZUREHOUND_VERSION/azurehound-darwin-arm64.zip \ @@ -89,13 +105,15 @@ RUN wget \ https://github.com/BloodHoundAD/AzureHound/releases/download/$AZUREHOUND_VERSION/azurehound-windows-amd64.zip.sha256 \ https://github.com/BloodHoundAD/AzureHound/releases/download/$AZUREHOUND_VERSION/azurehound-windows-arm64.zip \ https://github.com/BloodHoundAD/AzureHound/releases/download/$AZUREHOUND_VERSION/azurehound-windows-arm64.zip.sha256 -RUN sha256sum -cw *.sha256 -RUN 7z x '*.zip' -oartifacts/* -RUN ls + +RUN sha256sum -cw ./*.sha256 && \ + 7z x './*.zip' -oartifacts/* && \ + ls WORKDIR /tmp/azurehound/artifacts -RUN 7z a -tzip -mx9 azurehound-$AZUREHOUND_VERSION.zip azurehound-* -RUN sha256sum azurehound-$AZUREHOUND_VERSION.zip > azurehound-$AZUREHOUND_VERSION.zip.sha256 + +RUN 7z a -tzip -mx9 azurehound-$AZUREHOUND_VERSION.zip azurehound-* && \ + sha256sum azurehound-$AZUREHOUND_VERSION.zip > azurehound-$AZUREHOUND_VERSION.zip.sha256 ######## # Package Bloodhound diff --git a/tools/docker-compose/api.Dockerfile b/tools/docker-compose/api.Dockerfile index 0feda0a638..b54c94258d 100644 --- a/tools/docker-compose/api.Dockerfile +++ b/tools/docker-compose/api.Dockerfile @@ -30,8 +30,8 @@ ARG AZUREHOUND_VERSION WORKDIR /tmp/sharphound # Make some additional directories for minimal container to copy -RUN mkdir -p /opt/bloodhound /etc/bloodhound /var/log -RUN apk --no-cache add p7zip +RUN mkdir -p /opt/bloodhound /etc/bloodhound /var/log && \ + apk --no-cache add p7zip=17.04-r2 # Package Sharphound RUN wget https://github.com/BloodHoundAD/SharpHound/releases/download/$SHARPHOUND_VERSION/SharpHound-$SHARPHOUND_VERSION.zip -O sharphound-$SHARPHOUND_VERSION.zip @@ -40,7 +40,7 @@ RUN sha256sum sharphound-$SHARPHOUND_VERSION.zip > sharphound-$SHARPHOUND_VERSIO WORKDIR /tmp/azurehound # Package Azurehound -RUN wget \ +RUN wget --progres=dot:giga \ https://github.com/BloodHoundAD/AzureHound/releases/download/$AZUREHOUND_VERSION/azurehound-darwin-amd64.zip \ https://github.com/BloodHoundAD/AzureHound/releases/download/$AZUREHOUND_VERSION/azurehound-darwin-amd64.zip.sha256 \ https://github.com/BloodHoundAD/AzureHound/releases/download/$AZUREHOUND_VERSION/azurehound-darwin-arm64.zip \ @@ -53,24 +53,27 @@ RUN wget \ https://github.com/BloodHoundAD/AzureHound/releases/download/$AZUREHOUND_VERSION/azurehound-windows-amd64.zip.sha256 \ https://github.com/BloodHoundAD/AzureHound/releases/download/$AZUREHOUND_VERSION/azurehound-windows-arm64.zip \ https://github.com/BloodHoundAD/AzureHound/releases/download/$AZUREHOUND_VERSION/azurehound-windows-arm64.zip.sha256 -RUN sha256sum -cw *.sha256 -RUN 7z x '*.zip' -oartifacts/* -RUN ls + +RUN sha256sum -cw ./*.sha256 && \ + 7z x './*.zip' -oartifacts/* && \ + ls WORKDIR /tmp/azurehound/artifacts -RUN 7z a -tzip -mx9 azurehound-$AZUREHOUND_VERSION.zip azurehound-* -RUN sha256sum azurehound-$AZUREHOUND_VERSION.zip > azurehound-$AZUREHOUND_VERSION.zip.sha256 +RUN 7z a -tzip -mx9 azurehound-$AZUREHOUND_VERSION.zip azurehound-* && \ + sha256sum azurehound-$AZUREHOUND_VERSION.zip > azurehound-$AZUREHOUND_VERSION.zip.sha256 FROM docker.io/library/golang:1.23 + ARG SHARPHOUND_VERSION ARG AZUREHOUND_VERSION ENV GOFLAGS="-buildvcs=false" + WORKDIR /bloodhound -VOLUME [ "/go/pkg/mod" ] +VOLUME ["/go/pkg/mod"] -RUN mkdir -p /bhapi/collectors/azurehound /bhapi/collectors/sharphound /bhapi/work -RUN go install github.com/go-delve/delve/cmd/dlv@v1.23.0 -RUN go install github.com/air-verse/air@v1.52.3 +RUN mkdir -p /bhapi/collectors/azurehound /bhapi/collectors/sharphound /bhapi/work && \ + go install github.com/go-delve/delve/cmd/dlv@v1.23.0 && \ + go install github.com/air-verse/air@v1.52.3 COPY --from=hound-builder /tmp/sharphound/sharphound-$SHARPHOUND_VERSION.zip /bhapi/collectors/sharphound/ COPY --from=hound-builder /tmp/sharphound/sharphound-$SHARPHOUND_VERSION.zip.sha256 /bhapi/collectors/sharphound/ diff --git a/tools/docker-compose/pgadmin.Dockerfile b/tools/docker-compose/pgadmin.Dockerfile index 66a6467fb8..1c6aa1bb95 100644 --- a/tools/docker-compose/pgadmin.Dockerfile +++ b/tools/docker-compose/pgadmin.Dockerfile @@ -14,7 +14,7 @@ # # SPDX-License-Identifier: Apache-2.0 -FROM docker.io/dpage/pgadmin4 +FROM docker.io/dpage/pgadmin4:8.13.0 # Add bh server config COPY configs/pgadmin/servers.json /pgadmin4/servers.json @@ -23,6 +23,10 @@ COPY configs/pgadmin/servers.json /pgadmin4/servers.json RUN mkdir -p /var/lib/pgadmin/storage/bloodhound_specterops.io/ COPY configs/pgadmin/pgpass /var/lib/pgadmin/storage/bloodhound_specterops.io/pgpass -# Give pgadmin ownership or it will be owned by root and set u(rw) for password file or pgadmin will not use the file +# Give pgadmin ownership or it will be owned by root and set u(rw) for password +# file or pgadmin will not use the file USER root -RUN chown -R pgadmin /var/lib/pgadmin && chmod 600 /var/lib/pgadmin/storage/bloodhound_specterops.io/pgpass +RUN chown -R pgadmin /var/lib/pgadmin && \ + chmod 600 /var/lib/pgadmin/storage/bloodhound_specterops.io/pgpass + +USER pgadmin diff --git a/tools/docker-compose/ui.Dockerfile b/tools/docker-compose/ui.Dockerfile index 3899c79b49..d0decfcbd8 100644 --- a/tools/docker-compose/ui.Dockerfile +++ b/tools/docker-compose/ui.Dockerfile @@ -17,17 +17,21 @@ FROM docker.io/library/node:22-alpine AS base # Setup -RUN mkdir /.yarn && chmod -R go+w /.yarn -RUN mkdir /.cache && chmod -R go+w /.cache -RUN corepack enable -RUN corepack prepare yarn@stable --activate +RUN mkdir /.yarn && \ + chmod -R go+w /.yarn \ + mkdir /.cache && \ + chmod -R go+w /.cache && \ + correpack enable && \ + corepack prepare yarn@stable --activate # BloodHound Workspace files WORKDIR /bloodhound -COPY package.json ./ -COPY yarn.lock ./ -COPY .yarnrc.yml ./ -COPY .yarn ./.yarn + +COPY package.json \ + yarn.lock \ + .yarnrc.yml \ + .yarn \ + ./ # Shared Project Files WORKDIR /bloodhound/packages/javascript @@ -36,13 +40,12 @@ COPY packages/javascript/js-client-library/package.json ./js-client-library/ # BloodHound Project Files WORKDIR /bloodhound/cmd/ui -COPY cmd/ui/package.json ./ -COPY cmd/ui/vite.config.ts ./ -COPY cmd/ui/tsconfig.node.json ./ -COPY cmd/ui/tsconfig.json ./ +COPY cmd/ui/package.json \ + cmd/ui/vite.config.ts \ + cmd/ui/tsconfig.node.json \ + cmd/ui/tsconfig.json \ + cmd/ui/index.html \ + ./ COPY cmd/ui/public ./public -COPY cmd/ui/index.html ./ - -WORKDIR /bloodhound/cmd/ui RUN yarn