Compare commits
180 Commits
v0.8.0-rc6
...
main
Author | SHA1 | Date |
---|---|---|
|
9f30cce152 | |
|
090d95418e | |
|
6a25fa9f5a | |
|
ffb6e688e8 | |
|
a7b6cc6b6b | |
|
fd12beb1cd | |
|
d3c99d5dfc | |
|
6d9b57671f | |
|
54c47d097f | |
|
7a94528218 | |
|
876dcf4653 | |
|
581cbbc316 | |
|
b26c309f4d | |
|
15dd8fde15 | |
|
abdf330e55 | |
|
2b06411214 | |
|
295c633684 | |
|
bccca00d90 | |
|
54ef1cbbf1 | |
|
464a8a3cf9 | |
|
e632903105 | |
|
48a247e521 | |
|
47ad8d0e29 | |
|
3bf89dd0c9 | |
|
bb64751b9f | |
|
1765e1d326 | |
|
a6dcad415c | |
|
cead711238 | |
|
33c01252f6 | |
|
537ebcf446 | |
|
918e88464d | |
|
4bfeb0b0b5 | |
|
dfa4c583b1 | |
|
7d5aee8bb2 | |
|
0bce031350 | |
|
84d7fc852e | |
|
a420868063 | |
|
dabadcec4f | |
|
68484cd32b | |
|
3319e217d0 | |
|
99e76506f0 | |
|
4da81510d1 | |
|
1a71698e3f | |
|
94b56ea805 | |
|
ec3025e878 | |
|
6c71d1551e | |
|
d715341096 | |
|
335e365a78 | |
|
946d8f7b05 | |
|
088e2b45ec | |
|
6bcfad674e | |
|
f9734bb752 | |
|
dc7634cc28 | |
|
e71898ce53 | |
|
8a4febabe5 | |
|
cd992ad99c | |
|
730f80f471 | |
|
18c4322102 | |
|
769a3e5683 | |
|
38f2b1d703 | |
|
ba2730f048 | |
|
b6e47e6ea5 | |
|
84edb08963 | |
|
6bcda9881d | |
|
186b281e71 | |
|
2b11bc95df | |
|
c1ac24469d | |
|
bbdf8ac2f2 | |
|
310a119170 | |
|
f222cf4174 | |
|
af1ebe264b | |
|
70dda77939 | |
|
40b9e11683 | |
|
be7d5c2a55 | |
|
6f64f37774 | |
|
9dafcec9af | |
|
6f241ae803 | |
|
5bf4186068 | |
|
98c4183dd5 | |
|
9f360e12dd | |
|
a40d97f766 | |
|
cdd984dbf2 | |
|
61d9c71d96 | |
|
5776706e3c | |
|
46a22251cd | |
|
28ccc66497 | |
|
4599fe26b8 | |
|
a06072bd76 | |
|
3967730442 | |
|
076aef28c1 | |
|
cb7fd150ba | |
|
afaa782db6 | |
|
cc97e5ebaa | |
|
c29cad76b0 | |
|
2604fe2228 | |
|
1ac62368af | |
|
063491c111 | |
|
5846155f97 | |
|
131abecc4b | |
|
d35acb1b98 | |
|
2e87813a52 | |
|
eb9e67af1f | |
|
029726ec5d | |
|
ad33f00b56 | |
|
23094128e8 | |
|
3d077a8cac | |
|
503961ae91 | |
|
b041a7c6df | |
|
c3cd34939b | |
|
fb0a65a113 | |
|
f737d5f5ac | |
|
59245fdd66 | |
|
d6b1cfbff3 | |
|
f5722b9482 | |
|
7c57d3ee69 | |
|
fac6f31c61 | |
|
133952e1a6 | |
|
1f19a08b6a | |
|
c3a8850de6 | |
|
ebafd49a81 | |
|
3662765ac3 | |
|
46a47e0ef0 | |
|
3b3b535632 | |
|
fad320efff | |
|
7a741b57a9 | |
|
11b95ab75f | |
|
b00c0bd462 | |
|
4f562a2884 | |
|
7e06ca9fe2 | |
|
0a0cd490c5 | |
|
4fce8b537b | |
|
9c510af202 | |
|
db496e591d | |
|
27d569627e | |
|
ce6e1eef36 | |
|
e0d71e7da4 | |
|
7e6b79e9bd | |
|
fcf4def293 | |
|
1632a2d4f7 | |
|
7e05ec1b73 | |
|
006301cd5a | |
|
d1a3559878 | |
|
1a5aee911f | |
|
45af0b205a | |
|
73bfdb5b56 | |
|
cfe101856a | |
|
2dcedc0511 | |
|
d2a010445f | |
|
36b951fff3 | |
|
228cb06d4f | |
|
f55a5e6a06 | |
|
fc648dcf0e | |
|
8c56a3c85c | |
|
1f8d186326 | |
|
913d8b44eb | |
|
ee92cbf49b | |
|
150ef391f5 | |
|
76be634364 | |
|
096b8eaac2 | |
|
d6dd5cdf2f | |
|
11182eb1b8 | |
|
1b6596b5f2 | |
|
dbf56c0a2c | |
|
f5ebba87f8 | |
|
cd5ac2c073 | |
|
d7d61f4a55 | |
|
eb8fbb741e | |
|
9d429de90d | |
|
f82978f817 | |
|
ab0bebd8b3 | |
|
0d663fc1c6 | |
|
219f3d7955 | |
|
6c5f43833f | |
|
72e7129727 | |
|
addd0cd577 | |
|
5cb609d1f9 | |
|
048e8a1375 | |
|
dd7b7169a4 | |
|
5af9b5290a | |
|
655f0ea1d4 |
|
@ -26,7 +26,7 @@ jobs:
|
||||||
- go
|
- go
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5
|
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||||
- name: Initialize CodeQL
|
- name: Initialize CodeQL
|
||||||
uses: github/codeql-action/init@d23060145bc9131d50558d5d4185494a20208101 # v2.2.8
|
uses: github/codeql-action/init@d23060145bc9131d50558d5d4185494a20208101 # v2.2.8
|
||||||
with:
|
with:
|
||||||
|
|
|
@ -33,25 +33,25 @@ jobs:
|
||||||
digest: ${{ steps.build-and-push.outputs.digest }}
|
digest: ${{ steps.build-and-push.outputs.digest }}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5
|
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
- name: Set up QEMU
|
- name: Set up QEMU
|
||||||
uses: docker/setup-qemu-action@68827325e0b33c7199eb31dd4e31fbe9023e06e3 # v3.0.0
|
uses: docker/setup-qemu-action@29109295f81e9208d7d86ff1c6c12d2833863392 # v3.6.0
|
||||||
|
|
||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
id: Buildx
|
id: Buildx
|
||||||
uses: docker/setup-buildx-action@d70bba72b1f3fd22344832f00baa16ece964efeb # v3.3.0
|
uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1
|
||||||
|
|
||||||
- name: Login to Docker Hub
|
- name: Login to Docker Hub
|
||||||
uses: docker/login-action@e92390c5fb421da1463c202d546fed0ec5c39f20 # v3.1.0
|
uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0
|
||||||
with:
|
with:
|
||||||
username: ${{ secrets.DOCKERHUB_USER }}
|
username: ${{ secrets.DOCKERHUB_USER }}
|
||||||
password: ${{ secrets.DOCKERHUB_SECRET }}
|
password: ${{ secrets.DOCKERHUB_SECRET }}
|
||||||
|
|
||||||
- name: Configure AWS credentials
|
- name: Configure AWS credentials
|
||||||
uses: aws-actions/configure-aws-credentials@e3dd6a429d7300a6a4c196c26e071d42e0343502 # v4.0.2
|
uses: aws-actions/configure-aws-credentials@b47578312673ae6fa5b5096b330d9fbac3d116df # v4.2.1
|
||||||
with:
|
with:
|
||||||
role-to-assume: arn:aws:iam::292999226676:role/github_actions-falcoctl-ecr
|
role-to-assume: arn:aws:iam::292999226676:role/github_actions-falcoctl-ecr
|
||||||
aws-region: us-east-1
|
aws-region: us-east-1
|
||||||
|
@ -64,7 +64,7 @@ jobs:
|
||||||
|
|
||||||
- name: Docker Meta
|
- name: Docker Meta
|
||||||
id: meta_falcoctl
|
id: meta_falcoctl
|
||||||
uses: docker/metadata-action@8e5442c4ef9f78752691e2d8f8d19755c6f78e81 # v5.5.1
|
uses: docker/metadata-action@902fa8ec7d6ecbf8d84d538b9b233a880e428804 # v5.7.0
|
||||||
with:
|
with:
|
||||||
# list of Docker images to use as base name for tags
|
# list of Docker images to use as base name for tags
|
||||||
images: |
|
images: |
|
||||||
|
@ -78,7 +78,7 @@ jobs:
|
||||||
|
|
||||||
- name: Build and push
|
- name: Build and push
|
||||||
id: build-and-push
|
id: build-and-push
|
||||||
uses: docker/build-push-action@2cdde995de11925a030ce8070c3d77a52ffcf1c0 # v5.3.0
|
uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
platforms: linux/amd64,linux/arm64
|
platforms: linux/amd64,linux/arm64
|
||||||
|
@ -92,7 +92,7 @@ jobs:
|
||||||
|
|
||||||
- name: Install Cosign
|
- name: Install Cosign
|
||||||
if: ${{ inputs.sign }}
|
if: ${{ inputs.sign }}
|
||||||
uses: sigstore/cosign-installer@59acb6260d9c0ba8f4a2f9d9b48431a222b68e20 # v3.5.0
|
uses: sigstore/cosign-installer@d58896d6a1865668819e1d91763c7751a165e159 # v3.9.2
|
||||||
|
|
||||||
- name: Sign the images with GitHub OIDC Token
|
- name: Sign the images with GitHub OIDC Token
|
||||||
if: ${{ inputs.sign }}
|
if: ${{ inputs.sign }}
|
||||||
|
|
|
@ -23,12 +23,12 @@ jobs:
|
||||||
goos: windows
|
goos: windows
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout commit
|
- name: Checkout commit
|
||||||
uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5
|
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
- name: Setup Go
|
- name: Setup Go
|
||||||
uses: actions/setup-go@cdcb36043654635271a94b9a6d1392de5bb323a7 # v5.0.1
|
uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
|
||||||
with:
|
with:
|
||||||
go-version-file: 'go.mod'
|
go-version-file: 'go.mod'
|
||||||
check-latest: true
|
check-latest: true
|
||||||
|
@ -47,14 +47,14 @@ jobs:
|
||||||
tar -czvf falcoctl-${{ matrix.goos }}-${{ matrix.goarch }}.tar.gz falcoctl LICENSE
|
tar -czvf falcoctl-${{ matrix.goos }}-${{ matrix.goarch }}.tar.gz falcoctl LICENSE
|
||||||
|
|
||||||
- name: Upload falcoctl artifacts
|
- name: Upload falcoctl artifacts
|
||||||
uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3
|
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
||||||
with:
|
with:
|
||||||
name: falcoctl-${{ matrix.goos }}-${{ matrix.goarch }}
|
name: falcoctl-${{ matrix.goos }}-${{ matrix.goarch }}
|
||||||
path: ./falcoctl-${{ matrix.goos }}-${{ matrix.goarch }}
|
path: ./falcoctl-${{ matrix.goos }}-${{ matrix.goarch }}
|
||||||
retention-days: 1
|
retention-days: 1
|
||||||
|
|
||||||
- name: Upload falcoctl archives
|
- name: Upload falcoctl archives
|
||||||
uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3
|
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
||||||
with:
|
with:
|
||||||
name: falcoctl-${{ matrix.goos }}-${{ matrix.goarch }}.tar.gz
|
name: falcoctl-${{ matrix.goos }}-${{ matrix.goarch }}.tar.gz
|
||||||
path: ./falcoctl-${{ matrix.goos }}-${{ matrix.goarch }}.tar.gz
|
path: ./falcoctl-${{ matrix.goos }}-${{ matrix.goarch }}.tar.gz
|
||||||
|
@ -96,7 +96,7 @@ jobs:
|
||||||
actions: read # for detecting the Github Actions environment.
|
actions: read # for detecting the Github Actions environment.
|
||||||
id-token: write # for creating OIDC tokens for signing.
|
id-token: write # for creating OIDC tokens for signing.
|
||||||
packages: write # for uploading attestations.
|
packages: write # for uploading attestations.
|
||||||
uses: slsa-framework/slsa-github-generator/.github/workflows/generator_container_slsa3.yml@v2.0.0
|
uses: slsa-framework/slsa-github-generator/.github/workflows/generator_container_slsa3.yml@v2.1.0
|
||||||
with:
|
with:
|
||||||
image: docker.io/falcosecurity/falcoctl
|
image: docker.io/falcosecurity/falcoctl
|
||||||
# The image digest is used to prevent TOCTOU issues.
|
# The image digest is used to prevent TOCTOU issues.
|
||||||
|
@ -115,7 +115,7 @@ jobs:
|
||||||
id-token: write
|
id-token: write
|
||||||
steps:
|
steps:
|
||||||
- name: Configure AWS credentials
|
- name: Configure AWS credentials
|
||||||
uses: aws-actions/configure-aws-credentials@e3dd6a429d7300a6a4c196c26e071d42e0343502 # v4.0.2
|
uses: aws-actions/configure-aws-credentials@b47578312673ae6fa5b5096b330d9fbac3d116df # v4.2.1
|
||||||
with:
|
with:
|
||||||
role-to-assume: arn:aws:iam::292999226676:role/github_actions-falcoctl-ecr
|
role-to-assume: arn:aws:iam::292999226676:role/github_actions-falcoctl-ecr
|
||||||
aws-region: us-east-1
|
aws-region: us-east-1
|
||||||
|
@ -138,7 +138,7 @@ jobs:
|
||||||
actions: read # for detecting the Github Actions environment.
|
actions: read # for detecting the Github Actions environment.
|
||||||
id-token: write # for creating OIDC tokens for signing.
|
id-token: write # for creating OIDC tokens for signing.
|
||||||
packages: write # for uploading attestations.
|
packages: write # for uploading attestations.
|
||||||
uses: slsa-framework/slsa-github-generator/.github/workflows/generator_container_slsa3.yml@v2.0.0
|
uses: slsa-framework/slsa-github-generator/.github/workflows/generator_container_slsa3.yml@v2.1.0
|
||||||
with:
|
with:
|
||||||
image: public.ecr.aws/falcosecurity/falcoctl
|
image: public.ecr.aws/falcosecurity/falcoctl
|
||||||
# The image digest is used to prevent TOCTOU issues.
|
# The image digest is used to prevent TOCTOU issues.
|
||||||
|
@ -154,10 +154,10 @@ jobs:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout commit
|
- name: Checkout commit
|
||||||
uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5
|
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||||
|
|
||||||
- name: Setup Go
|
- name: Setup Go
|
||||||
uses: actions/setup-go@cdcb36043654635271a94b9a6d1392de5bb323a7 # v5.0.1
|
uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
|
||||||
with:
|
with:
|
||||||
go-version-file: 'go.mod'
|
go-version-file: 'go.mod'
|
||||||
check-latest: true
|
check-latest: true
|
||||||
|
|
|
@ -8,24 +8,25 @@ jobs:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5
|
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||||
with:
|
with:
|
||||||
ref: ${{ github.event.pull_request.head.sha }}
|
ref: ${{ github.event.pull_request.head.sha }}
|
||||||
repository: ${{github.event.pull_request.head.repo.full_name}}
|
repository: ${{github.event.pull_request.head.repo.full_name}}
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
|
|
||||||
- name: Setup Go
|
- name: Setup Go
|
||||||
uses: actions/setup-go@cdcb36043654635271a94b9a6d1392de5bb323a7 # v5.0.1
|
uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
|
||||||
with:
|
with:
|
||||||
go-version-file: 'go.mod'
|
go-version: "^1.24.3"
|
||||||
|
go-version-file: "go.mod"
|
||||||
check-latest: true
|
check-latest: true
|
||||||
cache: 'false'
|
cache: "false"
|
||||||
|
|
||||||
- name: golangci-lint
|
- name: golangci-lint
|
||||||
uses: golangci/golangci-lint-action@a4f60bb28d35aeee14e6880718e0c85ff1882e64 # v6.0.1
|
uses: golangci/golangci-lint-action@55c2c1448f86e01eaae002a5a3a9624417608d84 # v6.5.2
|
||||||
with:
|
with:
|
||||||
only-new-issues: true
|
only-new-issues: true
|
||||||
version: v1.55
|
version: v1.64.7
|
||||||
args: --timeout=900s
|
args: --timeout=900s
|
||||||
|
|
||||||
gomodtidy:
|
gomodtidy:
|
||||||
|
@ -34,16 +35,16 @@ jobs:
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5
|
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||||
with:
|
with:
|
||||||
ref: "${{ github.event.pull_request.head.sha }}"
|
ref: "${{ github.event.pull_request.head.sha }}"
|
||||||
repository: ${{github.event.pull_request.head.repo.full_name}}
|
repository: ${{github.event.pull_request.head.repo.full_name}}
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
|
|
||||||
- name: Setup Go
|
- name: Setup Go
|
||||||
uses: actions/setup-go@cdcb36043654635271a94b9a6d1392de5bb323a7 # v5.0.1
|
uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
|
||||||
with:
|
with:
|
||||||
go-version-file: 'go.mod'
|
go-version-file: "go.mod"
|
||||||
check-latest: true
|
check-latest: true
|
||||||
|
|
||||||
- name: Execute go mod tidy and check the outcome
|
- name: Execute go mod tidy and check the outcome
|
||||||
|
|
|
@ -14,7 +14,7 @@ jobs:
|
||||||
hashes: ${{ steps.hash.outputs.hashes }}
|
hashes: ${{ steps.hash.outputs.hashes }}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5
|
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
|
@ -22,14 +22,14 @@ jobs:
|
||||||
run: git fetch --force --tags
|
run: git fetch --force --tags
|
||||||
|
|
||||||
- name: Setup Go
|
- name: Setup Go
|
||||||
uses: actions/setup-go@cdcb36043654635271a94b9a6d1392de5bb323a7 # v5.0.1
|
uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
|
||||||
with:
|
with:
|
||||||
go-version-file: 'go.mod'
|
go-version-file: 'go.mod'
|
||||||
check-latest: true
|
check-latest: true
|
||||||
|
|
||||||
- name: Run GoReleaser
|
- name: Run GoReleaser
|
||||||
id: run-goreleaser
|
id: run-goreleaser
|
||||||
uses: goreleaser/goreleaser-action@5742e2a039330cbb23ebf35f046f814d4c6ff811 # v5.1.0
|
uses: goreleaser/goreleaser-action@9c156ee8a17a598857849441385a2041ef570552 # v6.3.0
|
||||||
with:
|
with:
|
||||||
distribution: goreleaser
|
distribution: goreleaser
|
||||||
version: latest
|
version: latest
|
||||||
|
@ -53,7 +53,7 @@ jobs:
|
||||||
actions: read # To read the workflow path.
|
actions: read # To read the workflow path.
|
||||||
id-token: write # To sign the provenance.
|
id-token: write # To sign the provenance.
|
||||||
contents: write # To add assets to a release.
|
contents: write # To add assets to a release.
|
||||||
uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v2.0.0
|
uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v2.1.0
|
||||||
with:
|
with:
|
||||||
base64-subjects: "${{ needs.goreleaser.outputs.hashes }}"
|
base64-subjects: "${{ needs.goreleaser.outputs.hashes }}"
|
||||||
upload-assets: true # upload to a new release
|
upload-assets: true # upload to a new release
|
||||||
|
@ -64,7 +64,7 @@ jobs:
|
||||||
permissions: read-all
|
permissions: read-all
|
||||||
steps:
|
steps:
|
||||||
- name: Install the verifier
|
- name: Install the verifier
|
||||||
uses: slsa-framework/slsa-verifier/actions/installer@v2.5.1
|
uses: slsa-framework/slsa-verifier/actions/installer@v2.7.1
|
||||||
|
|
||||||
- name: Download assets
|
- name: Download assets
|
||||||
env:
|
env:
|
||||||
|
@ -126,7 +126,7 @@ jobs:
|
||||||
actions: read # for detecting the Github Actions environment.
|
actions: read # for detecting the Github Actions environment.
|
||||||
id-token: write # for creating OIDC tokens for signing.
|
id-token: write # for creating OIDC tokens for signing.
|
||||||
packages: write # for uploading attestations.
|
packages: write # for uploading attestations.
|
||||||
uses: slsa-framework/slsa-github-generator/.github/workflows/generator_container_slsa3.yml@v2.0.0
|
uses: slsa-framework/slsa-github-generator/.github/workflows/generator_container_slsa3.yml@v2.1.0
|
||||||
with:
|
with:
|
||||||
image: docker.io/falcosecurity/falcoctl
|
image: docker.io/falcosecurity/falcoctl
|
||||||
# The image digest is used to prevent TOCTOU issues.
|
# The image digest is used to prevent TOCTOU issues.
|
||||||
|
@ -144,7 +144,7 @@ jobs:
|
||||||
id-token: write
|
id-token: write
|
||||||
steps:
|
steps:
|
||||||
- name: Configure AWS credentials
|
- name: Configure AWS credentials
|
||||||
uses: aws-actions/configure-aws-credentials@e3dd6a429d7300a6a4c196c26e071d42e0343502 # v4.0.2
|
uses: aws-actions/configure-aws-credentials@b47578312673ae6fa5b5096b330d9fbac3d116df # v4.2.1
|
||||||
with:
|
with:
|
||||||
role-to-assume: arn:aws:iam::292999226676:role/github_actions-falcoctl-ecr
|
role-to-assume: arn:aws:iam::292999226676:role/github_actions-falcoctl-ecr
|
||||||
aws-region: us-east-1
|
aws-region: us-east-1
|
||||||
|
@ -166,7 +166,7 @@ jobs:
|
||||||
actions: read # for detecting the Github Actions environment.
|
actions: read # for detecting the Github Actions environment.
|
||||||
id-token: write # for creating OIDC tokens for signing.
|
id-token: write # for creating OIDC tokens for signing.
|
||||||
packages: write # for uploading attestations.
|
packages: write # for uploading attestations.
|
||||||
uses: slsa-framework/slsa-github-generator/.github/workflows/generator_container_slsa3.yml@v2.0.0
|
uses: slsa-framework/slsa-github-generator/.github/workflows/generator_container_slsa3.yml@v2.1.0
|
||||||
with:
|
with:
|
||||||
image: public.ecr.aws/falcosecurity/falcoctl
|
image: public.ecr.aws/falcosecurity/falcoctl
|
||||||
# The image digest is used to prevent TOCTOU issues.
|
# The image digest is used to prevent TOCTOU issues.
|
||||||
|
|
|
@ -44,17 +44,11 @@ linters-settings:
|
||||||
- opinionated
|
- opinionated
|
||||||
- performance
|
- performance
|
||||||
- style
|
- style
|
||||||
disabled-checks:
|
|
||||||
# Conflicts with govet check-shadowing
|
|
||||||
- sloppyReassign
|
|
||||||
goimports:
|
goimports:
|
||||||
local-prefixes: github.com/falcosecurity/falcoctl
|
local-prefixes: github.com/falcosecurity/falcoctl
|
||||||
govet:
|
|
||||||
check-shadowing: true
|
|
||||||
misspell:
|
misspell:
|
||||||
locale: US
|
locale: US
|
||||||
nolintlint:
|
nolintlint:
|
||||||
allow-leading-space: true # don't require machine-readable nolint directives (i.e. with no leading space)
|
|
||||||
allow-unused: false # report any unused nolint directives
|
allow-unused: false # report any unused nolint directives
|
||||||
require-explanation: true # require an explanation for nolint directives
|
require-explanation: true # require an explanation for nolint directives
|
||||||
require-specific: true # require nolint directives to be specific about which linter is being skipped
|
require-specific: true # require nolint directives to be specific about which linter is being skipped
|
||||||
|
@ -71,7 +65,7 @@ linters:
|
||||||
- errcheck
|
- errcheck
|
||||||
- errorlint
|
- errorlint
|
||||||
- exhaustive
|
- exhaustive
|
||||||
- exportloopref
|
- copyloopvar
|
||||||
# - funlen
|
# - funlen
|
||||||
# - gochecknoglobals
|
# - gochecknoglobals
|
||||||
# - gochecknoinits
|
# - gochecknoinits
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
version: 2
|
||||||
|
|
||||||
project_name: falcoctl
|
project_name: falcoctl
|
||||||
before:
|
before:
|
||||||
hooks:
|
hooks:
|
||||||
|
@ -45,3 +47,6 @@ release:
|
||||||
|
|
||||||
changelog:
|
changelog:
|
||||||
use: github-native
|
use: github-native
|
||||||
|
|
||||||
|
git:
|
||||||
|
tag_sort: -version:creatordate
|
||||||
|
|
3
Makefile
3
Makefile
|
@ -18,6 +18,7 @@ PROJECT?=github.com/falcosecurity/falcoctl
|
||||||
# todo(leogr): re-enable race when CLI tests can run with race enabled
|
# todo(leogr): re-enable race when CLI tests can run with race enabled
|
||||||
TEST_FLAGS ?= -v -cover# -race
|
TEST_FLAGS ?= -v -cover# -race
|
||||||
|
|
||||||
|
.PHONY: falcoctl
|
||||||
falcoctl:
|
falcoctl:
|
||||||
$(GO) build -ldflags \
|
$(GO) build -ldflags \
|
||||||
"-X '${PROJECT}/cmd/version.semVersion=${RELEASE}' \
|
"-X '${PROJECT}/cmd/version.semVersion=${RELEASE}' \
|
||||||
|
@ -62,7 +63,7 @@ fmt: gci addlicense
|
||||||
.PHONY: golangci-lint
|
.PHONY: golangci-lint
|
||||||
golangci-lint:
|
golangci-lint:
|
||||||
ifeq (, $(shell which golangci-lint))
|
ifeq (, $(shell which golangci-lint))
|
||||||
@go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.52.2
|
@go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.62.2
|
||||||
GOLANGCILINT=$(GOBIN)/golangci-lint
|
GOLANGCILINT=$(GOBIN)/golangci-lint
|
||||||
else
|
else
|
||||||
GOLANGCILINT=$(shell which golangci-lint)
|
GOLANGCILINT=$(shell which golangci-lint)
|
||||||
|
|
1
OWNERS
1
OWNERS
|
@ -5,7 +5,6 @@ approvers:
|
||||||
- fededp
|
- fededp
|
||||||
- cpanato
|
- cpanato
|
||||||
- alacuku
|
- alacuku
|
||||||
reviewers:
|
|
||||||
- loresuso
|
- loresuso
|
||||||
emeritus_approvers:
|
emeritus_approvers:
|
||||||
- kris-nova
|
- kris-nova
|
||||||
|
|
|
@ -217,6 +217,7 @@ Indices for *falcoctl* can be retrieved from various storage backends. The suppo
|
||||||
| https | https:// | Convenience alias for the HTTP backend. |
|
| https | https:// | Convenience alias for the HTTP backend. |
|
||||||
| gcs | gs:// | For indices stored as Google Cloud Storage objects. Supports application default credentials. |
|
| gcs | gs:// | For indices stored as Google Cloud Storage objects. Supports application default credentials. |
|
||||||
| file | file:// | For indices stored on the local file system. |
|
| file | file:// | For indices stored on the local file system. |
|
||||||
|
| s3 | s3:// | For indices stored as AWS S3 objects. Supports default credentials, IRSA. |
|
||||||
|
|
||||||
|
|
||||||
#### falcoctl index add
|
#### falcoctl index add
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
FROM golang:1.22 as builder
|
FROM cgr.dev/chainguard/go AS builder
|
||||||
WORKDIR /tmp/builder
|
WORKDIR /tmp/builder
|
||||||
|
|
||||||
ARG RELEASE
|
ARG RELEASE
|
||||||
|
@ -29,14 +29,8 @@ RUN CGO_ENABLED=0 \
|
||||||
|
|
||||||
RUN echo ${RELEASE}
|
RUN echo ${RELEASE}
|
||||||
|
|
||||||
FROM alpine:3.18.4
|
FROM cgr.dev/chainguard/static:latest
|
||||||
|
|
||||||
RUN apk update --no-cache && \
|
COPY --from=builder /tmp/builder/falcoctl /usr/bin/falcoctl
|
||||||
apk add --upgrade --no-cache libssl3 libcrypto3
|
|
||||||
RUN rm -rf /var/cache/apk/*
|
|
||||||
|
|
||||||
ARG BIN_NAME="falcoctl"
|
ENTRYPOINT [ "/usr/bin/falcoctl" ]
|
||||||
COPY --from=builder /tmp/builder/${BIN_NAME} /usr/bin/${BIN_NAME}
|
|
||||||
RUN ln -s /usr/bin/${BIN_NAME} /usr/bin/falcoctl-bin
|
|
||||||
|
|
||||||
ENTRYPOINT [ "/usr/bin/falcoctl-bin" ]
|
|
||||||
|
|
|
@ -0,0 +1,326 @@
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
// Copyright (C) 2024 The Falco Authors
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
|
||||||
|
package driverconfig
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/falcosecurity/driverkit/pkg/kernelrelease"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
"gopkg.in/yaml.v3"
|
||||||
|
v1 "k8s.io/api/core/v1"
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
"k8s.io/client-go/kubernetes/fake"
|
||||||
|
|
||||||
|
drivertype "github.com/falcosecurity/falcoctl/pkg/driver/type"
|
||||||
|
"github.com/falcosecurity/falcoctl/pkg/options"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
falcoName = "falco"
|
||||||
|
)
|
||||||
|
|
||||||
|
func newOptions() *driverConfigOptions {
|
||||||
|
common := options.NewOptions()
|
||||||
|
common.Initialize()
|
||||||
|
|
||||||
|
// Parse the driver type.
|
||||||
|
dType, _ := drivertype.Parse("modern_ebpf")
|
||||||
|
return &driverConfigOptions{
|
||||||
|
Common: common,
|
||||||
|
Driver: &options.Driver{
|
||||||
|
Type: dType,
|
||||||
|
Name: falcoName,
|
||||||
|
Repos: []string{"https://download.falco.org/driver"},
|
||||||
|
Version: "6.0.0+driver",
|
||||||
|
HostRoot: "/",
|
||||||
|
Distro: nil,
|
||||||
|
Kr: kernelrelease.KernelRelease{},
|
||||||
|
},
|
||||||
|
update: false,
|
||||||
|
namespace: "",
|
||||||
|
kubeconfig: "",
|
||||||
|
configmap: "",
|
||||||
|
configDir: "",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func createFalcoConfigFile(cfg falcoCfg, configDir string) error {
|
||||||
|
engineKind, err := yaml.Marshal(cfg)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("unable to marshal falco config: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write the engine configuration to a specialized config file.
|
||||||
|
if err := os.WriteFile(filepath.Join(configDir, "falco.yaml"), engineKind, 0o600); err != nil {
|
||||||
|
return fmt.Errorf("unable to write falco.yaml file: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func createFalcoConfigMap(cfg falcoCfg, dataKey string) (*v1.ConfigMap, error) {
|
||||||
|
engineKind, err := yaml.Marshal(cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("unable to marshal falco config: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
cm := &v1.ConfigMap{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: falcoName,
|
||||||
|
Namespace: falcoName,
|
||||||
|
},
|
||||||
|
Data: map[string]string{
|
||||||
|
dataKey: string(engineKind),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
return cm, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDriverConfigOptions_Commit_Host(t *testing.T) {
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
args func(t *testing.T) *driverConfigOptions
|
||||||
|
expected func(t *testing.T, opt *driverConfigOptions, err error)
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"no falco config file",
|
||||||
|
func(t *testing.T) *driverConfigOptions {
|
||||||
|
opt := newOptions()
|
||||||
|
opt.configDir = "no-file-at-all"
|
||||||
|
opt.update = true
|
||||||
|
return opt
|
||||||
|
},
|
||||||
|
func(t *testing.T, opt *driverConfigOptions, err error) {
|
||||||
|
require.Error(t, err, "should error since falco configuration file does not exist")
|
||||||
|
require.ErrorContains(t, err, "open no-file-at-all/falco.yaml: no such file or directory")
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"update-falco-config",
|
||||||
|
func(t *testing.T) *driverConfigOptions {
|
||||||
|
opt := newOptions()
|
||||||
|
dir, err := os.MkdirTemp("", "falcoctl-driver-config-test")
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
// Write falco configuration file.
|
||||||
|
cfg := falcoCfg{engineCfg{Kind: "modern_ebpf"}}
|
||||||
|
err = createFalcoConfigFile(cfg, dir)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
opt.configDir = dir
|
||||||
|
return opt
|
||||||
|
},
|
||||||
|
func(t *testing.T, opt *driverConfigOptions, err error) {
|
||||||
|
require.NoError(t, err, "should not error")
|
||||||
|
|
||||||
|
// Config file.
|
||||||
|
specCfgFile := filepath.Join(opt.configDir, "config.d", falcoDriverConfigFile)
|
||||||
|
|
||||||
|
// Check that config file has been created.
|
||||||
|
_, err = os.Stat(specCfgFile)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
content, err := os.ReadFile(specCfgFile)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
cfg := falcoCfg{}
|
||||||
|
err = yaml.Unmarshal(content, &cfg)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, opt.Type.String(), cfg.Engine.Kind)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"falco-not-in-driver-mode",
|
||||||
|
func(t *testing.T) *driverConfigOptions {
|
||||||
|
opt := newOptions()
|
||||||
|
dir, err := os.MkdirTemp("", "falcoctl-driver-config-test")
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
// Write falco configuration file.
|
||||||
|
cfg := falcoCfg{engineCfg{Kind: "nodriver"}}
|
||||||
|
err = createFalcoConfigFile(cfg, dir)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
opt.configDir = dir
|
||||||
|
return opt
|
||||||
|
},
|
||||||
|
func(t *testing.T, opt *driverConfigOptions, err error) {
|
||||||
|
require.NoError(t, err, "should not error")
|
||||||
|
|
||||||
|
// Config file.
|
||||||
|
specCfgFile := filepath.Join(opt.configDir, "config.d", falcoDriverConfigFile)
|
||||||
|
|
||||||
|
// Check that config file has been created.
|
||||||
|
_, err = os.Stat(specCfgFile)
|
||||||
|
require.True(t, os.IsNotExist(err))
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, testCase := range testCases {
|
||||||
|
testCase := testCase
|
||||||
|
|
||||||
|
t.Run(testCase.name, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
opt := testCase.args(t)
|
||||||
|
err := opt.Commit(context.Background(), nil, opt.Type)
|
||||||
|
testCase.expected(t, opt, err)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDriverConfigOptions_Commit_K8S(t *testing.T) {
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
args func(t *testing.T) (*driverConfigOptions, *v1.ConfigMap)
|
||||||
|
expected func(t *testing.T, opt *driverConfigOptions, err error)
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"no falco configmap, wrong namespace",
|
||||||
|
func(t *testing.T) (*driverConfigOptions, *v1.ConfigMap) {
|
||||||
|
opt := newOptions()
|
||||||
|
opt.namespace = "wrong-namespace"
|
||||||
|
opt.configmap = falcoName
|
||||||
|
|
||||||
|
cm, err := createFalcoConfigMap(falcoCfg{engineCfg{Kind: "modern_ebpf"}}, "falco.yaml")
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
return opt, cm
|
||||||
|
},
|
||||||
|
func(t *testing.T, opt *driverConfigOptions, err error) {
|
||||||
|
require.Error(t, err, "should error since falco configmap does not exist")
|
||||||
|
require.ErrorContains(t, err, "unable to get configmap falco in namespace wrong-namespace")
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"no falco configmap, wrong name",
|
||||||
|
func(t *testing.T) (*driverConfigOptions, *v1.ConfigMap) {
|
||||||
|
opt := newOptions()
|
||||||
|
opt.namespace = falcoName
|
||||||
|
opt.configmap = "wrong-name"
|
||||||
|
|
||||||
|
cm, err := createFalcoConfigMap(falcoCfg{engineCfg{Kind: "modern_ebpf"}}, "falco.yaml")
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
return opt, cm
|
||||||
|
},
|
||||||
|
func(t *testing.T, opt *driverConfigOptions, err error) {
|
||||||
|
require.Error(t, err, "should error since falco configmap does not exist")
|
||||||
|
require.ErrorContains(t, err, "unable to get configmap wrong-name in namespace falco")
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"no falco config, wrong data key",
|
||||||
|
func(t *testing.T) (*driverConfigOptions, *v1.ConfigMap) {
|
||||||
|
opt := newOptions()
|
||||||
|
opt.namespace = falcoName
|
||||||
|
opt.configmap = falcoName
|
||||||
|
|
||||||
|
cm, err := createFalcoConfigMap(falcoCfg{engineCfg{Kind: "modern_ebpf"}}, "wrong-data-key")
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
return opt, cm
|
||||||
|
},
|
||||||
|
func(t *testing.T, opt *driverConfigOptions, err error) {
|
||||||
|
require.Error(t, err, "should error since falco configmap does not exist")
|
||||||
|
require.ErrorContains(t, err, "configMap falco does not contain key \"falco.yaml\"")
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"update-falco-config",
|
||||||
|
func(t *testing.T) (*driverConfigOptions, *v1.ConfigMap) {
|
||||||
|
opt := newOptions()
|
||||||
|
opt.namespace = falcoName
|
||||||
|
opt.configmap = falcoName
|
||||||
|
|
||||||
|
dir, err := os.MkdirTemp("", "falcoctl-driver-config-test")
|
||||||
|
require.NoError(t, err)
|
||||||
|
opt.configDir = dir
|
||||||
|
|
||||||
|
cm, err := createFalcoConfigMap(falcoCfg{engineCfg{Kind: "modern_ebpf"}}, "falco.yaml")
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
return opt, cm
|
||||||
|
},
|
||||||
|
|
||||||
|
func(t *testing.T, opt *driverConfigOptions, err error) {
|
||||||
|
require.NoError(t, err, "should not error")
|
||||||
|
|
||||||
|
// Config file.
|
||||||
|
specCfgFile := filepath.Join(opt.configDir, "config.d", falcoDriverConfigFile)
|
||||||
|
|
||||||
|
// Check that config file has been created.
|
||||||
|
_, err = os.Stat(specCfgFile)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
content, err := os.ReadFile(specCfgFile)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
cfg := falcoCfg{}
|
||||||
|
err = yaml.Unmarshal(content, &cfg)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, opt.Type.String(), cfg.Engine.Kind)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"falco-not-in-driver-mode",
|
||||||
|
func(t *testing.T) (*driverConfigOptions, *v1.ConfigMap) {
|
||||||
|
opt := newOptions()
|
||||||
|
opt.namespace = falcoName
|
||||||
|
opt.configmap = falcoName
|
||||||
|
|
||||||
|
dir, err := os.MkdirTemp("", "falcoctl-driver-config-test")
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
cm, err := createFalcoConfigMap(falcoCfg{engineCfg{Kind: "nodriver"}}, "falco.yaml")
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
opt.configDir = dir
|
||||||
|
return opt, cm
|
||||||
|
},
|
||||||
|
func(t *testing.T, opt *driverConfigOptions, err error) {
|
||||||
|
require.NoError(t, err, "should not error")
|
||||||
|
|
||||||
|
// Config file.
|
||||||
|
specCfgFile := filepath.Join(opt.configDir, "config.d", falcoDriverConfigFile)
|
||||||
|
|
||||||
|
// Check that config file has been created.
|
||||||
|
_, err = os.Stat(specCfgFile)
|
||||||
|
require.True(t, os.IsNotExist(err))
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, testCase := range testCases {
|
||||||
|
testCase := testCase
|
||||||
|
|
||||||
|
t.Run(testCase.name, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
opt, cm := testCase.args(t)
|
||||||
|
// Create fake client.
|
||||||
|
fakeClient := fake.NewSimpleClientset(cm)
|
||||||
|
err := opt.Commit(context.Background(), fakeClient, opt.Type)
|
||||||
|
testCase.expected(t, opt, err)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
// Copyright (C) 2023 The Falco Authors
|
// Copyright (C) 2024 The Falco Authors
|
||||||
//
|
//
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with the License.
|
// you may not use this file except in compliance with the License.
|
||||||
|
@ -16,7 +16,6 @@
|
||||||
package driverconfig
|
package driverconfig
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
@ -30,10 +29,8 @@ import (
|
||||||
"k8s.io/client-go/kubernetes"
|
"k8s.io/client-go/kubernetes"
|
||||||
"k8s.io/client-go/rest"
|
"k8s.io/client-go/rest"
|
||||||
"k8s.io/client-go/tools/clientcmd"
|
"k8s.io/client-go/tools/clientcmd"
|
||||||
"k8s.io/client-go/util/retry"
|
|
||||||
|
|
||||||
"github.com/falcosecurity/falcoctl/internal/config"
|
"github.com/falcosecurity/falcoctl/internal/config"
|
||||||
"github.com/falcosecurity/falcoctl/internal/utils"
|
|
||||||
drivertype "github.com/falcosecurity/falcoctl/pkg/driver/type"
|
drivertype "github.com/falcosecurity/falcoctl/pkg/driver/type"
|
||||||
"github.com/falcosecurity/falcoctl/pkg/options"
|
"github.com/falcosecurity/falcoctl/pkg/options"
|
||||||
)
|
)
|
||||||
|
@ -44,14 +41,18 @@ It will also update local Falco configuration or k8s configmap depending on the
|
||||||
Only supports deployments of Falco that use a driver engine, ie: one between kmod, ebpf and modern-ebpf.
|
Only supports deployments of Falco that use a driver engine, ie: one between kmod, ebpf and modern-ebpf.
|
||||||
If engine.kind key is set to a non-driver driven engine, Falco configuration won't be touched.
|
If engine.kind key is set to a non-driver driven engine, Falco configuration won't be touched.
|
||||||
`
|
`
|
||||||
|
falcoConfigFile = "falco.yaml"
|
||||||
|
falcoDriverConfigFile = "engine-kind-falcoctl.yaml"
|
||||||
)
|
)
|
||||||
|
|
||||||
type driverConfigOptions struct {
|
type driverConfigOptions struct {
|
||||||
*options.Common
|
*options.Common
|
||||||
*options.Driver
|
*options.Driver
|
||||||
Update bool
|
update bool
|
||||||
Namespace string
|
namespace string
|
||||||
KubeConfig string
|
kubeconfig string
|
||||||
|
configmap string
|
||||||
|
configDir string
|
||||||
}
|
}
|
||||||
|
|
||||||
type engineCfg struct {
|
type engineCfg struct {
|
||||||
|
@ -74,29 +75,20 @@ func NewDriverConfigCmd(ctx context.Context, opt *options.Common, driver *option
|
||||||
Short: "Configure a driver",
|
Short: "Configure a driver",
|
||||||
Long: longConfig,
|
Long: longConfig,
|
||||||
PreRunE: func(cmd *cobra.Command, args []string) error {
|
PreRunE: func(cmd *cobra.Command, args []string) error {
|
||||||
// Override "namespace" flag with viper config if not set by user.
|
viper.AutomaticEnv()
|
||||||
f := cmd.Flags().Lookup("namespace")
|
|
||||||
if f == nil {
|
_ = viper.BindPFlag("driver.config.configmap", cmd.Flags().Lookup("configmap"))
|
||||||
// should never happen
|
_ = viper.BindPFlag("driver.config.namespace", cmd.Flags().Lookup("namespace"))
|
||||||
return fmt.Errorf("unable to retrieve flag namespace")
|
_ = viper.BindPFlag("driver.config.update_falco", cmd.Flags().Lookup("update-falco"))
|
||||||
} else if !f.Changed && viper.IsSet(config.DriverNamespaceKey) {
|
_ = viper.BindPFlag("driver.config.kubeconfig", cmd.Flags().Lookup("kubeconfig"))
|
||||||
val := viper.Get(config.DriverNamespaceKey)
|
_ = viper.BindPFlag("driver.config.configdir", cmd.Flags().Lookup("falco-config-dir"))
|
||||||
if err := cmd.Flags().Set(f.Name, fmt.Sprintf("%v", val)); err != nil {
|
|
||||||
return fmt.Errorf("unable to overwrite \"namespace\" flag: %w", err)
|
o.configmap = viper.GetString("driver.config.configmap")
|
||||||
}
|
o.namespace = viper.GetString("driver.config.namespace")
|
||||||
}
|
o.kubeconfig = viper.GetString("driver.config.kubeconfig")
|
||||||
|
o.update = viper.GetBool("driver.config.update_falco")
|
||||||
|
o.configDir = viper.GetString("driver.config.configdir")
|
||||||
|
|
||||||
// Override "update-falco" flag with viper config if not set by user.
|
|
||||||
f = cmd.Flags().Lookup("update-falco")
|
|
||||||
if f == nil {
|
|
||||||
// should never happen
|
|
||||||
return fmt.Errorf("unable to retrieve flag update-falco")
|
|
||||||
} else if !f.Changed && viper.IsSet(config.DriverUpdateFalcoKey) {
|
|
||||||
val := viper.Get(config.DriverUpdateFalcoKey)
|
|
||||||
if err := cmd.Flags().Set(f.Name, fmt.Sprintf("%v", val)); err != nil {
|
|
||||||
return fmt.Errorf("unable to overwrite \"update-falco\" flag: %w", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
|
@ -104,9 +96,12 @@ func NewDriverConfigCmd(ctx context.Context, opt *options.Common, driver *option
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd.Flags().BoolVar(&o.Update, "update-falco", true, "Whether to update Falco config/configmap.")
|
cmd.Flags().BoolVar(&o.update, "update-falco", true, "Whether to overwrite Falco configuration")
|
||||||
cmd.Flags().StringVar(&o.Namespace, "namespace", "", "Kubernetes namespace.")
|
cmd.Flags().StringVar(&o.namespace, "namespace", "", "Kubernetes namespace.")
|
||||||
cmd.Flags().StringVar(&o.KubeConfig, "kubeconfig", "", "Kubernetes config.")
|
cmd.Flags().StringVar(&o.kubeconfig, "kubeconfig", "", "Kubernetes config.")
|
||||||
|
cmd.Flags().StringVar(&o.configmap, "configmap", "", "Falco configmap name.")
|
||||||
|
cmd.Flags().StringVar(&o.configDir, "falco-config-dir", "/etc/falco", "Falco configuration directory.")
|
||||||
|
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -119,8 +114,18 @@ func (o *driverConfigOptions) RunDriverConfig(ctx context.Context) error {
|
||||||
"host-root", o.Driver.HostRoot,
|
"host-root", o.Driver.HostRoot,
|
||||||
"repos", strings.Join(o.Driver.Repos, ",")))
|
"repos", strings.Join(o.Driver.Repos, ",")))
|
||||||
|
|
||||||
if o.Update {
|
if o.update {
|
||||||
if err := o.commit(ctx, o.Driver.Type); err != nil {
|
var cl kubernetes.Interface
|
||||||
|
var err error
|
||||||
|
|
||||||
|
if o.namespace != "" {
|
||||||
|
// Create a new clientset.
|
||||||
|
if cl, err = setupClient(o.kubeconfig); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := o.Commit(ctx, cl, o.Driver.Type); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -128,149 +133,130 @@ func (o *driverConfigOptions) RunDriverConfig(ctx context.Context) error {
|
||||||
return config.StoreDriver(o.Driver.ToDriverConfig(), o.ConfigFile)
|
return config.StoreDriver(o.Driver.ToDriverConfig(), o.ConfigFile)
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkFalcoRunsWithDrivers(engineKind string) error {
|
func checkFalcoRunsWithDrivers(engineKind string) bool {
|
||||||
// Modify the data in the ConfigMap/Falco config file ONLY if engine.kind is set to a known driver type.
|
// Modify the data in the ConfigMap/Falco config file ONLY if engine.kind is set to a known driver type.
|
||||||
// This ensures that we modify the config only for Falcos running with drivers, and not plugins/gvisor.
|
// This ensures that we modify the config only for Falcos running with drivers, and not plugins/gvisor.
|
||||||
// Scenario: user has multiple Falco pods deployed in its cluster, one running with driver,
|
// Scenario: user has multiple Falco pods deployed in its cluster, one running with driver,
|
||||||
// other running with plugins. We must only touch the one running with driver.
|
// other running with plugins. We must only touch the one running with driver.
|
||||||
if _, err := drivertype.Parse(engineKind); err != nil {
|
if _, err := drivertype.Parse(engineKind); err != nil {
|
||||||
return fmt.Errorf("engine.kind is not driver driven: %s", engineKind)
|
return false
|
||||||
}
|
}
|
||||||
return nil
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *driverConfigOptions) replaceDriverTypeInFalcoConfig(driverType drivertype.DriverType) error {
|
func (o *driverConfigOptions) IsRunningInDriverModeHost() (bool, error) {
|
||||||
falcoCfgFile := filepath.Clean(filepath.Join(string(os.PathSeparator), "etc", "falco", "falco.yaml"))
|
o.Printer.Logger.Debug("Checking if Falco is running in driver mode on host system")
|
||||||
|
|
||||||
|
falcoCfgFile := filepath.Join(o.configDir, falcoConfigFile)
|
||||||
yamlFile, err := os.ReadFile(filepath.Clean(falcoCfgFile))
|
yamlFile, err := os.ReadFile(filepath.Clean(falcoCfgFile))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return false, err
|
||||||
}
|
}
|
||||||
cfg := falcoCfg{}
|
cfg := falcoCfg{}
|
||||||
if err = yaml.Unmarshal(yamlFile, &cfg); err != nil {
|
if err = yaml.Unmarshal(yamlFile, &cfg); err != nil {
|
||||||
return err
|
return false, fmt.Errorf("unable to unmarshal falco.yaml to falcoCfg struct: %w", err)
|
||||||
}
|
}
|
||||||
if err = checkFalcoRunsWithDrivers(cfg.Engine.Kind); err != nil {
|
|
||||||
o.Printer.Logger.Warn("Avoid updating",
|
return checkFalcoRunsWithDrivers(cfg.Engine.Kind), nil
|
||||||
o.Printer.Logger.Args("config", falcoCfgFile, "reason", err))
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
const configKindKey = "kind: "
|
|
||||||
return utils.ReplaceTextInFile(falcoCfgFile, configKindKey+cfg.Engine.Kind, configKindKey+driverType.String(), 1)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *driverConfigOptions) replaceDriverTypeInK8SConfigMap(ctx context.Context, driverType drivertype.DriverType) error {
|
func (o *driverConfigOptions) IsRunningInDriverModeK8S(ctx context.Context, cl kubernetes.Interface) (bool, error) {
|
||||||
var (
|
o.Printer.Logger.Debug("Checking if Falco is running in driver mode in Kubernetes")
|
||||||
err error
|
|
||||||
cfg *rest.Config
|
configMap, err := cl.CoreV1().ConfigMaps(o.namespace).Get(ctx, o.configmap, metav1.GetOptions{})
|
||||||
)
|
|
||||||
|
|
||||||
if o.KubeConfig != "" {
|
|
||||||
cfg, err = clientcmd.BuildConfigFromFlags("", o.KubeConfig)
|
|
||||||
} else {
|
|
||||||
cfg, err = rest.InClusterConfig()
|
|
||||||
}
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return false, fmt.Errorf("unable to get configmap %s in namespace %s: %w", o.configmap, o.namespace, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
cl, err := kubernetes.NewForConfig(cfg)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
configMapList, err := cl.CoreV1().ConfigMaps(o.Namespace).List(ctx, metav1.ListOptions{
|
|
||||||
LabelSelector: "app.kubernetes.io/instance=falco",
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if configMapList.Size() == 0 {
|
|
||||||
return errors.New(`no configmaps matching "app.kubernetes.io/instance=falco" label were found`)
|
|
||||||
}
|
|
||||||
|
|
||||||
updated := false
|
|
||||||
for i := 0; i < len(configMapList.Items); i++ {
|
|
||||||
configMap := &configMapList.Items[i]
|
|
||||||
// Check that this is a Falco config map
|
// Check that this is a Falco config map
|
||||||
falcoYaml, present := configMap.Data["falco.yaml"]
|
falcoYaml, present := configMap.Data["falco.yaml"]
|
||||||
if !present {
|
if !present {
|
||||||
o.Printer.Logger.Debug("Skip non Falco-related config map",
|
o.Printer.Logger.Debug("Skip non Falco-related config map",
|
||||||
o.Printer.Logger.Args("configMap", configMap.Name))
|
o.Printer.Logger.Args("configMap", configMap.Name))
|
||||||
continue
|
return false, fmt.Errorf("configMap %s does not contain key \"falco.yaml\"", o.configmap)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check that Falco is configured to run with a driver
|
// Check that Falco is configured to run with a driver
|
||||||
var falcoConfig falcoCfg
|
var falcoConfig falcoCfg
|
||||||
err = yaml.Unmarshal([]byte(falcoYaml), &falcoConfig)
|
err = yaml.Unmarshal([]byte(falcoYaml), &falcoConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
o.Printer.Logger.Warn("Failed to unmarshal falco.yaml to falcoCfg struct",
|
return false, fmt.Errorf("unable to unmarshal falco.yaml to falcoCfg struct: %w", err)
|
||||||
o.Printer.Logger.Args("configMap", configMap.Name, "err", err))
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if err = checkFalcoRunsWithDrivers(falcoConfig.Engine.Kind); err != nil {
|
|
||||||
o.Printer.Logger.Warn("Avoid updating",
|
|
||||||
o.Printer.Logger.Args("configMap", configMap.Name, "reason", err))
|
|
||||||
continue
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the configMap.
|
return checkFalcoRunsWithDrivers(falcoConfig.Engine.Kind), nil
|
||||||
// Multiple steps:
|
}
|
||||||
// * unmarshal the `falco.yaml` as map[string]interface
|
|
||||||
// * update `engine.kind` value
|
// Commit saves the updated driver type to Falco config,
|
||||||
// * save back the marshaled map to the `falco.yaml` configmap
|
// in a specialized configuration file under /etc/falco/config.d.
|
||||||
// * update the configmap
|
func (o *driverConfigOptions) Commit(ctx context.Context, cl kubernetes.Interface, driverType drivertype.DriverType) error {
|
||||||
var falcoCfgData map[string]interface{}
|
// If set to true, then we need to overwrite the driver type.
|
||||||
err = yaml.Unmarshal([]byte(falcoYaml), &falcoCfgData)
|
var overwrite bool
|
||||||
if err != nil {
|
var err error
|
||||||
o.Printer.Logger.Warn("Failed to unmarshal falco.yaml to map[string]interface{}",
|
if cl != nil {
|
||||||
o.Printer.Logger.Args("configMap", configMap.Name, "err", err))
|
if overwrite, err = o.IsRunningInDriverModeK8S(ctx, cl); err != nil {
|
||||||
continue
|
|
||||||
}
|
|
||||||
falcoCfgEngine, ok := falcoCfgData["engine"].(map[string]interface{})
|
|
||||||
if !ok {
|
|
||||||
o.Printer.Logger.Warn("Error fetching engine config",
|
|
||||||
o.Printer.Logger.Args("configMap", configMap.Name))
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
falcoCfgEngine["kind"] = driverType.String()
|
|
||||||
falcoCfgData["engine"] = falcoCfgEngine
|
|
||||||
falcoCfgBytes, err := yaml.Marshal(falcoCfgData)
|
|
||||||
if err != nil {
|
|
||||||
o.Printer.Logger.Warn("Error generating update data",
|
|
||||||
o.Printer.Logger.Args("configMap", configMap.Name, "err", err))
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
configMap.Data["falco.yaml"] = string(falcoCfgBytes)
|
|
||||||
attempt := 0
|
|
||||||
err = retry.RetryOnConflict(retry.DefaultRetry, func() error {
|
|
||||||
o.Printer.Logger.Debug("Updating",
|
|
||||||
o.Printer.Logger.Args("configMap", configMap.Name, "attempt", attempt))
|
|
||||||
_, err := cl.CoreV1().ConfigMaps(configMap.Namespace).Update(
|
|
||||||
ctx, configMap, metav1.UpdateOptions{})
|
|
||||||
attempt++
|
|
||||||
return err
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
updated = true
|
} else {
|
||||||
|
if overwrite, err = o.IsRunningInDriverModeHost(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if overwrite {
|
||||||
|
o.Printer.Logger.Info("Committing driver config to specialized configuration file under",
|
||||||
|
o.Printer.Logger.Args("directory", filepath.Join(o.configDir, "config.d")))
|
||||||
|
return overwriteDriverType(o.configDir, driverType)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !updated {
|
o.Printer.Logger.Info("Falco is not configured to run with a driver, no need to set driver type.")
|
||||||
return errors.New("could not update any configmap")
|
|
||||||
}
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// commit saves the updated driver type to Falco config,
|
func setupClient(kubeconfig string) (kubernetes.Interface, error) {
|
||||||
// either to the local falco.yaml or updating the deployment configmap.
|
var cfg *rest.Config
|
||||||
func (o *driverConfigOptions) commit(ctx context.Context, driverType drivertype.DriverType) error {
|
var err error
|
||||||
if o.Namespace != "" {
|
|
||||||
// Ok we are on k8s
|
// Create the rest config.
|
||||||
o.Printer.Logger.Info("Committing driver config to k8s configmap",
|
if kubeconfig != "" {
|
||||||
o.Printer.Logger.Args("namespace", o.Namespace))
|
cfg, err = clientcmd.BuildConfigFromFlags("", kubeconfig)
|
||||||
return o.replaceDriverTypeInK8SConfigMap(ctx, driverType)
|
} else {
|
||||||
|
cfg, err = rest.InClusterConfig()
|
||||||
}
|
}
|
||||||
o.Printer.Logger.Info("Committing driver config to local Falco config")
|
if err != nil {
|
||||||
return o.replaceDriverTypeInFalcoConfig(driverType)
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the clientset.
|
||||||
|
return kubernetes.NewForConfig(cfg)
|
||||||
|
}
|
||||||
|
|
||||||
|
func overwriteDriverType(configDir string, driverType drivertype.DriverType) error {
|
||||||
|
var falcoConfig falcoCfg
|
||||||
|
|
||||||
|
configDir = filepath.Join(configDir, "config.d")
|
||||||
|
// First thing, check if config.d folder exists in the configuration directory.
|
||||||
|
_, err := os.Stat(configDir)
|
||||||
|
if os.IsNotExist(err) {
|
||||||
|
// Create it.
|
||||||
|
// #nosec G301 -- under /etc we want 755 permissions
|
||||||
|
if err := os.MkdirAll(configDir, 0o755); err != nil {
|
||||||
|
return fmt.Errorf("unable to create directory %s: %w", configDir, err)
|
||||||
|
}
|
||||||
|
} else if err != nil && !os.IsNotExist(err) {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
falcoConfig.Engine.Kind = driverType.String()
|
||||||
|
engineKind, err := yaml.Marshal(falcoConfig)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("unable to marshal falco config: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write the engine configuration to a specialized config file.
|
||||||
|
// #nosec G306 //under /etc we want 644 permissions
|
||||||
|
if err := os.WriteFile(filepath.Join(configDir, falcoDriverConfigFile), engineKind, 0o644); err != nil {
|
||||||
|
return fmt.Errorf("unable to persist engine kind to filesystem: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,10 +35,12 @@ Usage:
|
||||||
falcoctl driver config [flags]
|
falcoctl driver config [flags]
|
||||||
|
|
||||||
Flags:
|
Flags:
|
||||||
|
--configmap string Falco configmap name.
|
||||||
|
--falco-config-dir string Falco configuration directory. (default "/etc/falco")
|
||||||
-h, --help help for config
|
-h, --help help for config
|
||||||
--kubeconfig string Kubernetes config.
|
--kubeconfig string Kubernetes config.
|
||||||
--namespace string Kubernetes namespace.
|
--namespace string Kubernetes namespace.
|
||||||
--update-falco Whether to update Falco config/configmap. (default true)
|
--update-falco Whether to overwrite Falco configuration (default true)
|
||||||
|
|
||||||
Global Flags:
|
Global Flags:
|
||||||
--config string config file to be used for falcoctl (default "/etc/falcoctl/falcoctl.yaml")
|
--config string config file to be used for falcoctl (default "/etc/falcoctl/falcoctl.yaml")
|
||||||
|
|
|
@ -138,6 +138,8 @@ func NewDriverCmd(ctx context.Context, opt *options.Common) *cobra.Command {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
allowedDriverTypes = append(allowedDriverTypes, drvType)
|
allowedDriverTypes = append(allowedDriverTypes, drvType)
|
||||||
|
opt.Printer.Logger.Debug("Allowed driver",
|
||||||
|
opt.Printer.Logger.Args("type", drvType))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 2: fetch system info (kernel release/version and distro)
|
// Step 2: fetch system info (kernel release/version and distro)
|
||||||
|
|
|
@ -43,6 +43,7 @@ type driverInstallOptions struct {
|
||||||
*options.Driver
|
*options.Driver
|
||||||
Download bool
|
Download bool
|
||||||
Compile bool
|
Compile bool
|
||||||
|
DownloadHeaders bool
|
||||||
driverDownloadOptions
|
driverDownloadOptions
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -77,6 +78,7 @@ func NewDriverInstallCmd(ctx context.Context, opt *options.Common, driver *optio
|
||||||
|
|
||||||
cmd.Flags().BoolVar(&o.Download, "download", true, "Whether to enable download of prebuilt drivers")
|
cmd.Flags().BoolVar(&o.Download, "download", true, "Whether to enable download of prebuilt drivers")
|
||||||
cmd.Flags().BoolVar(&o.Compile, "compile", true, "Whether to enable local compilation of drivers")
|
cmd.Flags().BoolVar(&o.Compile, "compile", true, "Whether to enable local compilation of drivers")
|
||||||
|
cmd.Flags().BoolVar(&o.DownloadHeaders, "download-headers", true, "Whether to enable automatic kernel headers download where supported")
|
||||||
cmd.Flags().BoolVar(&o.InsecureDownload, "http-insecure", false, "Whether you want to allow insecure downloads or not")
|
cmd.Flags().BoolVar(&o.InsecureDownload, "http-insecure", false, "Whether you want to allow insecure downloads or not")
|
||||||
cmd.Flags().DurationVar(&o.HTTPTimeout, "http-timeout", 60*time.Second, "Timeout for each http try")
|
cmd.Flags().DurationVar(&o.HTTPTimeout, "http-timeout", 60*time.Second, "Timeout for each http try")
|
||||||
cmd.Flags().StringVar(&o.HTTPHeaders, "http-headers",
|
cmd.Flags().StringVar(&o.HTTPHeaders, "http-headers",
|
||||||
|
@ -191,7 +193,7 @@ func (o *driverInstallOptions) RunDriverInstall(ctx context.Context) (string, er
|
||||||
if !o.Printer.DisableStyling {
|
if !o.Printer.DisableStyling {
|
||||||
o.Printer.Spinner, _ = o.Printer.Spinner.Start("Trying to build the driver")
|
o.Printer.Spinner, _ = o.Printer.Spinner.Start("Trying to build the driver")
|
||||||
}
|
}
|
||||||
dest, err = driverdistro.Build(ctx, o.Distro, o.Printer.WithWriter(&buf), o.Kr, o.Driver.Name, o.Driver.Type, o.Driver.Version)
|
dest, err = driverdistro.Build(ctx, o.Distro, o.Printer.WithWriter(&buf), o.Kr, o.Driver.Name, o.Driver.Type, o.Driver.Version, o.DownloadHeaders)
|
||||||
if o.Printer.Spinner != nil {
|
if o.Printer.Spinner != nil {
|
||||||
_ = o.Printer.Spinner.Stop()
|
_ = o.Printer.Spinner.Stop()
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,6 +34,7 @@ Usage:
|
||||||
Flags:
|
Flags:
|
||||||
--compile Whether to enable local compilation of drivers (default true)
|
--compile Whether to enable local compilation of drivers (default true)
|
||||||
--download Whether to enable download of prebuilt drivers (default true)
|
--download Whether to enable download of prebuilt drivers (default true)
|
||||||
|
--download-headers Whether to enable automatic kernel headers download where supported (default true)
|
||||||
-h, --help help for install
|
-h, --help help for install
|
||||||
--http-headers string Optional comma-separated list of headers for the http GET request (e.g. --http-headers='x-emc-namespace: default,Proxy-Authenticate: Basic'). Not necessary if default repo is used
|
--http-headers string Optional comma-separated list of headers for the http GET request (e.g. --http-headers='x-emc-namespace: default,Proxy-Authenticate: Basic'). Not necessary if default repo is used
|
||||||
--http-insecure Whether you want to allow insecure downloads or not
|
--http-insecure Whether you want to allow insecure downloads or not
|
||||||
|
|
|
@ -16,10 +16,16 @@
|
||||||
package basic
|
package basic
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bufio"
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
"github.com/spf13/viper"
|
||||||
|
"golang.org/x/term"
|
||||||
"oras.land/oras-go/v2/registry/remote/credentials"
|
"oras.land/oras-go/v2/registry/remote/credentials"
|
||||||
|
|
||||||
"github.com/falcosecurity/falcoctl/internal/config"
|
"github.com/falcosecurity/falcoctl/internal/config"
|
||||||
|
@ -27,10 +33,14 @@ import (
|
||||||
"github.com/falcosecurity/falcoctl/internal/utils"
|
"github.com/falcosecurity/falcoctl/internal/utils"
|
||||||
"github.com/falcosecurity/falcoctl/pkg/oci/authn"
|
"github.com/falcosecurity/falcoctl/pkg/oci/authn"
|
||||||
"github.com/falcosecurity/falcoctl/pkg/options"
|
"github.com/falcosecurity/falcoctl/pkg/options"
|
||||||
|
"github.com/falcosecurity/falcoctl/pkg/output"
|
||||||
)
|
)
|
||||||
|
|
||||||
type loginOptions struct {
|
type loginOptions struct {
|
||||||
*options.Common
|
*options.Common
|
||||||
|
username string
|
||||||
|
password string
|
||||||
|
passwordFromStdin bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewBasicCmd returns the basic command.
|
// NewBasicCmd returns the basic command.
|
||||||
|
@ -43,22 +53,56 @@ func NewBasicCmd(ctx context.Context, opt *options.Common) *cobra.Command {
|
||||||
Use: "basic [hostname]",
|
Use: "basic [hostname]",
|
||||||
DisableFlagsInUseLine: true,
|
DisableFlagsInUseLine: true,
|
||||||
Short: "Login to an OCI registry",
|
Short: "Login to an OCI registry",
|
||||||
Long: "Login to an OCI registry to push and pull artifacts",
|
Long: `Login to an OCI registry
|
||||||
|
|
||||||
|
Example - Log in with username and password from command line flags:
|
||||||
|
falcoctl registry auth basic -u username -p password localhost:5000
|
||||||
|
|
||||||
|
Example - Login with username and password from env variables:
|
||||||
|
FALCOCTL_REGISTRY_AUTH_BASIC_USERNAME=username FALCOCTL_REGISTRY_AUTH_BASIC_PASSWORD=password falcoctl registry auth basic localhost:5000
|
||||||
|
|
||||||
|
Example - Login with username and password from stdin:
|
||||||
|
falcoctl registry auth basic -u username --password-stdin localhost:5000
|
||||||
|
|
||||||
|
Example - Login with username and password in an interactive prompt:
|
||||||
|
falcoctl registry auth basic localhost:5000
|
||||||
|
`,
|
||||||
Args: cobra.ExactArgs(1),
|
Args: cobra.ExactArgs(1),
|
||||||
|
PreRunE: func(cmd *cobra.Command, args []string) error {
|
||||||
|
_ = viper.BindPFlag("registry.auth.basic.username", cmd.Flags().Lookup("username"))
|
||||||
|
_ = viper.BindPFlag("registry.auth.basic.password", cmd.Flags().Lookup("password"))
|
||||||
|
_ = viper.BindPFlag("registry.auth.basic.password_stdin", cmd.Flags().Lookup("password-stdin"))
|
||||||
|
|
||||||
|
o.username = viper.GetString("registry.auth.basic.username")
|
||||||
|
o.password = viper.GetString("registry.auth.basic.password")
|
||||||
|
o.passwordFromStdin = viper.GetBool("registry.auth.basic.password_stdin")
|
||||||
|
|
||||||
|
return nil
|
||||||
|
},
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
return o.RunBasic(ctx, args)
|
return o.RunBasic(ctx, args)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cmd.Flags().StringVarP(&o.username, "username", "u", "", "registry username")
|
||||||
|
cmd.Flags().StringVarP(&o.password, "password", "p", "", "registry password")
|
||||||
|
cmd.Flags().BoolVar(&o.passwordFromStdin, "password-stdin", false, "read password from stdin")
|
||||||
|
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
// RunBasic executes the business logic for the basic command.
|
// RunBasic executes the business logic for the basic command.
|
||||||
func (o *loginOptions) RunBasic(ctx context.Context, args []string) error {
|
func (o *loginOptions) RunBasic(ctx context.Context, args []string) error {
|
||||||
reg := args[0]
|
var reg string
|
||||||
logger := o.Printer.Logger
|
logger := o.Printer.Logger
|
||||||
user, token, err := utils.GetCredentials(o.Printer)
|
|
||||||
|
// Allow to have the registry expressed as a ref, but actually extract it.
|
||||||
|
reg, err := utils.GetRegistryFromRef(args[0])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
reg = args[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := getCredentials(o.Printer, o); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,11 +117,46 @@ func (o *loginOptions) RunBasic(ctx context.Context, args []string) error {
|
||||||
return fmt.Errorf("unable to create new store: %w", err)
|
return fmt.Errorf("unable to create new store: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := basic.Login(ctx, client, credentialStore, reg, user, token); err != nil {
|
if err := basic.Login(ctx, client, credentialStore, reg, o.username, o.password); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
logger.Debug("Credentials added", logger.Args("credential store", config.RegistryCredentialConfPath()))
|
logger.Debug("Credentials added", logger.Args("credential store", config.RegistryCredentialConfPath()))
|
||||||
logger.Info("Login succeeded", logger.Args("registry", reg, "user", user))
|
logger.Info("Login succeeded", logger.Args("registry", reg, "user", o.username))
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// getCredentials is used to retrieve username and password from standard input.
|
||||||
|
func getCredentials(p *output.Printer, opt *loginOptions) error {
|
||||||
|
reader := bufio.NewReader(os.Stdin)
|
||||||
|
|
||||||
|
if opt.username == "" {
|
||||||
|
p.DefaultText.Print(p.FormatTitleAsLoggerInfo("Enter username:"))
|
||||||
|
username, err := reader.ReadString('\n')
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
opt.username = strings.TrimSpace(username)
|
||||||
|
}
|
||||||
|
|
||||||
|
if opt.password == "" {
|
||||||
|
if opt.passwordFromStdin {
|
||||||
|
password, err := io.ReadAll(os.Stdin)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
opt.password = strings.TrimSuffix(string(password), "\n")
|
||||||
|
opt.password = strings.TrimSuffix(opt.password, "\r")
|
||||||
|
} else {
|
||||||
|
p.DefaultText.Print(p.FormatTitleAsLoggerInfo("Enter password: "))
|
||||||
|
bytePassword, err := term.ReadPassword(int(os.Stdin.Fd()))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
opt.password = string(bytePassword)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,7 +59,34 @@ Global Flags:
|
||||||
`
|
`
|
||||||
|
|
||||||
//nolint:unused // false positive
|
//nolint:unused // false positive
|
||||||
var registryAuthBasicHelp = `Login to an OCI registry to push and pull artifacts`
|
var registryAuthBasicHelp = `Login to an OCI registry
|
||||||
|
|
||||||
|
Example - Log in with username and password from command line flags:
|
||||||
|
falcoctl registry auth basic -u username -p password localhost:5000
|
||||||
|
|
||||||
|
Example - Login with username and password from env variables:
|
||||||
|
FALCOCTL_REGISTRY_AUTH_BASIC_USERNAME=username FALCOCTL_REGISTRY_AUTH_BASIC_PASSWORD=password falcoctl registry auth basic localhost:5000
|
||||||
|
|
||||||
|
Example - Login with username and password from stdin:
|
||||||
|
falcoctl registry auth basic -u username --password-stdin localhost:5000
|
||||||
|
|
||||||
|
Example - Login with username and password in an interactive prompt:
|
||||||
|
falcoctl registry auth basic localhost:5000
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
falcoctl registry auth basic [hostname]
|
||||||
|
|
||||||
|
Flags:
|
||||||
|
-h, --help help for basic
|
||||||
|
-p, --password string registry password
|
||||||
|
--password-stdin read password from stdin
|
||||||
|
-u, --username string registry username
|
||||||
|
|
||||||
|
Global Flags:
|
||||||
|
--config string config file to be used for falcoctl (default "/etc/falcoctl/falcoctl.yaml")
|
||||||
|
--log-format string Set formatting for logs (color, text, json) (default "color")
|
||||||
|
--log-level string Set level for logs (info, warn, debug, trace) (default "info")
|
||||||
|
`
|
||||||
|
|
||||||
//nolint:unused // false positive
|
//nolint:unused // false positive
|
||||||
var registryAuthBasicAssertFailedBehavior = func(usage, specificError string) {
|
var registryAuthBasicAssertFailedBehavior = func(usage, specificError string) {
|
||||||
|
|
|
@ -174,7 +174,7 @@ func (o *pushOptions) runPush(ctx context.Context, args []string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
path, err := utils.CreateTarGzArchive("", p)
|
path, err := utils.CreateTarGzArchive("", p, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
369
go.mod
369
go.mod
|
@ -1,73 +1,76 @@
|
||||||
module github.com/falcosecurity/falcoctl
|
module github.com/falcosecurity/falcoctl
|
||||||
|
|
||||||
go 1.22.0
|
go 1.24.3
|
||||||
|
|
||||||
toolchain go1.22.2
|
|
||||||
|
|
||||||
require (
|
require (
|
||||||
cloud.google.com/go/storage v1.40.0
|
cloud.google.com/go/storage v1.51.0
|
||||||
|
github.com/aws/aws-sdk-go-v2 v1.36.3
|
||||||
|
github.com/aws/aws-sdk-go-v2/config v1.29.9
|
||||||
|
github.com/aws/aws-sdk-go-v2/service/s3 v1.58.3
|
||||||
github.com/blang/semver v3.5.1+incompatible
|
github.com/blang/semver v3.5.1+incompatible
|
||||||
github.com/blang/semver/v4 v4.0.0
|
github.com/blang/semver/v4 v4.0.0
|
||||||
github.com/cilium/ebpf v0.15.0
|
github.com/cilium/ebpf v0.17.3
|
||||||
github.com/distribution/distribution/v3 v3.0.0-alpha.1
|
github.com/distribution/distribution/v3 v3.0.0
|
||||||
github.com/docker/cli v26.1.2+incompatible
|
github.com/docker/cli v28.3.2+incompatible
|
||||||
github.com/docker/docker v26.1.2+incompatible
|
github.com/docker/docker v28.3.3+incompatible
|
||||||
github.com/falcosecurity/driverkit v0.19.2
|
github.com/falcosecurity/driverkit v0.21.2
|
||||||
github.com/go-oauth2/oauth2/v4 v4.5.2
|
github.com/go-oauth2/oauth2/v4 v4.5.3
|
||||||
github.com/golang-jwt/jwt v3.2.2+incompatible
|
github.com/golang-jwt/jwt/v5 v5.2.2
|
||||||
github.com/google/go-containerregistry v0.19.1
|
github.com/google/go-containerregistry v0.20.3
|
||||||
github.com/gookit/color v1.5.4
|
github.com/gookit/color v1.5.4
|
||||||
github.com/mitchellh/mapstructure v1.5.0
|
github.com/mattn/go-isatty v0.0.20
|
||||||
github.com/onsi/ginkgo/v2 v2.17.3
|
github.com/mitchellh/mapstructure v1.5.1-0.20231216201459-8508981c8b6c
|
||||||
github.com/onsi/gomega v1.33.1
|
github.com/onsi/ginkgo/v2 v2.23.3
|
||||||
github.com/opencontainers/image-spec v1.1.0
|
github.com/onsi/gomega v1.36.3
|
||||||
github.com/pterm/pterm v0.12.79
|
github.com/opencontainers/image-spec v1.1.1
|
||||||
|
github.com/pterm/pterm v0.12.80
|
||||||
github.com/robfig/cron/v3 v3.0.1
|
github.com/robfig/cron/v3 v3.0.1
|
||||||
github.com/sigstore/cosign/v2 v2.2.4
|
github.com/sigstore/cosign/v2 v2.4.3
|
||||||
github.com/sigstore/sigstore v1.8.3
|
github.com/sigstore/sigstore v1.9.1
|
||||||
github.com/sigstore/sigstore/pkg/signature/kms/aws v1.8.3
|
github.com/sigstore/sigstore/pkg/signature/kms/aws v1.9.1
|
||||||
github.com/sigstore/sigstore/pkg/signature/kms/azure v1.8.3
|
github.com/sigstore/sigstore/pkg/signature/kms/azure v1.9.1
|
||||||
github.com/sigstore/sigstore/pkg/signature/kms/gcp v1.8.3
|
github.com/sigstore/sigstore/pkg/signature/kms/gcp v1.9.1
|
||||||
github.com/sigstore/sigstore/pkg/signature/kms/hashivault v1.8.3
|
github.com/sigstore/sigstore/pkg/signature/kms/hashivault v1.9.1
|
||||||
github.com/spf13/cobra v1.8.0
|
github.com/spf13/cobra v1.9.1
|
||||||
github.com/spf13/pflag v1.0.5
|
github.com/spf13/pflag v1.0.6
|
||||||
github.com/spf13/viper v1.18.2
|
github.com/spf13/viper v1.20.0
|
||||||
golang.org/x/crypto v0.23.0
|
github.com/stretchr/testify v1.10.0
|
||||||
golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842
|
golang.org/x/crypto v0.38.0
|
||||||
google.golang.org/api v0.180.0
|
golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f
|
||||||
|
golang.org/x/net v0.40.0
|
||||||
|
golang.org/x/oauth2 v0.28.0
|
||||||
|
golang.org/x/sys v0.33.0
|
||||||
|
golang.org/x/term v0.32.0
|
||||||
|
google.golang.org/api v0.227.0
|
||||||
gopkg.in/ini.v1 v1.67.0
|
gopkg.in/ini.v1 v1.67.0
|
||||||
gopkg.in/yaml.v3 v3.0.1
|
gopkg.in/yaml.v3 v3.0.1
|
||||||
k8s.io/apimachinery v0.30.0
|
k8s.io/api v0.32.3
|
||||||
k8s.io/client-go v0.30.0
|
k8s.io/apimachinery v0.32.3
|
||||||
|
k8s.io/client-go v0.32.3
|
||||||
oras.land/oras-go/v2 v2.5.0
|
oras.land/oras-go/v2 v2.5.0
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
|
||||||
github.com/docker/docker-credential-helpers v0.8.1 // indirect
|
|
||||||
github.com/opencontainers/go-digest v1.0.0 // indirect
|
|
||||||
golang.org/x/sync v0.7.0 // indirect
|
|
||||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
|
||||||
)
|
|
||||||
|
|
||||||
require (
|
require (
|
||||||
atomicgo.dev/cursor v0.2.0 // indirect
|
atomicgo.dev/cursor v0.2.0 // indirect
|
||||||
atomicgo.dev/keyboard v0.2.9 // indirect
|
atomicgo.dev/keyboard v0.2.9 // indirect
|
||||||
atomicgo.dev/schedule v0.1.0 // indirect
|
atomicgo.dev/schedule v0.1.0 // indirect
|
||||||
cloud.google.com/go v0.112.2 // indirect
|
cel.dev/expr v0.19.2 // indirect
|
||||||
cloud.google.com/go/auth v0.4.1 // indirect
|
cloud.google.com/go v0.118.3 // indirect
|
||||||
cloud.google.com/go/auth/oauth2adapt v0.2.2 // indirect
|
cloud.google.com/go/auth v0.15.0 // indirect
|
||||||
cloud.google.com/go/compute/metadata v0.3.0 // indirect
|
cloud.google.com/go/auth/oauth2adapt v0.2.7 // indirect
|
||||||
cloud.google.com/go/iam v1.1.8 // indirect
|
cloud.google.com/go/compute/metadata v0.6.0 // indirect
|
||||||
cloud.google.com/go/kms v1.15.9 // indirect
|
cloud.google.com/go/iam v1.4.1 // indirect
|
||||||
filippo.io/edwards25519 v1.1.0 // indirect
|
cloud.google.com/go/kms v1.21.0 // indirect
|
||||||
github.com/AliyunContainerService/ack-ram-tool/pkg/credentials/alibabacloudsdkgo/helper v0.2.0 // indirect
|
cloud.google.com/go/longrunning v0.6.5 // indirect
|
||||||
|
cloud.google.com/go/monitoring v1.24.0 // indirect
|
||||||
|
github.com/AliyunContainerService/ack-ram-tool/pkg/credentials/provider v0.14.0 // indirect
|
||||||
github.com/Azure/azure-sdk-for-go v68.0.0+incompatible // indirect
|
github.com/Azure/azure-sdk-for-go v68.0.0+incompatible // indirect
|
||||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.11.1 // indirect
|
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.17.1 // indirect
|
||||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.5.2 // indirect
|
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.2 // indirect
|
||||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.7.0 // indirect
|
github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 // indirect
|
||||||
github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys v1.1.0 // indirect
|
github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys v1.3.1 // indirect
|
||||||
github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v1.0.1 // indirect
|
github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v1.1.1 // indirect
|
||||||
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect
|
github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c // indirect
|
||||||
github.com/Azure/go-autorest v14.2.0+incompatible // indirect
|
github.com/Azure/go-autorest v14.2.0+incompatible // indirect
|
||||||
github.com/Azure/go-autorest/autorest v0.11.29 // indirect
|
github.com/Azure/go-autorest/autorest v0.11.29 // indirect
|
||||||
github.com/Azure/go-autorest/autorest/adal v0.9.23 // indirect
|
github.com/Azure/go-autorest/autorest/adal v0.9.23 // indirect
|
||||||
|
@ -76,7 +79,10 @@ require (
|
||||||
github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect
|
github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect
|
||||||
github.com/Azure/go-autorest/logger v0.2.1 // indirect
|
github.com/Azure/go-autorest/logger v0.2.1 // indirect
|
||||||
github.com/Azure/go-autorest/tracing v0.6.0 // indirect
|
github.com/Azure/go-autorest/tracing v0.6.0 // indirect
|
||||||
github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2 // indirect
|
github.com/AzureAD/microsoft-authentication-library-for-go v1.3.3 // indirect
|
||||||
|
github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.25.0 // indirect
|
||||||
|
github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.51.0 // indirect
|
||||||
|
github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.51.0 // indirect
|
||||||
github.com/MakeNowJust/heredoc v1.0.0 // indirect
|
github.com/MakeNowJust/heredoc v1.0.0 // indirect
|
||||||
github.com/Microsoft/go-winio v0.6.2 // indirect
|
github.com/Microsoft/go-winio v0.6.2 // indirect
|
||||||
github.com/ProtonMail/go-crypto v1.0.0 // indirect
|
github.com/ProtonMail/go-crypto v1.0.0 // indirect
|
||||||
|
@ -93,42 +99,45 @@ require (
|
||||||
github.com/alibabacloud-go/tea-xml v1.1.3 // indirect
|
github.com/alibabacloud-go/tea-xml v1.1.3 // indirect
|
||||||
github.com/aliyun/credentials-go v1.3.3 // indirect
|
github.com/aliyun/credentials-go v1.3.3 // indirect
|
||||||
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect
|
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect
|
||||||
github.com/aws/aws-sdk-go-v2 v1.26.1 // indirect
|
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.3 // indirect
|
||||||
github.com/aws/aws-sdk-go-v2/config v1.27.11 // indirect
|
github.com/aws/aws-sdk-go-v2/credentials v1.17.62 // indirect
|
||||||
github.com/aws/aws-sdk-go-v2/credentials v1.17.11 // indirect
|
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.30 // indirect
|
||||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.1 // indirect
|
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.34 // indirect
|
||||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.5 // indirect
|
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.34 // indirect
|
||||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.5 // indirect
|
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 // indirect
|
||||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 // indirect
|
github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.15 // indirect
|
||||||
github.com/aws/aws-sdk-go-v2/service/ecr v1.27.4 // indirect
|
github.com/aws/aws-sdk-go-v2/service/ecr v1.40.3 // indirect
|
||||||
github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.23.4 // indirect
|
github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.31.2 // indirect
|
||||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.2 // indirect
|
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.3 // indirect
|
||||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.7 // indirect
|
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.3.17 // indirect
|
||||||
github.com/aws/aws-sdk-go-v2/service/kms v1.31.0 // indirect
|
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.15 // indirect
|
||||||
github.com/aws/aws-sdk-go-v2/service/sso v1.20.5 // indirect
|
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.15 // indirect
|
||||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.23.4 // indirect
|
github.com/aws/aws-sdk-go-v2/service/kms v1.38.1 // indirect
|
||||||
github.com/aws/aws-sdk-go-v2/service/sts v1.28.6 // indirect
|
github.com/aws/aws-sdk-go-v2/service/sso v1.25.1 // indirect
|
||||||
github.com/aws/smithy-go v1.20.2 // indirect
|
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.29.1 // indirect
|
||||||
github.com/awslabs/amazon-ecr-credential-helper/ecr-login v0.0.0-20240507150535-b99368f3064d // indirect
|
github.com/aws/aws-sdk-go-v2/service/sts v1.33.17 // indirect
|
||||||
|
github.com/aws/smithy-go v1.22.2 // indirect
|
||||||
|
github.com/awslabs/amazon-ecr-credential-helper/ecr-login v0.9.1 // indirect
|
||||||
github.com/beorn7/perks v1.0.1 // indirect
|
github.com/beorn7/perks v1.0.1 // indirect
|
||||||
github.com/bshuster-repo/logrus-logstash-hook v1.1.0 // indirect
|
github.com/bshuster-repo/logrus-logstash-hook v1.1.0 // indirect
|
||||||
github.com/buildkite/agent/v3 v3.72.0 // indirect
|
github.com/buildkite/agent/v3 v3.92.1 // indirect
|
||||||
github.com/buildkite/go-pipeline v0.9.0 // indirect
|
github.com/buildkite/go-pipeline v0.13.3 // indirect
|
||||||
github.com/buildkite/interpolate v0.0.0-20200526001904-07f35b4ae251 // indirect
|
github.com/buildkite/interpolate v0.1.5 // indirect
|
||||||
github.com/buildkite/roko v1.2.0 // indirect
|
github.com/buildkite/roko v1.3.1 // indirect
|
||||||
github.com/cenkalti/backoff/v3 v3.2.2 // indirect
|
|
||||||
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
|
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
|
||||||
github.com/cespare/xxhash/v2 v2.2.0 // indirect
|
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||||
github.com/chai2010/gettext-go v1.0.3 // indirect
|
github.com/chai2010/gettext-go v1.0.3 // indirect
|
||||||
github.com/chrismellard/docker-credential-acr-env v0.0.0-20230304212654-82a0ddb27589 // indirect
|
github.com/chrismellard/docker-credential-acr-env v0.0.0-20230304212654-82a0ddb27589 // indirect
|
||||||
github.com/clbanning/mxj/v2 v2.7.0 // indirect
|
github.com/clbanning/mxj/v2 v2.7.0 // indirect
|
||||||
github.com/cloudflare/circl v1.3.8 // indirect
|
github.com/cloudflare/circl v1.6.1 // indirect
|
||||||
|
github.com/cncf/xds/go v0.0.0-20250121191232-2f005788dc42 // indirect
|
||||||
github.com/common-nighthawk/go-figure v0.0.0-20210622060536-734e95fb86be // indirect
|
github.com/common-nighthawk/go-figure v0.0.0-20210622060536-734e95fb86be // indirect
|
||||||
github.com/containerd/console v1.0.4 // indirect
|
github.com/containerd/console v1.0.4 // indirect
|
||||||
github.com/containerd/containerd v1.7.16 // indirect
|
github.com/containerd/errdefs v1.0.0 // indirect
|
||||||
|
github.com/containerd/errdefs/pkg v0.3.0 // indirect
|
||||||
github.com/containerd/log v0.1.0 // indirect
|
github.com/containerd/log v0.1.0 // indirect
|
||||||
github.com/containerd/stargz-snapshotter/estargz v0.15.1 // indirect
|
github.com/containerd/stargz-snapshotter/estargz v0.16.3 // indirect
|
||||||
github.com/coreos/go-oidc/v3 v3.10.0 // indirect
|
github.com/coreos/go-oidc/v3 v3.12.0 // indirect
|
||||||
github.com/coreos/go-systemd/v22 v22.5.0 // indirect
|
github.com/coreos/go-systemd/v22 v22.5.0 // indirect
|
||||||
github.com/creasty/defaults v1.7.0 // indirect
|
github.com/creasty/defaults v1.7.0 // indirect
|
||||||
github.com/cyberphone/json-canonicalization v0.0.0-20231217050601-ba74d44ecf5f // indirect
|
github.com/cyberphone/json-canonicalization v0.0.0-20231217050601-ba74d44ecf5f // indirect
|
||||||
|
@ -139,23 +148,28 @@ require (
|
||||||
github.com/dimchansky/utfbom v1.1.1 // indirect
|
github.com/dimchansky/utfbom v1.1.1 // indirect
|
||||||
github.com/distribution/reference v0.6.0 // indirect
|
github.com/distribution/reference v0.6.0 // indirect
|
||||||
github.com/docker/distribution v2.8.3+incompatible // indirect
|
github.com/docker/distribution v2.8.3+incompatible // indirect
|
||||||
|
github.com/docker/docker-credential-helpers v0.8.2 // indirect
|
||||||
github.com/docker/go-connections v0.5.0 // indirect
|
github.com/docker/go-connections v0.5.0 // indirect
|
||||||
github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c // indirect
|
github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c // indirect
|
||||||
github.com/docker/go-metrics v0.0.1 // indirect
|
github.com/docker/go-metrics v0.0.1 // indirect
|
||||||
github.com/docker/go-units v0.5.0 // indirect
|
github.com/docker/go-units v0.5.0 // indirect
|
||||||
github.com/dustin/go-humanize v1.0.1 // indirect
|
github.com/dustin/go-humanize v1.0.1 // indirect
|
||||||
github.com/emicklei/go-restful/v3 v3.12.0 // indirect
|
github.com/emicklei/go-restful/v3 v3.12.0 // indirect
|
||||||
|
github.com/envoyproxy/go-control-plane/envoy v1.32.4 // indirect
|
||||||
|
github.com/envoyproxy/protoc-gen-validate v1.2.1 // indirect
|
||||||
github.com/evanphx/json-patch v5.9.0+incompatible // indirect
|
github.com/evanphx/json-patch v5.9.0+incompatible // indirect
|
||||||
github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f // indirect
|
github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f // indirect
|
||||||
github.com/fatih/camelcase v1.0.0 // indirect
|
github.com/fatih/camelcase v1.0.0 // indirect
|
||||||
github.com/felixge/httpsnoop v1.0.4 // indirect
|
github.com/felixge/httpsnoop v1.0.4 // indirect
|
||||||
|
github.com/fsnotify/fsnotify v1.8.0 // indirect
|
||||||
github.com/fvbommel/sortorder v1.1.0 // indirect
|
github.com/fvbommel/sortorder v1.1.0 // indirect
|
||||||
github.com/gabriel-vasile/mimetype v1.4.3 // indirect
|
github.com/fxamacker/cbor/v2 v2.7.0 // indirect
|
||||||
|
github.com/gabriel-vasile/mimetype v1.4.8 // indirect
|
||||||
github.com/go-chi/chi v4.1.2+incompatible // indirect
|
github.com/go-chi/chi v4.1.2+incompatible // indirect
|
||||||
github.com/go-errors/errors v1.5.1 // indirect
|
github.com/go-errors/errors v1.5.1 // indirect
|
||||||
github.com/go-jose/go-jose/v3 v3.0.3 // indirect
|
github.com/go-jose/go-jose/v3 v3.0.4 // indirect
|
||||||
github.com/go-jose/go-jose/v4 v4.0.1 // indirect
|
github.com/go-jose/go-jose/v4 v4.0.5 // indirect
|
||||||
github.com/go-logr/logr v1.4.1 // indirect
|
github.com/go-logr/logr v1.4.2 // indirect
|
||||||
github.com/go-logr/stdr v1.2.2 // indirect
|
github.com/go-logr/stdr v1.2.2 // indirect
|
||||||
github.com/go-openapi/analysis v0.23.0 // indirect
|
github.com/go-openapi/analysis v0.23.0 // indirect
|
||||||
github.com/go-openapi/errors v0.22.0 // indirect
|
github.com/go-openapi/errors v0.22.0 // indirect
|
||||||
|
@ -167,39 +181,38 @@ require (
|
||||||
github.com/go-openapi/strfmt v0.23.0 // indirect
|
github.com/go-openapi/strfmt v0.23.0 // indirect
|
||||||
github.com/go-openapi/swag v0.23.0 // indirect
|
github.com/go-openapi/swag v0.23.0 // indirect
|
||||||
github.com/go-openapi/validate v0.24.0 // indirect
|
github.com/go-openapi/validate v0.24.0 // indirect
|
||||||
github.com/go-piv/piv-go v1.11.0 // indirect
|
github.com/go-piv/piv-go/v2 v2.3.0 // indirect
|
||||||
github.com/go-playground/locales v0.14.1 // indirect
|
github.com/go-playground/locales v0.14.1 // indirect
|
||||||
github.com/go-playground/universal-translator v0.18.1 // indirect
|
github.com/go-playground/universal-translator v0.18.1 // indirect
|
||||||
github.com/go-playground/validator/v10 v10.20.0 // indirect
|
github.com/go-playground/validator/v10 v10.24.0 // indirect
|
||||||
github.com/go-task/slim-sprig/v3 v3.0.0 // indirect
|
github.com/go-task/slim-sprig/v3 v3.0.0 // indirect
|
||||||
|
github.com/go-viper/mapstructure/v2 v2.3.0 // indirect
|
||||||
github.com/gogo/protobuf v1.3.2 // indirect
|
github.com/gogo/protobuf v1.3.2 // indirect
|
||||||
github.com/golang-jwt/jwt/v4 v4.5.0 // indirect
|
github.com/golang-jwt/jwt/v4 v4.5.2 // indirect
|
||||||
github.com/golang-jwt/jwt/v5 v5.2.1 // indirect
|
|
||||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
|
||||||
github.com/golang/protobuf v1.5.4 // indirect
|
github.com/golang/protobuf v1.5.4 // indirect
|
||||||
github.com/golang/snappy v0.0.4 // indirect
|
github.com/golang/snappy v0.0.4 // indirect
|
||||||
github.com/google/btree v1.1.2 // indirect
|
github.com/google/btree v1.1.3 // indirect
|
||||||
github.com/google/certificate-transparency-go v1.1.8 // indirect
|
github.com/google/certificate-transparency-go v1.3.1 // indirect
|
||||||
github.com/google/gnostic-models v0.6.9-0.20230804172637-c7be7c783f49 // indirect
|
github.com/google/gnostic-models v0.6.9-0.20230804172637-c7be7c783f49 // indirect
|
||||||
github.com/google/go-cmp v0.6.0 // indirect
|
github.com/google/go-cmp v0.7.0 // indirect
|
||||||
github.com/google/go-github/v55 v55.0.0 // indirect
|
github.com/google/go-github/v55 v55.0.0 // indirect
|
||||||
github.com/google/go-querystring v1.1.0 // indirect
|
github.com/google/go-querystring v1.1.0 // indirect
|
||||||
github.com/google/gofuzz v1.2.0 // indirect
|
github.com/google/gofuzz v1.2.0 // indirect
|
||||||
github.com/google/pprof v0.0.0-20240424215950-a892ee059fd6 // indirect
|
github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad // indirect
|
||||||
github.com/google/s2a-go v0.1.7 // indirect
|
github.com/google/s2a-go v0.1.9 // indirect
|
||||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
|
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
|
||||||
github.com/google/uuid v1.6.0 // indirect
|
github.com/google/uuid v1.6.0 // indirect
|
||||||
github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect
|
github.com/googleapis/enterprise-certificate-proxy v0.3.6 // indirect
|
||||||
github.com/googleapis/gax-go/v2 v2.12.4 // indirect
|
github.com/googleapis/gax-go/v2 v2.14.1 // indirect
|
||||||
github.com/gorilla/handlers v1.5.1 // indirect
|
github.com/gorilla/handlers v1.5.2 // indirect
|
||||||
github.com/gorilla/mux v1.8.1 // indirect
|
github.com/gorilla/mux v1.8.1 // indirect
|
||||||
github.com/gorilla/websocket v1.5.1 // indirect
|
github.com/gorilla/websocket v1.5.1 // indirect
|
||||||
github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 // indirect
|
github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 // indirect
|
||||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.1 // indirect
|
github.com/grpc-ecosystem/grpc-gateway/v2 v2.25.1 // indirect
|
||||||
github.com/hashicorp/errwrap v1.1.0 // indirect
|
github.com/hashicorp/errwrap v1.1.0 // indirect
|
||||||
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
|
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
|
||||||
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
||||||
github.com/hashicorp/go-retryablehttp v0.7.5 // indirect
|
github.com/hashicorp/go-retryablehttp v0.7.7 // indirect
|
||||||
github.com/hashicorp/go-rootcerts v1.0.2 // indirect
|
github.com/hashicorp/go-rootcerts v1.0.2 // indirect
|
||||||
github.com/hashicorp/go-secure-stdlib/parseutil v0.1.8 // indirect
|
github.com/hashicorp/go-secure-stdlib/parseutil v0.1.8 // indirect
|
||||||
github.com/hashicorp/go-secure-stdlib/strutil v0.1.2 // indirect
|
github.com/hashicorp/go-secure-stdlib/strutil v0.1.2 // indirect
|
||||||
|
@ -207,80 +220,85 @@ require (
|
||||||
github.com/hashicorp/golang-lru/arc/v2 v2.0.5 // indirect
|
github.com/hashicorp/golang-lru/arc/v2 v2.0.5 // indirect
|
||||||
github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect
|
github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect
|
||||||
github.com/hashicorp/hcl v1.0.1-vault-5 // indirect
|
github.com/hashicorp/hcl v1.0.1-vault-5 // indirect
|
||||||
github.com/hashicorp/vault/api v1.13.0 // indirect
|
github.com/hashicorp/vault/api v1.16.0 // indirect
|
||||||
github.com/imdario/mergo v0.3.16 // indirect
|
github.com/in-toto/attestation v1.1.0 // indirect
|
||||||
github.com/in-toto/in-toto-golang v0.9.0 // indirect
|
github.com/in-toto/in-toto-golang v0.9.0 // indirect
|
||||||
|
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||||
github.com/jedisct1/go-minisign v0.0.0-20230811132847-661be99b8267 // indirect
|
github.com/jedisct1/go-minisign v0.0.0-20230811132847-661be99b8267 // indirect
|
||||||
github.com/jellydator/ttlcache/v3 v3.2.0 // indirect
|
github.com/jellydator/ttlcache/v3 v3.3.0 // indirect
|
||||||
github.com/jmespath/go-jmespath v0.4.0 // indirect
|
|
||||||
github.com/josharian/intern v1.0.0 // indirect
|
github.com/josharian/intern v1.0.0 // indirect
|
||||||
github.com/json-iterator/go v1.1.12 // indirect
|
github.com/json-iterator/go v1.1.12 // indirect
|
||||||
github.com/klauspost/compress v1.17.8 // indirect
|
github.com/klauspost/compress v1.18.0 // indirect
|
||||||
github.com/kylelemons/godebug v1.1.0 // indirect
|
github.com/kylelemons/godebug v1.1.0 // indirect
|
||||||
github.com/leodido/go-urn v1.4.0 // indirect
|
github.com/leodido/go-urn v1.4.0 // indirect
|
||||||
github.com/letsencrypt/boulder v0.0.0-20240506202929-c1561b070b86 // indirect
|
github.com/letsencrypt/boulder v0.0.0-20240620165639-de9c06129bec // indirect
|
||||||
github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de // indirect
|
github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de // indirect
|
||||||
github.com/lithammer/fuzzysearch v1.1.8 // indirect
|
github.com/lithammer/fuzzysearch v1.1.8 // indirect
|
||||||
github.com/magiconair/properties v1.8.7 // indirect
|
|
||||||
github.com/mailru/easyjson v0.7.7 // indirect
|
github.com/mailru/easyjson v0.7.7 // indirect
|
||||||
github.com/mattn/go-runewidth v0.0.15 // indirect
|
github.com/mattn/go-runewidth v0.0.16 // indirect
|
||||||
github.com/miekg/pkcs11 v1.1.1 // indirect
|
github.com/miekg/pkcs11 v1.1.1 // indirect
|
||||||
github.com/mitchellh/go-homedir v1.1.0 // indirect
|
github.com/mitchellh/go-homedir v1.1.0 // indirect
|
||||||
github.com/mitchellh/go-wordwrap v1.0.1 // indirect
|
github.com/mitchellh/go-wordwrap v1.0.1 // indirect
|
||||||
github.com/moby/docker-image-spec v1.3.1 // indirect
|
github.com/moby/docker-image-spec v1.3.1 // indirect
|
||||||
|
github.com/moby/go-archive v0.1.0 // indirect
|
||||||
github.com/moby/patternmatcher v0.6.0 // indirect
|
github.com/moby/patternmatcher v0.6.0 // indirect
|
||||||
github.com/moby/spdystream v0.2.0 // indirect
|
github.com/moby/spdystream v0.5.0 // indirect
|
||||||
github.com/moby/sys/sequential v0.5.0 // indirect
|
github.com/moby/sys/sequential v0.6.0 // indirect
|
||||||
github.com/moby/sys/user v0.1.0 // indirect
|
github.com/moby/sys/user v0.4.0 // indirect
|
||||||
github.com/moby/term v0.5.0 // indirect
|
github.com/moby/sys/userns v0.1.0 // indirect
|
||||||
|
github.com/moby/term v0.5.2 // indirect
|
||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||||
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect
|
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect
|
||||||
github.com/mozillazg/docker-credential-acr-helper v0.3.0 // indirect
|
github.com/mozillazg/docker-credential-acr-helper v0.4.0 // indirect
|
||||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
||||||
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect
|
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect
|
||||||
github.com/ncruces/go-strftime v0.1.9 // indirect
|
github.com/ncruces/go-strftime v0.1.9 // indirect
|
||||||
github.com/nozzle/throttler v0.0.0-20180817012639-2ea982251481 // indirect
|
github.com/nozzle/throttler v0.0.0-20180817012639-2ea982251481 // indirect
|
||||||
github.com/oklog/ulid v1.3.1 // indirect
|
github.com/oklog/ulid v1.3.1 // indirect
|
||||||
github.com/oleiade/reflections v1.0.1 // indirect
|
github.com/oleiade/reflections v1.1.0 // indirect
|
||||||
github.com/olekukonko/tablewriter v0.0.5 // indirect
|
github.com/olekukonko/tablewriter v0.0.5 // indirect
|
||||||
|
github.com/opencontainers/go-digest v1.0.0 // indirect
|
||||||
github.com/opentracing/opentracing-go v1.2.0 // indirect
|
github.com/opentracing/opentracing-go v1.2.0 // indirect
|
||||||
github.com/pborman/uuid v1.2.1 // indirect
|
github.com/pborman/uuid v1.2.1 // indirect
|
||||||
github.com/pelletier/go-toml/v2 v2.2.2 // indirect
|
github.com/pelletier/go-toml/v2 v2.2.3 // indirect
|
||||||
github.com/peterbourgon/diskv v2.0.1+incompatible // indirect
|
github.com/peterbourgon/diskv v2.0.1+incompatible // indirect
|
||||||
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect
|
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect
|
||||||
github.com/pkg/errors v0.9.1 // indirect
|
github.com/pkg/errors v0.9.1 // indirect
|
||||||
|
github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 // indirect
|
||||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||||
github.com/prometheus/client_golang v1.19.0 // indirect
|
github.com/prometheus/client_golang v1.20.5 // indirect
|
||||||
github.com/prometheus/client_model v0.6.0 // indirect
|
github.com/prometheus/client_model v0.6.1 // indirect
|
||||||
github.com/prometheus/common v0.51.1 // indirect
|
github.com/prometheus/common v0.62.0 // indirect
|
||||||
github.com/prometheus/procfs v0.12.0 // indirect
|
github.com/prometheus/procfs v0.15.1 // indirect
|
||||||
github.com/redis/go-redis/extra/rediscmd/v9 v9.0.5 // indirect
|
github.com/redis/go-redis/extra/rediscmd/v9 v9.0.5 // indirect
|
||||||
github.com/redis/go-redis/extra/redisotel/v9 v9.0.5 // indirect
|
github.com/redis/go-redis/extra/redisotel/v9 v9.0.5 // indirect
|
||||||
github.com/redis/go-redis/v9 v9.5.1 // indirect
|
github.com/redis/go-redis/v9 v9.7.3 // indirect
|
||||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
||||||
github.com/rivo/uniseg v0.4.7 // indirect
|
github.com/rivo/uniseg v0.4.7 // indirect
|
||||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||||
github.com/ryanuber/go-glob v1.0.0 // indirect
|
github.com/ryanuber/go-glob v1.0.0 // indirect
|
||||||
github.com/sagikazarmark/locafero v0.4.0 // indirect
|
github.com/sagikazarmark/locafero v0.7.0 // indirect
|
||||||
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
|
|
||||||
github.com/sassoftware/relic v7.2.1+incompatible // indirect
|
github.com/sassoftware/relic v7.2.1+incompatible // indirect
|
||||||
github.com/secure-systems-lab/go-securesystemslib v0.8.0 // indirect
|
github.com/secure-systems-lab/go-securesystemslib v0.9.0 // indirect
|
||||||
github.com/segmentio/ksuid v1.0.4 // indirect
|
github.com/segmentio/ksuid v1.0.4 // indirect
|
||||||
github.com/shibumi/go-pathspec v1.3.0 // indirect
|
github.com/shibumi/go-pathspec v1.3.0 // indirect
|
||||||
github.com/sigstore/fulcio v1.4.5 // indirect
|
github.com/sigstore/fulcio v1.6.6 // indirect
|
||||||
github.com/sigstore/rekor v1.3.6 // indirect
|
github.com/sigstore/protobuf-specs v0.4.0 // indirect
|
||||||
github.com/sigstore/timestamp-authority v1.2.2 // indirect
|
github.com/sigstore/rekor v1.3.9 // indirect
|
||||||
|
github.com/sigstore/sigstore-go v0.7.0 // indirect
|
||||||
|
github.com/sigstore/timestamp-authority v1.2.4 // indirect
|
||||||
github.com/sirupsen/logrus v1.9.3 // indirect
|
github.com/sirupsen/logrus v1.9.3 // indirect
|
||||||
github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966 // indirect
|
github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966 // indirect
|
||||||
github.com/sourcegraph/conc v0.3.0 // indirect
|
github.com/sourcegraph/conc v0.3.0 // indirect
|
||||||
github.com/spf13/afero v1.11.0 // indirect
|
github.com/spf13/afero v1.12.0 // indirect
|
||||||
github.com/spf13/cast v1.6.0 // indirect
|
github.com/spf13/cast v1.7.1 // indirect
|
||||||
github.com/spiffe/go-spiffe/v2 v2.2.0 // indirect
|
github.com/spiffe/go-spiffe/v2 v2.5.0 // indirect
|
||||||
github.com/subosito/gotenv v1.6.0 // indirect
|
github.com/subosito/gotenv v1.6.0 // indirect
|
||||||
github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d // indirect
|
github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d // indirect
|
||||||
github.com/thales-e-security/pool v0.0.2 // indirect
|
github.com/thales-e-security/pool v0.0.2 // indirect
|
||||||
github.com/theupdateframework/go-tuf v0.7.0 // indirect
|
github.com/theupdateframework/go-tuf v0.7.0 // indirect
|
||||||
|
github.com/theupdateframework/go-tuf/v2 v2.0.2 // indirect
|
||||||
github.com/tidwall/btree v1.6.0 // indirect
|
github.com/tidwall/btree v1.6.0 // indirect
|
||||||
github.com/tidwall/buntdb v1.3.0 // indirect
|
github.com/tidwall/buntdb v1.3.0 // indirect
|
||||||
github.com/tidwall/gjson v1.16.0 // indirect
|
github.com/tidwall/gjson v1.16.0 // indirect
|
||||||
|
@ -293,52 +311,60 @@ require (
|
||||||
github.com/tjfoc/gmsm v1.4.1 // indirect
|
github.com/tjfoc/gmsm v1.4.1 // indirect
|
||||||
github.com/transparency-dev/merkle v0.0.2 // indirect
|
github.com/transparency-dev/merkle v0.0.2 // indirect
|
||||||
github.com/valyala/fasthttp v1.50.0 // indirect
|
github.com/valyala/fasthttp v1.50.0 // indirect
|
||||||
github.com/vbatts/tar-split v0.11.5 // indirect
|
github.com/vbatts/tar-split v0.11.6 // indirect
|
||||||
github.com/xanzy/go-gitlab v0.104.1 // indirect
|
github.com/x448/float16 v0.8.4 // indirect
|
||||||
github.com/xlab/treeprint v1.2.0 // indirect
|
github.com/xlab/treeprint v1.2.0 // indirect
|
||||||
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
|
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
|
||||||
github.com/zeebo/errs v1.3.0 // indirect
|
github.com/zeebo/errs v1.4.0 // indirect
|
||||||
|
gitlab.com/gitlab-org/api/client-go v0.123.0 // indirect
|
||||||
go.mongodb.org/mongo-driver v1.15.0 // indirect
|
go.mongodb.org/mongo-driver v1.15.0 // indirect
|
||||||
go.opencensus.io v0.24.0 // indirect
|
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
|
||||||
go.opentelemetry.io/contrib/exporters/autoexport v0.46.1 // indirect
|
go.opentelemetry.io/contrib/bridges/prometheus v0.57.0 // indirect
|
||||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.51.0 // indirect
|
go.opentelemetry.io/contrib/detectors/gcp v1.34.0 // indirect
|
||||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.51.0 // indirect
|
go.opentelemetry.io/contrib/exporters/autoexport v0.57.0 // indirect
|
||||||
go.opentelemetry.io/otel v1.26.0 // indirect
|
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.59.0 // indirect
|
||||||
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.44.0 // indirect
|
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0 // indirect
|
||||||
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v0.44.0 // indirect
|
go.opentelemetry.io/otel v1.34.0 // indirect
|
||||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.26.0 // indirect
|
go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.8.0 // indirect
|
||||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.26.0 // indirect
|
go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.8.0 // indirect
|
||||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.21.0 // indirect
|
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.32.0 // indirect
|
||||||
go.opentelemetry.io/otel/exporters/prometheus v0.44.0 // indirect
|
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.32.0 // indirect
|
||||||
go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v0.44.0 // indirect
|
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0 // indirect
|
||||||
go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.21.0 // indirect
|
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0 // indirect
|
||||||
go.opentelemetry.io/otel/metric v1.26.0 // indirect
|
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.33.0 // indirect
|
||||||
go.opentelemetry.io/otel/sdk v1.26.0 // indirect
|
go.opentelemetry.io/otel/exporters/prometheus v0.54.0 // indirect
|
||||||
go.opentelemetry.io/otel/sdk/metric v1.21.0 // indirect
|
go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.8.0 // indirect
|
||||||
go.opentelemetry.io/otel/trace v1.26.0 // indirect
|
go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.32.0 // indirect
|
||||||
go.opentelemetry.io/proto/otlp v1.2.0 // indirect
|
go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.32.0 // indirect
|
||||||
|
go.opentelemetry.io/otel/log v0.8.0 // indirect
|
||||||
|
go.opentelemetry.io/otel/metric v1.34.0 // indirect
|
||||||
|
go.opentelemetry.io/otel/sdk v1.34.0 // indirect
|
||||||
|
go.opentelemetry.io/otel/sdk/log v0.8.0 // indirect
|
||||||
|
go.opentelemetry.io/otel/sdk/metric v1.34.0 // indirect
|
||||||
|
go.opentelemetry.io/otel/trace v1.34.0 // indirect
|
||||||
|
go.opentelemetry.io/proto/otlp v1.5.0 // indirect
|
||||||
go.starlark.net v0.0.0-20240507195648-35fe9f26b4bc // indirect
|
go.starlark.net v0.0.0-20240507195648-35fe9f26b4bc // indirect
|
||||||
go.step.sm/crypto v0.44.8 // indirect
|
|
||||||
go.uber.org/multierr v1.11.0 // indirect
|
go.uber.org/multierr v1.11.0 // indirect
|
||||||
go.uber.org/zap v1.27.0 // indirect
|
go.uber.org/zap v1.27.0 // indirect
|
||||||
golang.org/x/mod v0.17.0 // indirect
|
golang.org/x/mod v0.23.0 // indirect
|
||||||
golang.org/x/text v0.15.0 // indirect
|
golang.org/x/sync v0.14.0 // indirect
|
||||||
golang.org/x/time v0.5.0 // indirect
|
golang.org/x/text v0.25.0 // indirect
|
||||||
golang.org/x/tools v0.21.0 // indirect
|
golang.org/x/time v0.11.0 // indirect
|
||||||
google.golang.org/genproto v0.0.0-20240506185236-b8a5c65736ae // indirect
|
golang.org/x/tools v0.30.0 // indirect
|
||||||
google.golang.org/genproto/googleapis/api v0.0.0-20240506185236-b8a5c65736ae // indirect
|
google.golang.org/genproto v0.0.0-20250303144028-a0af3efb3deb // indirect
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240506185236-b8a5c65736ae // indirect
|
google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb // indirect
|
||||||
google.golang.org/grpc v1.63.2 // indirect
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20250313205543-e70fdf4c4cb4 // indirect
|
||||||
google.golang.org/protobuf v1.34.1 // indirect
|
google.golang.org/grpc v1.71.0 // indirect
|
||||||
|
google.golang.org/protobuf v1.36.5 // indirect
|
||||||
gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect
|
gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect
|
||||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||||
k8s.io/api v0.30.0 // indirect
|
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||||
k8s.io/cli-runtime v0.30.0 // indirect
|
k8s.io/cli-runtime v0.30.0 // indirect
|
||||||
k8s.io/component-base v0.30.0 // indirect
|
k8s.io/component-base v0.30.0 // indirect
|
||||||
k8s.io/klog/v2 v2.120.1 // indirect
|
k8s.io/klog/v2 v2.130.1 // indirect
|
||||||
k8s.io/kube-openapi v0.0.0-20240430033511-f0e62f92d13f // indirect
|
k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f // indirect
|
||||||
k8s.io/kubectl v0.30.0 // indirect
|
k8s.io/kubectl v0.30.0 // indirect
|
||||||
k8s.io/utils v0.0.0-20240502163921-fe8a2dddb1d0 // indirect
|
k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 // indirect
|
||||||
modernc.org/gc/v3 v3.0.0-20240304020402-f0dba7c97c2b // indirect
|
modernc.org/gc/v3 v3.0.0-20240304020402-f0dba7c97c2b // indirect
|
||||||
modernc.org/libc v1.50.5 // indirect
|
modernc.org/libc v1.50.5 // indirect
|
||||||
modernc.org/mathutil v1.6.0 // indirect
|
modernc.org/mathutil v1.6.0 // indirect
|
||||||
|
@ -346,21 +372,10 @@ require (
|
||||||
modernc.org/sqlite v1.29.9 // indirect
|
modernc.org/sqlite v1.29.9 // indirect
|
||||||
modernc.org/strutil v1.2.0 // indirect
|
modernc.org/strutil v1.2.0 // indirect
|
||||||
modernc.org/token v1.1.0 // indirect
|
modernc.org/token v1.1.0 // indirect
|
||||||
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
|
sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 // indirect
|
||||||
sigs.k8s.io/kustomize/api v0.17.1 // indirect
|
sigs.k8s.io/kustomize/api v0.17.1 // indirect
|
||||||
sigs.k8s.io/kustomize/kyaml v0.17.0 // indirect
|
sigs.k8s.io/kustomize/kyaml v0.17.0 // indirect
|
||||||
sigs.k8s.io/release-utils v0.8.2 // indirect
|
sigs.k8s.io/release-utils v0.11.0 // indirect
|
||||||
sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect
|
sigs.k8s.io/structured-merge-diff/v4 v4.4.2 // indirect
|
||||||
sigs.k8s.io/yaml v1.4.0 // indirect
|
sigs.k8s.io/yaml v1.4.0 // indirect
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
|
||||||
github.com/fsnotify/fsnotify v1.7.0 // indirect
|
|
||||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
|
||||||
github.com/mattn/go-isatty v0.0.20
|
|
||||||
github.com/stretchr/testify v1.9.0
|
|
||||||
golang.org/x/net v0.25.0
|
|
||||||
golang.org/x/oauth2 v0.20.0
|
|
||||||
golang.org/x/sys v0.20.0
|
|
||||||
golang.org/x/term v0.20.0
|
|
||||||
)
|
|
||||||
|
|
|
@ -30,6 +30,7 @@ import (
|
||||||
"github.com/mitchellh/mapstructure"
|
"github.com/mitchellh/mapstructure"
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
|
|
||||||
|
"github.com/falcosecurity/falcoctl/internal/utils"
|
||||||
drivertype "github.com/falcosecurity/falcoctl/pkg/driver/type"
|
drivertype "github.com/falcosecurity/falcoctl/pkg/driver/type"
|
||||||
"github.com/falcosecurity/falcoctl/pkg/oci"
|
"github.com/falcosecurity/falcoctl/pkg/oci"
|
||||||
)
|
)
|
||||||
|
@ -137,10 +138,6 @@ const (
|
||||||
DriverNameKey = "driver.name"
|
DriverNameKey = "driver.name"
|
||||||
// DriverHostRootKey is the Viper key for the driver host root.
|
// DriverHostRootKey is the Viper key for the driver host root.
|
||||||
DriverHostRootKey = "driver.hostRoot"
|
DriverHostRootKey = "driver.hostRoot"
|
||||||
// DriverNamespaceKey is the Viper key for the driver config namespace flag.
|
|
||||||
DriverNamespaceKey = "driver.config.namespace"
|
|
||||||
// DriverUpdateFalcoKey is the Viper key for the driver config update-falco flag.
|
|
||||||
DriverUpdateFalcoKey = "driver.config.update-falco"
|
|
||||||
falcoHostRootEnvKey = "HOST_ROOT"
|
falcoHostRootEnvKey = "HOST_ROOT"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -395,8 +392,14 @@ func basicAuthListHookFunc() mapstructure.DecodeHookFuncType {
|
||||||
return data, fmt.Errorf("not valid token %q", token)
|
return data, fmt.Errorf("not valid token %q", token)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Allow to have the registry expressed as a ref, but actually extract it.
|
||||||
|
registry, err := utils.GetRegistryFromRef(values[0])
|
||||||
|
if err != nil {
|
||||||
|
registry = values[0]
|
||||||
|
}
|
||||||
|
|
||||||
auths[i] = BasicAuth{
|
auths[i] = BasicAuth{
|
||||||
Registry: values[0],
|
Registry: registry,
|
||||||
User: values[1],
|
User: values[1],
|
||||||
Password: values[2],
|
Password: values[2],
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
// Copyright (C) 2023 The Falco Authors
|
// Copyright (C) 2025 The Falco Authors
|
||||||
//
|
//
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with the License.
|
// you may not use this file except in compliance with the License.
|
||||||
|
@ -203,52 +203,83 @@ func (f *Follower) follow(ctx context.Context) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Install the artifacts if necessary.
|
// Move files to their destination
|
||||||
for _, path := range filePaths {
|
if err := f.moveFiles(filePaths, dstDir); err != nil {
|
||||||
baseName := filepath.Base(path)
|
|
||||||
f.logger.Debug("Installing file", f.logger.Args("followerName", f.ref, "fileName", baseName))
|
|
||||||
dstPath := filepath.Join(dstDir, baseName)
|
|
||||||
// Check if the file exists.
|
|
||||||
f.logger.Debug("Checking if file already exists", f.logger.Args("followerName", f.ref, "fileName", baseName, "directory", dstDir))
|
|
||||||
exists, err := utils.FileExists(dstPath)
|
|
||||||
if err != nil {
|
|
||||||
f.logger.Error("Unable to check existence for file", f.logger.Args("followerName", f.ref, "fileName", baseName, "reason", err.Error()))
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
f.logger.Info("Artifact correctly installed",
|
||||||
|
f.logger.Args("followerName", f.ref, "artifactName", f.ref, "type", res.Type, "digest", res.Digest, "directory", dstDir))
|
||||||
|
f.currentDigest = desc.Digest.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
// moveFiles moves files from their temporary location to the destination directory.
|
||||||
|
// It preserves the directory structure relative to the temporary directory.
|
||||||
|
// For example, if a file is at "tmpDir/subdir/file.yaml", it will be moved to
|
||||||
|
// "dstDir/subdir/file.yaml". This ensures that files in subdirectories are moved
|
||||||
|
// correctly as individual files, not as entire directories.
|
||||||
|
func (f *Follower) moveFiles(filePaths []string, dstDir string) error {
|
||||||
|
// Install the artifacts if necessary.
|
||||||
|
for _, path := range filePaths {
|
||||||
|
// Get the relative path from the temporary directory to preserve directory structure
|
||||||
|
relPath, err := filepath.Rel(f.tmpDir, path)
|
||||||
|
if err != nil {
|
||||||
|
f.logger.Error("Unable to get relative path", f.logger.Args("followerName", f.ref, "path", path, "reason", err.Error()))
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
dstPath := filepath.Join(dstDir, relPath)
|
||||||
|
// Ensure the parent directory exists
|
||||||
|
if err := os.MkdirAll(filepath.Dir(dstPath), 0o750); err != nil {
|
||||||
|
f.logger.Error("Unable to create destination directory", f.logger.Args(
|
||||||
|
"followerName", f.ref,
|
||||||
|
"directory", filepath.Dir(dstPath),
|
||||||
|
"reason", err.Error(),
|
||||||
|
))
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
f.logger.Debug("Installing file", f.logger.Args("followerName", f.ref, "path", relPath))
|
||||||
|
// Check if the file exists.
|
||||||
|
f.logger.Debug("Checking if file already exists", f.logger.Args("followerName", f.ref, "path", relPath, "directory", dstDir))
|
||||||
|
exists, err := utils.FileExists(dstPath)
|
||||||
|
if err != nil {
|
||||||
|
f.logger.Error("Unable to check existence for file", f.logger.Args("followerName", f.ref, "path", relPath, "reason", err.Error()))
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
if !exists {
|
if !exists {
|
||||||
f.logger.Debug("Moving file", f.logger.Args("followerName", f.ref, "fileName", baseName, "destDirectory", dstDir))
|
f.logger.Debug("Moving file", f.logger.Args("followerName", f.ref, "path", relPath, "destDirectory", dstDir))
|
||||||
if err = utils.Move(path, dstPath); err != nil {
|
if err = utils.Move(path, dstPath); err != nil {
|
||||||
f.logger.Error("Unable to move file", f.logger.Args("followerName", f.ref, "fileName", baseName, "destDirectory", dstDir, "reason", err.Error()))
|
f.logger.Error("Unable to move file", f.logger.Args("followerName", f.ref, "path", relPath, "destDirectory", dstDir, "reason", err.Error()))
|
||||||
return
|
return err
|
||||||
}
|
}
|
||||||
f.logger.Debug("File correctly installed", f.logger.Args("followerName", f.ref, "path", path))
|
f.logger.Debug("File correctly installed", f.logger.Args("followerName", f.ref, "path", path))
|
||||||
// It's done, move to the next file.
|
// It's done, move to the next file.
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
f.logger.Debug(fmt.Sprintf("file %q already exists in %q, checking if it is equal to the existing one", baseName, dstDir),
|
|
||||||
|
f.logger.Debug(fmt.Sprintf("file %q already exists in %q, checking if it is equal to the existing one", relPath, dstDir),
|
||||||
f.logger.Args("followerName", f.ref))
|
f.logger.Args("followerName", f.ref))
|
||||||
|
|
||||||
// Check if the files are equal.
|
// Check if the files are equal.
|
||||||
eq, err := equal([]string{path, dstPath})
|
eq, err := equal([]string{path, dstPath})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
f.logger.Error("Unable to compare files", f.logger.Args("followerName", f.ref, "newFile", path, "existingFile", dstPath, "reason", err.Error()))
|
f.logger.Error("Unable to compare files", f.logger.Args("followerName", f.ref, "existingFile", dstPath, "reason", err.Error()))
|
||||||
return
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if !eq {
|
if !eq {
|
||||||
f.logger.Debug(fmt.Sprintf("Overwriting file %q with file %q", dstPath, path), f.logger.Args("followerName", f.ref))
|
f.logger.Debug(fmt.Sprintf("Overwriting file %q with file %q", dstPath, path), f.logger.Args("followerName", f.ref))
|
||||||
if err = utils.Move(path, dstPath); err != nil {
|
if err = utils.Move(path, dstPath); err != nil {
|
||||||
f.logger.Error("Unable to overwrite file", f.logger.Args("followerName", f.ref, "existingFile", dstPath, "reason", err.Error()))
|
f.logger.Error("Unable to overwrite file", f.logger.Args("followerName", f.ref, "existingFile", dstPath, "reason", err.Error()))
|
||||||
return
|
return err
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
f.logger.Debug("The two file are equal, nothing to be done")
|
f.logger.Debug("The two file are equal, nothing to be done")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return nil
|
||||||
f.logger.Info("Artifact correctly installed",
|
|
||||||
f.logger.Args("followerName", f.ref, "artifactName", f.ref, "type", res.Type, "digest", res.Digest, "directory", dstDir))
|
|
||||||
f.currentDigest = desc.Digest.String()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// pull downloads, extracts, and installs the artifact.
|
// pull downloads, extracts, and installs the artifact.
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
// Copyright (C) 2024 The Falco Authors
|
// Copyright (C) 2025 The Falco Authors
|
||||||
//
|
//
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with the License.
|
// you may not use this file except in compliance with the License.
|
||||||
|
@ -17,6 +17,7 @@ package follower
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"os"
|
"os"
|
||||||
|
"path/filepath"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/pterm/pterm"
|
"github.com/pterm/pterm"
|
||||||
|
@ -135,3 +136,170 @@ func TestCheckRequirements(t *testing.T) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestMoveFiles(t *testing.T) {
|
||||||
|
type testFile struct {
|
||||||
|
path string
|
||||||
|
content string
|
||||||
|
replace bool
|
||||||
|
}
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
files []testFile
|
||||||
|
existing []testFile
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "basic file at root",
|
||||||
|
files: []testFile{
|
||||||
|
{
|
||||||
|
path: "file1.yaml",
|
||||||
|
content: "content1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "file in subdirectory",
|
||||||
|
files: []testFile{
|
||||||
|
{
|
||||||
|
path: "subdir/file2.yaml",
|
||||||
|
content: "content2",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "multiple files in different directories",
|
||||||
|
files: []testFile{
|
||||||
|
{
|
||||||
|
path: "file1.yaml",
|
||||||
|
content: "content1",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "subdir/file2.yaml",
|
||||||
|
content: "content2",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "subdir/nested/file3.yaml",
|
||||||
|
content: "content3",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "existing file with identical content",
|
||||||
|
files: []testFile{
|
||||||
|
{
|
||||||
|
path: "file1.yaml",
|
||||||
|
content: "content1",
|
||||||
|
replace: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
existing: []testFile{
|
||||||
|
{
|
||||||
|
path: "file1.yaml",
|
||||||
|
content: "content1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "existing file with different content",
|
||||||
|
files: []testFile{
|
||||||
|
{
|
||||||
|
path: "file1.yaml",
|
||||||
|
content: "new content",
|
||||||
|
replace: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
existing: []testFile{
|
||||||
|
{
|
||||||
|
path: "file1.yaml",
|
||||||
|
content: "old content",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "mix of new and existing files",
|
||||||
|
files: []testFile{
|
||||||
|
{
|
||||||
|
path: "file1.yaml",
|
||||||
|
content: "content1",
|
||||||
|
replace: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "subdir/file2.yaml",
|
||||||
|
content: "new content2",
|
||||||
|
replace: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
existing: []testFile{
|
||||||
|
{
|
||||||
|
path: "file1.yaml",
|
||||||
|
content: "content1",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "subdir/file2.yaml",
|
||||||
|
content: "old content2",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
tmpDir, err := os.MkdirTemp("", "falcoctl-test-*")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
defer os.RemoveAll(tmpDir)
|
||||||
|
|
||||||
|
dstDir, err := os.MkdirTemp("", "falcoctl-dst-*")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
defer os.RemoveAll(dstDir)
|
||||||
|
|
||||||
|
// Setup existing files
|
||||||
|
for _, ef := range tt.existing {
|
||||||
|
dstPath := filepath.Join(dstDir, ef.path)
|
||||||
|
err = os.MkdirAll(filepath.Dir(dstPath), 0o755)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
err = os.WriteFile(dstPath, []byte(ef.content), 0o644)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
f, err := New("test-registry/test-ref", output.NewPrinter(pterm.LogLevelDebug, pterm.LogFormatterJSON, os.Stdout), &Config{
|
||||||
|
RulesfilesDir: dstDir,
|
||||||
|
TmpDir: tmpDir,
|
||||||
|
})
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
var paths []string
|
||||||
|
for _, tf := range tt.files {
|
||||||
|
fullPath := filepath.Join(f.tmpDir, tf.path)
|
||||||
|
err = os.MkdirAll(filepath.Dir(fullPath), 0o755)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
err = os.WriteFile(fullPath, []byte(tf.content), 0o644)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
paths = append(paths, fullPath)
|
||||||
|
}
|
||||||
|
|
||||||
|
f.currentDigest = "test-digest"
|
||||||
|
err = f.moveFiles(paths, dstDir)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
for _, tf := range tt.files {
|
||||||
|
dstPath := filepath.Join(dstDir, tf.path)
|
||||||
|
_, err = os.Stat(dstPath)
|
||||||
|
assert.NoError(t, err, "file should exist at %s", dstPath)
|
||||||
|
|
||||||
|
content, err := os.ReadFile(dstPath)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, tf.content, string(content), "file content should match at %s", dstPath)
|
||||||
|
|
||||||
|
// For files marked as replace=false, verify they have identical content with existing files
|
||||||
|
if !tf.replace {
|
||||||
|
for _, ef := range tt.existing {
|
||||||
|
if ef.path == tf.path {
|
||||||
|
assert.Equal(t, ef.content, string(content), "file content should not change when replace=false: %s", dstPath)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -28,7 +28,7 @@ import (
|
||||||
// Login checks if passed gcp credentials are correct.
|
// Login checks if passed gcp credentials are correct.
|
||||||
func Login(ctx context.Context, reg string) error {
|
func Login(ctx context.Context, reg string) error {
|
||||||
// Check that we can find a valid token source using GCE or ApplicationDefault.
|
// Check that we can find a valid token source using GCE or ApplicationDefault.
|
||||||
ts, err := google.DefaultTokenSource(ctx)
|
ts, err := google.DefaultTokenSource(ctx, "https://www.googleapis.com/auth/cloud-platform")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("wrong GCP token source, unable to find a valid source: %w", err)
|
return fmt.Errorf("wrong GCP token source, unable to find a valid source: %w", err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,7 +31,7 @@ import (
|
||||||
const TmpDirPrefix = "falcoctl-registry-push-"
|
const TmpDirPrefix = "falcoctl-registry-push-"
|
||||||
|
|
||||||
// CreateTarGzArchive compresses and saves in a tar archive the passed file.
|
// CreateTarGzArchive compresses and saves in a tar archive the passed file.
|
||||||
func CreateTarGzArchive(dir, path string) (file string, err error) {
|
func CreateTarGzArchive(dir, path string, stripComponents bool) (file string, err error) {
|
||||||
cleanedPath := filepath.Clean(path)
|
cleanedPath := filepath.Clean(path)
|
||||||
if dir == "" {
|
if dir == "" {
|
||||||
dir = TmpDirPrefix
|
dir = TmpDirPrefix
|
||||||
|
@ -96,13 +96,13 @@ func CreateTarGzArchive(dir, path string) (file string, err error) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return copyToTarGz(path, tw, info)
|
return copyToTarGz(path, tw, info, stripComponents)
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if err = copyToTarGz(path, tw, fInfo); err != nil {
|
if err = copyToTarGz(path, tw, fInfo, stripComponents); err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -110,9 +110,17 @@ func CreateTarGzArchive(dir, path string) (file string, err error) {
|
||||||
return outFile.Name(), err
|
return outFile.Name(), err
|
||||||
}
|
}
|
||||||
|
|
||||||
func copyToTarGz(path string, tw *tar.Writer, info fs.FileInfo) error {
|
func copyToTarGz(path string, tw *tar.Writer, info fs.FileInfo, stripComponents bool) error {
|
||||||
|
var headerName string
|
||||||
|
|
||||||
|
if stripComponents {
|
||||||
|
headerName = filepath.Base(path)
|
||||||
|
} else {
|
||||||
|
headerName = path
|
||||||
|
}
|
||||||
|
|
||||||
header := &tar.Header{
|
header := &tar.Header{
|
||||||
Name: path,
|
Name: headerName,
|
||||||
Size: info.Size(),
|
Size: info.Size(),
|
||||||
Mode: int64(info.Mode()),
|
Mode: int64(info.Mode()),
|
||||||
Typeflag: tar.TypeReg,
|
Typeflag: tar.TypeReg,
|
||||||
|
|
|
@ -36,25 +36,25 @@ func TestCreateTarGzArchiveFile(t *testing.T) {
|
||||||
dir := t.TempDir()
|
dir := t.TempDir()
|
||||||
f1, err := os.Create(filepath.Join(dir, filename1))
|
f1, err := os.Create(filepath.Join(dir, filename1))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf(err.Error())
|
t.Fatal(err.Error())
|
||||||
}
|
}
|
||||||
defer f1.Close()
|
defer f1.Close()
|
||||||
|
|
||||||
tarball, err := CreateTarGzArchive(tmpPrefix, filepath.Join(dir, filename1))
|
tarball, err := CreateTarGzArchive(tmpPrefix, filepath.Join(dir, filename1), false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf(err.Error())
|
t.Fatal(err.Error())
|
||||||
}
|
}
|
||||||
defer os.RemoveAll(filepath.Dir(tarball))
|
defer os.RemoveAll(filepath.Dir(tarball))
|
||||||
|
|
||||||
file, err := os.Open(tarball)
|
file, err := os.Open(tarball)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf(err.Error())
|
t.Fatal(err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
paths, err := listHeaders(file)
|
paths, err := listHeaders(file)
|
||||||
fmt.Println(paths)
|
fmt.Println(paths)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf(err.Error())
|
t.Fatal(err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(paths) != 1 {
|
if len(paths) != 1 {
|
||||||
|
@ -67,6 +67,41 @@ func TestCreateTarGzArchiveFile(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestCreateTarGzArchiveFileStripComponents(t *testing.T) {
|
||||||
|
dir := t.TempDir()
|
||||||
|
f1, err := os.Create(filepath.Join(dir, filename1))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err.Error())
|
||||||
|
}
|
||||||
|
defer f1.Close()
|
||||||
|
|
||||||
|
tarball, err := CreateTarGzArchive(tmpPrefix, filepath.Join(dir, filename1), true)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err.Error())
|
||||||
|
}
|
||||||
|
defer os.RemoveAll(filepath.Dir(tarball))
|
||||||
|
|
||||||
|
file, err := os.Open(tarball)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
paths, err := listHeaders(file)
|
||||||
|
fmt.Println(paths)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(paths) != 1 {
|
||||||
|
t.Fatalf("Expected 1 path, got %d", len(paths))
|
||||||
|
}
|
||||||
|
|
||||||
|
base := paths[0]
|
||||||
|
if base != filename1 {
|
||||||
|
t.Errorf("Expected file1, got %s", base)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestCreateTarGzArchiveDir(t *testing.T) {
|
func TestCreateTarGzArchiveDir(t *testing.T) {
|
||||||
// Test that we can compress directories
|
// Test that we can compress directories
|
||||||
dir := t.TempDir()
|
dir := t.TempDir()
|
||||||
|
@ -74,30 +109,30 @@ func TestCreateTarGzArchiveDir(t *testing.T) {
|
||||||
// add some files
|
// add some files
|
||||||
f1, err := os.Create(filepath.Join(dir, filename1))
|
f1, err := os.Create(filepath.Join(dir, filename1))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf(err.Error())
|
t.Fatal(err.Error())
|
||||||
}
|
}
|
||||||
defer f1.Close()
|
defer f1.Close()
|
||||||
f2, err := os.Create(filepath.Join(dir, filename2))
|
f2, err := os.Create(filepath.Join(dir, filename2))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf(err.Error())
|
t.Fatal(err.Error())
|
||||||
}
|
}
|
||||||
defer f2.Close()
|
defer f2.Close()
|
||||||
|
|
||||||
tarball, err := CreateTarGzArchive(tmpPrefix, dir)
|
tarball, err := CreateTarGzArchive(tmpPrefix, dir, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf(err.Error())
|
t.Fatal(err.Error())
|
||||||
}
|
}
|
||||||
defer os.RemoveAll(filepath.Dir(tarball))
|
defer os.RemoveAll(filepath.Dir(tarball))
|
||||||
|
|
||||||
file, err := os.Open(tarball)
|
file, err := os.Open(tarball)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf(err.Error())
|
t.Fatal(err.Error())
|
||||||
}
|
}
|
||||||
defer file.Close()
|
defer file.Close()
|
||||||
|
|
||||||
paths, err := listHeaders(file)
|
paths, err := listHeaders(file)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf(err.Error())
|
t.Fatal(err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(paths) != 3 {
|
if len(paths) != 3 {
|
||||||
|
|
|
@ -1,46 +0,0 @@
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
// Copyright (C) 2023 The Falco Authors
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// 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.
|
|
||||||
|
|
||||||
package utils
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bufio"
|
|
||||||
"os"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"golang.org/x/term"
|
|
||||||
|
|
||||||
"github.com/falcosecurity/falcoctl/pkg/output"
|
|
||||||
)
|
|
||||||
|
|
||||||
// GetCredentials is used to retrieve username and password from standard input.
|
|
||||||
func GetCredentials(p *output.Printer) (username, password string, err error) {
|
|
||||||
reader := bufio.NewReader(os.Stdin)
|
|
||||||
|
|
||||||
p.DefaultText.Print(p.FormatTitleAsLoggerInfo("Enter username:"))
|
|
||||||
username, err = reader.ReadString('\n')
|
|
||||||
if err != nil {
|
|
||||||
return "", "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
p.Logger.Info("Enter password: ")
|
|
||||||
bytePassword, err := term.ReadPassword(int(os.Stdin.Fd()))
|
|
||||||
if err != nil {
|
|
||||||
return "", "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
password = string(bytePassword)
|
|
||||||
return strings.TrimSpace(username), strings.TrimSpace(password), nil
|
|
||||||
}
|
|
|
@ -86,7 +86,6 @@ func ExtractTarGz(ctx context.Context, gzipStream io.Reader, destDir string, str
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
info := header.FileInfo()
|
info := header.FileInfo()
|
||||||
files = append(files, path)
|
|
||||||
|
|
||||||
switch header.Typeflag {
|
switch header.Typeflag {
|
||||||
case tar.TypeDir:
|
case tar.TypeDir:
|
||||||
|
@ -106,6 +105,7 @@ func ExtractTarGz(ctx context.Context, gzipStream io.Reader, destDir string, str
|
||||||
if err = outFile.Close(); err != nil {
|
if err = outFile.Close(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
files = append(files, path)
|
||||||
case tar.TypeLink:
|
case tar.TypeLink:
|
||||||
name := header.Linkname
|
name := header.Linkname
|
||||||
if stripPathComponents > 0 {
|
if stripPathComponents > 0 {
|
||||||
|
|
|
@ -69,7 +69,7 @@ func (c *cos) customizeBuild(ctx context.Context,
|
||||||
}
|
}
|
||||||
printer.Logger.Info("COS detected, using COS kernel headers.", printer.Logger.Args("build ID", c.buildID))
|
printer.Logger.Info("COS detected, using COS kernel headers.", printer.Logger.Args("build ID", c.buildID))
|
||||||
bpfKernelSrcURL := fmt.Sprintf("https://storage.googleapis.com/cos-tools/%s/kernel-headers.tgz", c.buildID)
|
bpfKernelSrcURL := fmt.Sprintf("https://storage.googleapis.com/cos-tools/%s/kernel-headers.tgz", c.buildID)
|
||||||
kr.Extraversion = "+"
|
|
||||||
env, err := downloadKernelSrc(ctx, printer, &kr, bpfKernelSrcURL, 0)
|
env, err := downloadKernelSrc(ctx, printer, &kr, bpfKernelSrcURL, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
|
@ -169,6 +169,7 @@ func Build(ctx context.Context,
|
||||||
driverName string,
|
driverName string,
|
||||||
driverType drivertype.DriverType,
|
driverType drivertype.DriverType,
|
||||||
driverVer string,
|
driverVer string,
|
||||||
|
downloadHeaders bool,
|
||||||
) (string, error) {
|
) (string, error) {
|
||||||
printer.Logger.Info("Trying to compile the requested driver")
|
printer.Logger.Info("Trying to compile the requested driver")
|
||||||
driverFileName := toFilename(d, &kr, driverName, driverType)
|
driverFileName := toFilename(d, &kr, driverName, driverType)
|
||||||
|
@ -190,7 +191,6 @@ func Build(ctx context.Context,
|
||||||
// Disable automatic kernel headers fetching
|
// Disable automatic kernel headers fetching
|
||||||
// if customizeBuild already retrieved kernel headers for us
|
// if customizeBuild already retrieved kernel headers for us
|
||||||
// (and has set the KernelDirEnv key)
|
// (and has set the KernelDirEnv key)
|
||||||
downloadHeaders := true
|
|
||||||
if _, ok := env[drivertype.KernelDirEnv]; ok {
|
if _, ok := env[drivertype.KernelDirEnv]; ok {
|
||||||
downloadHeaders = false
|
downloadHeaders = false
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,9 +27,6 @@ import (
|
||||||
"github.com/falcosecurity/falcoctl/pkg/output"
|
"github.com/falcosecurity/falcoctl/pkg/output"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TypeBpf is the string for the bpf driver type.
|
|
||||||
const TypeBpf = "ebpf"
|
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
driverTypes[TypeBpf] = &bpf{}
|
driverTypes[TypeBpf] = &bpf{}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
// Copyright (C) 2025 The Falco Authors
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
|
||||||
|
package drivertype
|
||||||
|
|
||||||
|
const (
|
||||||
|
// TypeKmod is the string for the kernel module driver type.
|
||||||
|
TypeKmod = "kmod"
|
||||||
|
// TypeModernBpf is the string for the modern bpf driver type.
|
||||||
|
TypeModernBpf = "modern_ebpf"
|
||||||
|
// TypeBpf is the string for the bpf driver type.
|
||||||
|
TypeBpf = "ebpf"
|
||||||
|
)
|
|
@ -30,8 +30,6 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// TypeKmod is the string for the bpf driver type.
|
|
||||||
TypeKmod = "kmod"
|
|
||||||
maxRmmodWait = 10
|
maxRmmodWait = 10
|
||||||
rmmodWaitTime = 5 * time.Second
|
rmmodWaitTime = 5 * time.Second
|
||||||
)
|
)
|
||||||
|
|
|
@ -13,11 +13,12 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
|
//go:build linux
|
||||||
|
|
||||||
package drivertype
|
package drivertype
|
||||||
|
|
||||||
import (
|
import (
|
||||||
// Needed for go:linkname to be able to access a private function from cilium/ebpf/features.
|
_ "unsafe" // Needed for go:linkname to be able to access a private function from cilium/ebpf/features.
|
||||||
_ "unsafe"
|
|
||||||
|
|
||||||
"github.com/cilium/ebpf"
|
"github.com/cilium/ebpf"
|
||||||
"github.com/cilium/ebpf/features"
|
"github.com/cilium/ebpf/features"
|
||||||
|
@ -27,9 +28,6 @@ import (
|
||||||
"github.com/falcosecurity/falcoctl/pkg/output"
|
"github.com/falcosecurity/falcoctl/pkg/output"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TypeModernBpf is the string for the bpf driver type.
|
|
||||||
const TypeModernBpf = "modern_ebpf"
|
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
driverTypes[TypeModernBpf] = &modernBpf{}
|
driverTypes[TypeModernBpf] = &modernBpf{}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,7 @@ import (
|
||||||
"github.com/falcosecurity/falcoctl/pkg/index/fetch/file"
|
"github.com/falcosecurity/falcoctl/pkg/index/fetch/file"
|
||||||
"github.com/falcosecurity/falcoctl/pkg/index/fetch/gcs"
|
"github.com/falcosecurity/falcoctl/pkg/index/fetch/gcs"
|
||||||
"github.com/falcosecurity/falcoctl/pkg/index/fetch/http"
|
"github.com/falcosecurity/falcoctl/pkg/index/fetch/http"
|
||||||
|
"github.com/falcosecurity/falcoctl/pkg/index/fetch/s3"
|
||||||
"github.com/falcosecurity/falcoctl/pkg/index/index"
|
"github.com/falcosecurity/falcoctl/pkg/index/index"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -48,12 +49,14 @@ func NewFetcher() *Fetcher {
|
||||||
"https": http.Fetch,
|
"https": http.Fetch,
|
||||||
"gcs": gcs.Fetch,
|
"gcs": gcs.Fetch,
|
||||||
"file": file.Fetch,
|
"file": file.Fetch,
|
||||||
|
"s3": s3.Fetch,
|
||||||
},
|
},
|
||||||
schemeDefaultBackends: map[string]string{
|
schemeDefaultBackends: map[string]string{
|
||||||
"http": "http",
|
"http": "http",
|
||||||
"https": "https",
|
"https": "https",
|
||||||
"gs": "gcs",
|
"gs": "gcs",
|
||||||
"file": "file",
|
"file": "file",
|
||||||
|
"s3": "s3",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
// Copyright (C) 2024 The Falco Authors
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
// Package s3 implements all the logic for fetching indexes from AWS S3.
|
||||||
|
package s3
|
|
@ -0,0 +1,63 @@
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
// Copyright (C) 2024 The Falco Authors
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
package s3
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
|
||||||
|
"github.com/aws/aws-sdk-go-v2/aws"
|
||||||
|
"github.com/aws/aws-sdk-go-v2/config"
|
||||||
|
"github.com/aws/aws-sdk-go-v2/service/s3"
|
||||||
|
|
||||||
|
indexConfig "github.com/falcosecurity/falcoctl/pkg/index/config"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Fetch fetches the raw index file from an S3 object.
|
||||||
|
func Fetch(ctx context.Context, conf *indexConfig.Entry) ([]byte, error) {
|
||||||
|
o, err := s3ObjectFromURI(conf.URL)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a new AWS config
|
||||||
|
cfg, err := config.LoadDefaultConfig(context.TODO())
|
||||||
|
if err != nil {
|
||||||
|
// handle error
|
||||||
|
return nil, fmt.Errorf("unable to create AWS config: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
svc := s3.NewFromConfig(cfg)
|
||||||
|
|
||||||
|
// Get the object from S3
|
||||||
|
res, err := svc.GetObject(ctx, &s3.GetObjectInput{
|
||||||
|
Bucket: aws.String(o.Bucket),
|
||||||
|
Key: aws.String(o.Key),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("unable to get S3 object: %w", err)
|
||||||
|
}
|
||||||
|
defer res.Body.Close()
|
||||||
|
|
||||||
|
// Read the object data
|
||||||
|
bytes, err := io.ReadAll(res.Body)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("error reading S3 object: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return bytes, nil
|
||||||
|
}
|
|
@ -0,0 +1,55 @@
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
// Copyright (C) 2024 The Falco Authors
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
package s3
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net/url"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
const s3Scheme = "s3"
|
||||||
|
|
||||||
|
// s3Object represents an S3 object with its bucket and key.
|
||||||
|
type s3Object struct {
|
||||||
|
Bucket string
|
||||||
|
Key string
|
||||||
|
}
|
||||||
|
|
||||||
|
// s3ObjectFromURI parses S3 URIs (s3://<bucket>/<object>) and returns a s3Object.
|
||||||
|
func s3ObjectFromURI(uri string) (*s3Object, error) {
|
||||||
|
parsedURI, err := url.Parse(uri)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("unable to parse URI: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !strings.EqualFold(parsedURI.Scheme, s3Scheme) {
|
||||||
|
return nil, fmt.Errorf("invalid S3 URI: scheme should be '%s' but got '%s'", s3Scheme, parsedURI.Scheme)
|
||||||
|
}
|
||||||
|
|
||||||
|
if parsedURI.Host == "" {
|
||||||
|
return nil, fmt.Errorf("invalid S3 URI: missing bucket name")
|
||||||
|
}
|
||||||
|
|
||||||
|
if parsedURI.Path == "" {
|
||||||
|
return nil, fmt.Errorf("invalid S3 URI: missing object name")
|
||||||
|
}
|
||||||
|
|
||||||
|
return &s3Object{
|
||||||
|
Bucket: parsedURI.Host,
|
||||||
|
Key: parsedURI.Path[1:], // Remove the leading slash
|
||||||
|
}, nil
|
||||||
|
}
|
|
@ -55,7 +55,7 @@ func GCPCredential(ctx context.Context, reg string) (auth.Credential, error) {
|
||||||
|
|
||||||
// load saved tokenSource or saves it
|
// load saved tokenSource or saves it
|
||||||
if SavedTokenSource == nil {
|
if SavedTokenSource == nil {
|
||||||
tokenSource, err = google.DefaultTokenSource(ctx)
|
tokenSource, err = google.DefaultTokenSource(ctx, "https://www.googleapis.com/auth/cloud-platform")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return auth.EmptyCredential, fmt.Errorf("error while trying to identify a GCP TokenSource %w", err)
|
return auth.EmptyCredential, fmt.Errorf("error while trying to identify a GCP TokenSource %w", err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,7 +64,7 @@ func WithPlainHTTP(plainHTTP bool) func(r *Repository) {
|
||||||
func (r *Repository) Tags(ctx context.Context) ([]string, error) {
|
func (r *Repository) Tags(ctx context.Context) ([]string, error) {
|
||||||
var result []string
|
var result []string
|
||||||
var tagRetriever = func(tags []string) error {
|
var tagRetriever = func(tags []string) error {
|
||||||
result = tags
|
result = append(result, tags...)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -88,8 +88,8 @@ func HumanReadableMediaType(s string) string {
|
||||||
return string(Asset)
|
return string(Asset)
|
||||||
}
|
}
|
||||||
|
|
||||||
// should never happen
|
// If we do not have a match for a well known mediaType then we return the original mediaType.
|
||||||
return ""
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
// ArtifactTypeSlice is a slice of ArtifactType, can be passed as comma separated values.
|
// ArtifactTypeSlice is a slice of ArtifactType, can be passed as comma separated values.
|
||||||
|
|
|
@ -43,7 +43,7 @@ import (
|
||||||
"github.com/go-oauth2/oauth2/v4/models"
|
"github.com/go-oauth2/oauth2/v4/models"
|
||||||
"github.com/go-oauth2/oauth2/v4/server"
|
"github.com/go-oauth2/oauth2/v4/server"
|
||||||
"github.com/go-oauth2/oauth2/v4/store"
|
"github.com/go-oauth2/oauth2/v4/store"
|
||||||
"github.com/golang-jwt/jwt"
|
"github.com/golang-jwt/jwt/v5"
|
||||||
)
|
)
|
||||||
|
|
||||||
// RegistryTLSConfig maintains all certificate informations.
|
// RegistryTLSConfig maintains all certificate informations.
|
||||||
|
|
Loading…
Reference in New Issue