mirror of
https://github.com/projectcapsule/capsule.git
synced 2026-02-22 13:54:06 +00:00
Compare commits
25 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
67b5c3e880 | ||
|
|
1f4fcce977 | ||
|
|
100454d303 | ||
|
|
074eb40734 | ||
|
|
1336ebe9c3 | ||
|
|
13d37b28be | ||
|
|
ca9323518f | ||
|
|
e1f47feade | ||
|
|
24543aa13a | ||
|
|
73cc0917ee | ||
|
|
06614c9d86 | ||
|
|
b3bfead6a0 | ||
|
|
1b415d4931 | ||
|
|
0ab0135977 | ||
|
|
b22adc424f | ||
|
|
a31259ad9b | ||
|
|
13208208d6 | ||
|
|
dda7393c3f | ||
|
|
c7dbb44aaf | ||
|
|
1e3b62bf83 | ||
|
|
30168db4fa | ||
|
|
9d6d68c519 | ||
|
|
3bac2b6f0e | ||
|
|
cdca11f0b9 | ||
|
|
10eeecc6a3 |
4
.github/actions/setup-caches/action.yaml
vendored
4
.github/actions/setup-caches/action.yaml
vendored
@@ -9,11 +9,11 @@ inputs:
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
|
||||
- uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4
|
||||
with:
|
||||
path: ~/go/pkg/mod
|
||||
key: ${{ runner.os }}-go-pkg-mod-${{ hashFiles('**/go.sum') }}-${{ hashFiles('Makefile') }}
|
||||
- uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
|
||||
- uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4
|
||||
if: ${{ inputs.build-cache-key }}
|
||||
with:
|
||||
path: ~/.cache/go-build
|
||||
|
||||
2
.github/workflows/check-actions.yml
vendored
2
.github/workflows/check-actions.yml
vendored
@@ -15,7 +15,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
- name: Ensure SHA pinned actions
|
||||
uses: zgosalvez/github-actions-ensure-sha-pinned-actions@fc87bb5b5a97953d987372e74478de634726b3e5 # v3.0.25
|
||||
with:
|
||||
|
||||
2
.github/workflows/check-commit.yml
vendored
2
.github/workflows/check-commit.yml
vendored
@@ -16,7 +16,7 @@ jobs:
|
||||
commit_lint:
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: wagoid/commitlint-github-action@b948419dd99f3fd78a6548d48f94e3df7f6bf3ed # v6.2.1
|
||||
|
||||
2
.github/workflows/check-pr.yml
vendored
2
.github/workflows/check-pr.yml
vendored
@@ -15,7 +15,7 @@ jobs:
|
||||
name: Validate PR title
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: amannn/action-semantic-pull-request@335288255954904a41ddda8947c8f2c844b8bfeb
|
||||
- uses: amannn/action-semantic-pull-request@a46a7c8dc4bb34503174eba2f2f7ef80dffc8ed7
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
|
||||
10
.github/workflows/coverage.yml
vendored
10
.github/workflows/coverage.yml
vendored
@@ -19,7 +19,7 @@ jobs:
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- name: "Checkout Code"
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
- name: Check secret
|
||||
id: checksecret
|
||||
uses: ./.github/actions/exists
|
||||
@@ -47,16 +47,16 @@ jobs:
|
||||
contents: read
|
||||
steps:
|
||||
- name: Checkout Source
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
- uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
|
||||
with:
|
||||
go-version-file: 'go.mod'
|
||||
- name: Run Gosec Security Scanner
|
||||
uses: securego/gosec@32975f4bab0d7b683a88756aaf3fa5502188b476 # v2.22.7
|
||||
uses: securego/gosec@c9453023c4e81ebdb6dde29e22d9cd5e2285fb16 # v2.22.8
|
||||
with:
|
||||
args: '-no-fail -fmt sarif -out gosec.sarif ./...'
|
||||
- name: Upload SARIF file
|
||||
uses: github/codeql-action/upload-sarif@b9b3b12fa29bb4f95fb2e36128124ff9364aaf0e
|
||||
uses: github/codeql-action/upload-sarif@233052189b8c862bfaf875fb02c115f54d2b9286
|
||||
with:
|
||||
sarif_file: gosec.sarif
|
||||
unit_tests:
|
||||
@@ -64,7 +64,7 @@ jobs:
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
- uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
|
||||
with:
|
||||
go-version-file: 'go.mod'
|
||||
|
||||
4
.github/workflows/docker-build.yml
vendored
4
.github/workflows/docker-build.yml
vendored
@@ -24,7 +24,7 @@ jobs:
|
||||
contents: read
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
- name: ko build
|
||||
run: VERSION=${{ github.sha }} make ko-build-all
|
||||
- name: Trivy Scan Image
|
||||
@@ -40,6 +40,6 @@ jobs:
|
||||
# See: https://github.com/aquasecurity/trivy-action/issues/389#issuecomment-2385416577
|
||||
TRIVY_DB_REPOSITORY: 'public.ecr.aws/aquasecurity/trivy-db:2'
|
||||
- name: Upload Trivy scan results to GitHub Security tab
|
||||
uses: github/codeql-action/upload-sarif@b9b3b12fa29bb4f95fb2e36128124ff9364aaf0e
|
||||
uses: github/codeql-action/upload-sarif@233052189b8c862bfaf875fb02c115f54d2b9286
|
||||
with:
|
||||
sarif_file: 'trivy-results.sarif'
|
||||
|
||||
2
.github/workflows/docker-publish.yml
vendored
2
.github/workflows/docker-publish.yml
vendored
@@ -20,7 +20,7 @@ jobs:
|
||||
capsule-digest: ${{ steps.publish-capsule.outputs.digest }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
- name: Setup caches
|
||||
uses: ./.github/actions/setup-caches
|
||||
timeout-minutes: 5
|
||||
|
||||
2
.github/workflows/e2e.yml
vendored
2
.github/workflows/e2e.yml
vendored
@@ -26,7 +26,7 @@ jobs:
|
||||
runs-on:
|
||||
labels: ubuntu-latest-8-cores
|
||||
steps:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
|
||||
|
||||
4
.github/workflows/helm-publish.yml
vendored
4
.github/workflows/helm-publish.yml
vendored
@@ -16,7 +16,7 @@ jobs:
|
||||
if: github.repository_owner == 'projectcapsule'
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
- name: "Extract Version"
|
||||
id: extract_version
|
||||
run: |
|
||||
@@ -45,7 +45,7 @@ jobs:
|
||||
outputs:
|
||||
chart-digest: ${{ steps.helm_publish.outputs.digest }}
|
||||
steps:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
- uses: sigstore/cosign-installer@d58896d6a1865668819e1d91763c7751a165e159 # v3.9.2
|
||||
- name: "Extract Version"
|
||||
id: extract_version
|
||||
|
||||
4
.github/workflows/helm-test.yml
vendored
4
.github/workflows/helm-test.yml
vendored
@@ -23,14 +23,14 @@ jobs:
|
||||
options: --user root
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
- name: Run ah lint
|
||||
working-directory: ./charts/
|
||||
run: ah lint
|
||||
lint:
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: azure/setup-helm@b9e51907a09c216f16ebe8536097933489208112 # v4
|
||||
|
||||
6
.github/workflows/lint.yml
vendored
6
.github/workflows/lint.yml
vendored
@@ -15,7 +15,7 @@ jobs:
|
||||
name: diff
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
|
||||
@@ -35,7 +35,7 @@ jobs:
|
||||
name: yamllint
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
- name: Install yamllint
|
||||
run: pip install yamllint
|
||||
- name: Lint YAML files
|
||||
@@ -44,7 +44,7 @@ jobs:
|
||||
name: lint
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
- uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
|
||||
with:
|
||||
go-version-file: 'go.mod'
|
||||
|
||||
10
.github/workflows/releaser.yml
vendored
10
.github/workflows/releaser.yml
vendored
@@ -23,7 +23,7 @@ jobs:
|
||||
- "v1.30.0"
|
||||
runs-on: ubuntu-latest-8-cores
|
||||
steps:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
|
||||
@@ -52,7 +52,7 @@ jobs:
|
||||
id-token: write
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Install Go
|
||||
@@ -64,16 +64,16 @@ jobs:
|
||||
timeout-minutes: 5
|
||||
continue-on-error: true
|
||||
- uses: creekorful/goreportcard-action@1f35ced8cdac2cba28c9a2f2288a16aacfd507f9 # v1.0
|
||||
- uses: anchore/sbom-action/download-syft@7b36ad622f042cab6f59a75c2ac24ccb256e9b45
|
||||
- uses: anchore/sbom-action/download-syft@da167eac915b4e86f08b264dbdbc867b61be6f0c
|
||||
- name: Install Cosign
|
||||
uses: sigstore/cosign-installer@d58896d6a1865668819e1d91763c7751a165e159 # v3.9.2
|
||||
- name: download artifact
|
||||
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
|
||||
uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0
|
||||
with:
|
||||
name: capsule-seccomp
|
||||
path: ./capsule-seccomp.json
|
||||
- name: Run GoReleaser
|
||||
uses: goreleaser/goreleaser-action@9c156ee8a17a598857849441385a2041ef570552 # v6.3.0
|
||||
uses: goreleaser/goreleaser-action@e435ccd777264be153ace6237001ef4d979d3a7a # v6.4.0
|
||||
with:
|
||||
version: latest
|
||||
args: release --clean --timeout 90m
|
||||
|
||||
4
.github/workflows/scorecard.yml
vendored
4
.github/workflows/scorecard.yml
vendored
@@ -20,7 +20,7 @@ jobs:
|
||||
id-token: write
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Run analysis
|
||||
@@ -37,6 +37,6 @@ jobs:
|
||||
path: results.sarif
|
||||
retention-days: 5
|
||||
- name: Upload to code-scanning
|
||||
uses: github/codeql-action/upload-sarif@51f77329afa6477de8c49fc9c7046c15b9a4e79d # v3.29.5
|
||||
uses: github/codeql-action/upload-sarif@df559355d593797519d70b90fc8edd5db049e7a2 # v3.29.9
|
||||
with:
|
||||
sarif_file: results.sarif
|
||||
|
||||
2
.github/workflows/stale.yml
vendored
2
.github/workflows/stale.yml
vendored
@@ -15,7 +15,7 @@ jobs:
|
||||
pull-requests: write
|
||||
steps:
|
||||
- name: Close stale pull requests
|
||||
uses: actions/stale@a92fd57ffeff1a7d5e9f90394c229c1cebb74321
|
||||
uses: actions/stale@8f717f0dfca33b78d3c933452e42558e4456c8e7
|
||||
with:
|
||||
stale-issue-message: 'This issue is stale because it has been open 60 days with no activity. Remove stale label or comment or this will be closed in 30 days.'
|
||||
stale-pr-message: 'This pull request has been marked as stale because it has been inactive for more than 30 days. Please update this pull request or it will be automatically closed in 30 days.'
|
||||
|
||||
@@ -23,6 +23,7 @@ linters:
|
||||
- unparam
|
||||
- varnamelen
|
||||
- wrapcheck
|
||||
- interfacebloat
|
||||
- noinlineerr
|
||||
- revive
|
||||
settings:
|
||||
|
||||
@@ -6,7 +6,7 @@ repos:
|
||||
stages: [commit-msg]
|
||||
additional_dependencies: ['@commitlint/config-conventional', 'commitlint-plugin-function-rules']
|
||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||
rev: v5.0.0
|
||||
rev: v6.0.0
|
||||
hooks:
|
||||
- id: check-executables-have-shebangs
|
||||
- id: double-quote-string-fixer
|
||||
|
||||
2
Makefile
2
Makefile
@@ -383,7 +383,7 @@ nwa:
|
||||
$(call go-install-tool,$(NWA),github.com/$(NWA_LOOKUP)@$(NWA_VERSION))
|
||||
|
||||
GOLANGCI_LINT := $(LOCALBIN)/golangci-lint
|
||||
GOLANGCI_LINT_VERSION := v2.3.0
|
||||
GOLANGCI_LINT_VERSION := v2.4.0
|
||||
GOLANGCI_LINT_LOOKUP := golangci/golangci-lint
|
||||
golangci-lint: ## Download golangci-lint locally if necessary.
|
||||
@test -s $(GOLANGCI_LINT) && $(GOLANGCI_LINT) -h | grep -q $(GOLANGCI_LINT_VERSION) || \
|
||||
|
||||
@@ -14,6 +14,9 @@ type CapsuleConfigurationSpec struct {
|
||||
// Names of the groups for Capsule users.
|
||||
// +kubebuilder:default={capsule.clastix.io}
|
||||
UserGroups []string `json:"userGroups,omitempty"`
|
||||
// Define groups which when found in the request of a user will be ignored by the Capsule
|
||||
// this might be useful if you have one group where all the users are in, but you want to separate administrators from normal users with additional groups.
|
||||
IgnoreUserWithGroups []string `json:"ignoreUserWithGroups,omitempty"`
|
||||
// Enforces the Tenant owner, during Namespace creation, to name it using the selected Tenant name as prefix,
|
||||
// separated by a dash. This is useful to avoid Namespace name collision in a public CaaS environment.
|
||||
// +kubebuilder:default=false
|
||||
|
||||
@@ -122,6 +122,11 @@ func (in *CapsuleConfigurationSpec) DeepCopyInto(out *CapsuleConfigurationSpec)
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
if in.IgnoreUserWithGroups != nil {
|
||||
in, out := &in.IgnoreUserWithGroups, &out.IgnoreUserWithGroups
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
out.CapsuleResources = in.CapsuleResources
|
||||
if in.NodeMetadata != nil {
|
||||
in, out := &in.NodeMetadata, &out.NodeMetadata
|
||||
|
||||
@@ -52,6 +52,13 @@ spec:
|
||||
Enforces the Tenant owner, during Namespace creation, to name it using the selected Tenant name as prefix,
|
||||
separated by a dash. This is useful to avoid Namespace name collision in a public CaaS environment.
|
||||
type: boolean
|
||||
ignoreUserWithGroups:
|
||||
description: |-
|
||||
Define groups which when found in the request of a user will be ignored by the Capsule
|
||||
this might be useful if you have one group where all the users are in, but you want to separate administrators from normal users with additional groups.
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
nodeMetadata:
|
||||
description: |-
|
||||
Allows to set the forbidden metadata for the worker nodes that could be patched by a Tenant.
|
||||
|
||||
@@ -40,7 +40,13 @@ func prepareAdditionalMetadata(m map[string]string) map[string]string {
|
||||
return make(map[string]string)
|
||||
}
|
||||
|
||||
return m
|
||||
// we need to create a new map to avoid modifying the original one
|
||||
copied := make(map[string]string, len(m))
|
||||
for k, v := range m {
|
||||
copied[k] = v
|
||||
}
|
||||
|
||||
return copied
|
||||
}
|
||||
|
||||
func (r *Processor) HandlePruning(ctx context.Context, current, desired sets.Set[string]) (updateStatus bool) {
|
||||
|
||||
@@ -9,11 +9,14 @@ import (
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
. "github.com/onsi/gomega"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
|
||||
capsulev1beta2 "github.com/projectcapsule/capsule/api/v1beta2"
|
||||
)
|
||||
|
||||
var _ = Describe("creating a Namespace as Tenant owner with custom --capsule-group", Label("config"), func() {
|
||||
originConfig := &capsulev1beta2.CapsuleConfiguration{}
|
||||
|
||||
tnt := &capsulev1beta2.Tenant{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "tenant-assigned-custom-group",
|
||||
@@ -29,6 +32,8 @@ var _ = Describe("creating a Namespace as Tenant owner with custom --capsule-gro
|
||||
}
|
||||
|
||||
JustBeforeEach(func() {
|
||||
Expect(k8sClient.Get(context.Background(), client.ObjectKey{Name: defaultConfigurationName}, originConfig)).To(Succeed())
|
||||
|
||||
EventuallyCreation(func() error {
|
||||
tnt.ResourceVersion = ""
|
||||
return k8sClient.Create(context.TODO(), tnt)
|
||||
@@ -36,6 +41,17 @@ var _ = Describe("creating a Namespace as Tenant owner with custom --capsule-gro
|
||||
})
|
||||
JustAfterEach(func() {
|
||||
Expect(k8sClient.Delete(context.TODO(), tnt)).Should(Succeed())
|
||||
|
||||
// Restore Configuration
|
||||
Eventually(func() error {
|
||||
c := &capsulev1beta2.CapsuleConfiguration{}
|
||||
if err := k8sClient.Get(context.Background(), client.ObjectKey{Name: originConfig.Name}, c); err != nil {
|
||||
return err
|
||||
}
|
||||
// Apply the initial configuration from originConfig to c
|
||||
c.Spec = originConfig.Spec
|
||||
return k8sClient.Update(context.Background(), c)
|
||||
}, defaultTimeoutInterval, defaultPollInterval).Should(Succeed())
|
||||
})
|
||||
|
||||
It("should fail using a User non matching the capsule-user-group flag", func() {
|
||||
@@ -68,4 +84,16 @@ var _ = Describe("creating a Namespace as Tenant owner with custom --capsule-gro
|
||||
NamespaceCreation(ns, tnt.Spec.Owners[0], defaultTimeoutInterval).Should(Succeed())
|
||||
TenantNamespaceList(tnt, defaultTimeoutInterval).Should(ContainElement(ns.GetName()))
|
||||
})
|
||||
|
||||
It("should fail when group is ignored", func() {
|
||||
ModifyCapsuleConfigurationOpts(func(configuration *capsulev1beta2.CapsuleConfiguration) {
|
||||
configuration.Spec.UserGroups = []string{"projectcapsule.dev"}
|
||||
configuration.Spec.IgnoreUserWithGroups = []string{"projectcapsule.dev"}
|
||||
})
|
||||
|
||||
ns := NewNamespace("")
|
||||
|
||||
NamespaceCreation(ns, tnt.Spec.Owners[0], defaultTimeoutInterval).ShouldNot(Succeed())
|
||||
})
|
||||
|
||||
})
|
||||
|
||||
@@ -54,7 +54,7 @@ var _ = Describe("creating several Namespaces for a Tenant", Label("namespace"),
|
||||
|
||||
})
|
||||
|
||||
It("Can't hijack offlimits namespace", func() {
|
||||
It("Can't hijack offlimits namespace (Ownerreferences)", func() {
|
||||
tenant := &capsulev1beta2.Tenant{}
|
||||
Expect(k8sClient.Get(context.TODO(), types.NamespacedName{Name: tnt.Name}, tenant)).Should(Succeed())
|
||||
|
||||
@@ -72,6 +72,40 @@ var _ = Describe("creating several Namespaces for a Tenant", Label("namespace"),
|
||||
}
|
||||
})
|
||||
|
||||
It("Can't hijack offlimits namespace (Labels)", func() {
|
||||
tenant := &capsulev1beta2.Tenant{}
|
||||
Expect(k8sClient.Get(context.TODO(), types.NamespacedName{Name: tnt.Name}, tenant)).Should(Succeed())
|
||||
|
||||
// Get the namespace
|
||||
Expect(k8sClient.Get(context.TODO(), types.NamespacedName{Name: kubeSystem.GetName()}, kubeSystem)).Should(Succeed())
|
||||
|
||||
for _, owner := range tnt.Spec.Owners {
|
||||
cs := ownerClient(owner)
|
||||
|
||||
patch := []byte(fmt.Sprintf(`{"metadata":{"labels":{"%s":"%s"}}}`, "capsule.clastix.io/tenant", tenant.GetName()))
|
||||
|
||||
_, err := cs.CoreV1().Namespaces().Patch(context.TODO(), kubeSystem.Name, types.StrategicMergePatchType, patch, metav1.PatchOptions{})
|
||||
Expect(err).To(HaveOccurred())
|
||||
}
|
||||
})
|
||||
|
||||
It("Can't hijack offlimits namespace (Annotations)", func() {
|
||||
tenant := &capsulev1beta2.Tenant{}
|
||||
Expect(k8sClient.Get(context.TODO(), types.NamespacedName{Name: tnt.Name}, tenant)).Should(Succeed())
|
||||
|
||||
// Get the namespace
|
||||
Expect(k8sClient.Get(context.TODO(), types.NamespacedName{Name: kubeSystem.GetName()}, kubeSystem)).Should(Succeed())
|
||||
|
||||
for _, owner := range tnt.Spec.Owners {
|
||||
cs := ownerClient(owner)
|
||||
|
||||
patch := []byte(fmt.Sprintf(`{"metadata":{"annotations":{"%s":"%s"}}}`, "capsule.clastix.io/tenant", tenant.GetName()))
|
||||
|
||||
_, err := cs.CoreV1().Namespaces().Patch(context.TODO(), kubeSystem.Name, types.StrategicMergePatchType, patch, metav1.PatchOptions{})
|
||||
Expect(err).To(HaveOccurred())
|
||||
}
|
||||
})
|
||||
|
||||
It("Owners can create and attempt to patch new namespaces but patches should not be applied", func() {
|
||||
for _, owner := range tnt.Spec.Owners {
|
||||
cs := ownerClient(owner)
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
rbacv1 "k8s.io/api/rbac/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
|
||||
capsulev1beta2 "github.com/projectcapsule/capsule/api/v1beta2"
|
||||
"github.com/projectcapsule/capsule/pkg/api"
|
||||
@@ -19,6 +20,8 @@ import (
|
||||
)
|
||||
|
||||
var _ = Describe("modifying node labels and annotations", Label("config", "nodes"), func() {
|
||||
originConfig := &capsulev1beta2.CapsuleConfiguration{}
|
||||
|
||||
tnt := &capsulev1beta2.Tenant{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "tenant-node-user-metadata-forbidden",
|
||||
@@ -72,6 +75,8 @@ var _ = Describe("modifying node labels and annotations", Label("config", "nodes
|
||||
Skip(fmt.Sprintf("Node webhook is disabled for current version %s", version.String()))
|
||||
}
|
||||
|
||||
Expect(k8sClient.Get(context.Background(), client.ObjectKey{Name: defaultConfigurationName}, originConfig)).To(Succeed())
|
||||
|
||||
EventuallyCreation(func() error {
|
||||
tnt.ResourceVersion = ""
|
||||
return k8sClient.Create(context.TODO(), tnt)
|
||||
@@ -110,6 +115,17 @@ var _ = Describe("modifying node labels and annotations", Label("config", "nodes
|
||||
return k8sClient.Update(context.Background(), node)
|
||||
})
|
||||
}).Should(Succeed())
|
||||
|
||||
// Restore Configuration
|
||||
Eventually(func() error {
|
||||
c := &capsulev1beta2.CapsuleConfiguration{}
|
||||
if err := k8sClient.Get(context.Background(), client.ObjectKey{Name: originConfig.Name}, c); err != nil {
|
||||
return err
|
||||
}
|
||||
// Apply the initial configuration from originConfig to c
|
||||
c.Spec = originConfig.Spec
|
||||
return k8sClient.Update(context.Background(), c)
|
||||
}, defaultTimeoutInterval, defaultPollInterval).Should(Succeed())
|
||||
})
|
||||
|
||||
It("should allow", func() {
|
||||
@@ -171,6 +187,19 @@ var _ = Describe("modifying node labels and annotations", Label("config", "nodes
|
||||
})
|
||||
})
|
||||
It("should fail", func() {
|
||||
ModifyCapsuleConfigurationOpts(func(configuration *capsulev1beta2.CapsuleConfiguration) {
|
||||
configuration.Spec.NodeMetadata = &capsulev1beta2.NodeMetadata{
|
||||
ForbiddenLabels: api.ForbiddenListSpec{
|
||||
Exact: []string{"foo", "bar"},
|
||||
Regex: "^gatsby-.*$",
|
||||
},
|
||||
ForbiddenAnnotations: api.ForbiddenListSpec{
|
||||
Exact: []string{"foo", "bar"},
|
||||
Regex: "^gatsby-.*$",
|
||||
},
|
||||
}
|
||||
})
|
||||
|
||||
Expect(ModifyNode(func(node *corev1.Node) error {
|
||||
node.Labels["foo"] = "bar"
|
||||
node.Labels["gatsby-foo"] = "bar"
|
||||
|
||||
@@ -9,11 +9,14 @@ import (
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
. "github.com/onsi/gomega"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
|
||||
capsulev1beta2 "github.com/projectcapsule/capsule/api/v1beta2"
|
||||
)
|
||||
|
||||
var _ = Describe("creating a Namespace with a protected Namespace regex enabled", Label("namespace"), func() {
|
||||
originConfig := &capsulev1beta2.CapsuleConfiguration{}
|
||||
|
||||
tnt := &capsulev1beta2.Tenant{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "tenant-protected-namespace",
|
||||
@@ -29,6 +32,8 @@ var _ = Describe("creating a Namespace with a protected Namespace regex enabled"
|
||||
}
|
||||
|
||||
JustBeforeEach(func() {
|
||||
Expect(k8sClient.Get(context.Background(), client.ObjectKey{Name: defaultConfigurationName}, originConfig)).To(Succeed())
|
||||
|
||||
EventuallyCreation(func() error {
|
||||
tnt.ResourceVersion = ""
|
||||
return k8sClient.Create(context.TODO(), tnt)
|
||||
@@ -36,6 +41,17 @@ var _ = Describe("creating a Namespace with a protected Namespace regex enabled"
|
||||
})
|
||||
JustAfterEach(func() {
|
||||
Expect(k8sClient.Delete(context.TODO(), tnt)).Should(Succeed())
|
||||
|
||||
// Restore Configuration
|
||||
Eventually(func() error {
|
||||
c := &capsulev1beta2.CapsuleConfiguration{}
|
||||
if err := k8sClient.Get(context.Background(), client.ObjectKey{Name: originConfig.Name}, c); err != nil {
|
||||
return err
|
||||
}
|
||||
// Apply the initial configuration from originConfig to c
|
||||
c.Spec = originConfig.Spec
|
||||
return k8sClient.Update(context.Background(), c)
|
||||
}, defaultTimeoutInterval, defaultPollInterval).Should(Succeed())
|
||||
})
|
||||
|
||||
It("should succeed and be available in Tenant namespaces list", func() {
|
||||
|
||||
@@ -27,8 +27,9 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
defaultTimeoutInterval = 40 * time.Second
|
||||
defaultPollInterval = time.Second
|
||||
defaultTimeoutInterval = 40 * time.Second
|
||||
defaultPollInterval = time.Second
|
||||
defaultConfigurationName = "default"
|
||||
)
|
||||
|
||||
func NewService(svc types.NamespacedName) *corev1.Service {
|
||||
@@ -100,7 +101,7 @@ func EventuallyCreation(f interface{}) AsyncAssertion {
|
||||
|
||||
func ModifyCapsuleConfigurationOpts(fn func(configuration *capsulev1beta2.CapsuleConfiguration)) {
|
||||
config := &capsulev1beta2.CapsuleConfiguration{}
|
||||
Expect(k8sClient.Get(context.Background(), types.NamespacedName{Name: "default"}, config)).ToNot(HaveOccurred())
|
||||
Expect(k8sClient.Get(context.Background(), types.NamespacedName{Name: defaultConfigurationName}, config)).ToNot(HaveOccurred())
|
||||
|
||||
fn(config)
|
||||
|
||||
|
||||
10
go.mod
10
go.mod
@@ -2,7 +2,7 @@ module github.com/projectcapsule/capsule
|
||||
|
||||
go 1.24.0
|
||||
|
||||
toolchain go1.24.5
|
||||
toolchain go1.24.6
|
||||
|
||||
require (
|
||||
github.com/go-logr/logr v1.4.3
|
||||
@@ -16,10 +16,10 @@ require (
|
||||
go.uber.org/automaxprocs v1.6.0
|
||||
go.uber.org/zap v1.27.0
|
||||
golang.org/x/sync v0.16.0
|
||||
k8s.io/api v0.33.3
|
||||
k8s.io/apiextensions-apiserver v0.33.3
|
||||
k8s.io/apimachinery v0.33.3
|
||||
k8s.io/client-go v0.33.3
|
||||
k8s.io/api v0.33.4
|
||||
k8s.io/apiextensions-apiserver v0.33.4
|
||||
k8s.io/apimachinery v0.33.4
|
||||
k8s.io/client-go v0.33.4
|
||||
k8s.io/utils v0.0.0-20250604170112-4c0f3b243397
|
||||
sigs.k8s.io/cluster-api v1.10.4
|
||||
sigs.k8s.io/controller-runtime v0.21.0
|
||||
|
||||
8
go.sum
8
go.sum
@@ -288,18 +288,24 @@ k8s.io/api v0.33.2 h1:YgwIS5jKfA+BZg//OQhkJNIfie/kmRsO0BmNaVSimvY=
|
||||
k8s.io/api v0.33.2/go.mod h1:fhrbphQJSM2cXzCWgqU29xLDuks4mu7ti9vveEnpSXs=
|
||||
k8s.io/api v0.33.3 h1:SRd5t//hhkI1buzxb288fy2xvjubstenEKL9K51KBI8=
|
||||
k8s.io/api v0.33.3/go.mod h1:01Y/iLUjNBM3TAvypct7DIj0M0NIZc+PzAHCIo0CYGE=
|
||||
k8s.io/api v0.33.4 h1:oTzrFVNPXBjMu0IlpA2eDDIU49jsuEorGHB4cvKupkk=
|
||||
k8s.io/api v0.33.4/go.mod h1:VHQZ4cuxQ9sCUMESJV5+Fe8bGnqAARZ08tSTdHWfeAc=
|
||||
k8s.io/apiextensions-apiserver v0.33.1 h1:N7ccbSlRN6I2QBcXevB73PixX2dQNIW0ZRuguEE91zI=
|
||||
k8s.io/apiextensions-apiserver v0.33.1/go.mod h1:uNQ52z1A1Gu75QSa+pFK5bcXc4hq7lpOXbweZgi4dqA=
|
||||
k8s.io/apiextensions-apiserver v0.33.2 h1:6gnkIbngnaUflR3XwE1mCefN3YS8yTD631JXQhsU6M8=
|
||||
k8s.io/apiextensions-apiserver v0.33.2/go.mod h1:IvVanieYsEHJImTKXGP6XCOjTwv2LUMos0YWc9O+QP8=
|
||||
k8s.io/apiextensions-apiserver v0.33.3 h1:qmOcAHN6DjfD0v9kxL5udB27SRP6SG/MTopmge3MwEs=
|
||||
k8s.io/apiextensions-apiserver v0.33.3/go.mod h1:oROuctgo27mUsyp9+Obahos6CWcMISSAPzQ77CAQGz8=
|
||||
k8s.io/apiextensions-apiserver v0.33.4 h1:rtq5SeXiDbXmSwxsF0MLe2Mtv3SwprA6wp+5qh/CrOU=
|
||||
k8s.io/apiextensions-apiserver v0.33.4/go.mod h1:mWXcZQkQV1GQyxeIjYApuqsn/081hhXPZwZ2URuJeSs=
|
||||
k8s.io/apimachinery v0.33.1 h1:mzqXWV8tW9Rw4VeW9rEkqvnxj59k1ezDUl20tFK/oM4=
|
||||
k8s.io/apimachinery v0.33.1/go.mod h1:BHW0YOu7n22fFv/JkYOEfkUYNRN0fj0BlvMFWA7b+SM=
|
||||
k8s.io/apimachinery v0.33.2 h1:IHFVhqg59mb8PJWTLi8m1mAoepkUNYmptHsV+Z1m5jY=
|
||||
k8s.io/apimachinery v0.33.2/go.mod h1:BHW0YOu7n22fFv/JkYOEfkUYNRN0fj0BlvMFWA7b+SM=
|
||||
k8s.io/apimachinery v0.33.3 h1:4ZSrmNa0c/ZpZJhAgRdcsFcZOw1PQU1bALVQ0B3I5LA=
|
||||
k8s.io/apimachinery v0.33.3/go.mod h1:BHW0YOu7n22fFv/JkYOEfkUYNRN0fj0BlvMFWA7b+SM=
|
||||
k8s.io/apimachinery v0.33.4 h1:SOf/JW33TP0eppJMkIgQ+L6atlDiP/090oaX0y9pd9s=
|
||||
k8s.io/apimachinery v0.33.4/go.mod h1:BHW0YOu7n22fFv/JkYOEfkUYNRN0fj0BlvMFWA7b+SM=
|
||||
k8s.io/apiserver v0.33.1 h1:yLgLUPDVC6tHbNcw5uE9mo1T6ELhJj7B0geifra3Qdo=
|
||||
k8s.io/apiserver v0.33.1/go.mod h1:VMbE4ArWYLO01omz+k8hFjAdYfc3GVAYPrhP2tTKccs=
|
||||
k8s.io/client-go v0.33.1 h1:ZZV/Ks2g92cyxWkRRnfUDsnhNn28eFpt26aGc8KbXF4=
|
||||
@@ -308,6 +314,8 @@ k8s.io/client-go v0.33.2 h1:z8CIcc0P581x/J1ZYf4CNzRKxRvQAwoAolYPbtQes+E=
|
||||
k8s.io/client-go v0.33.2/go.mod h1:9mCgT4wROvL948w6f6ArJNb7yQd7QsvqavDeZHvNmHo=
|
||||
k8s.io/client-go v0.33.3 h1:M5AfDnKfYmVJif92ngN532gFqakcGi6RvaOF16efrpA=
|
||||
k8s.io/client-go v0.33.3/go.mod h1:luqKBQggEf3shbxHY4uVENAxrDISLOarxpTKMiUuujg=
|
||||
k8s.io/client-go v0.33.4 h1:TNH+CSu8EmXfitntjUPwaKVPN0AYMbc9F1bBS8/ABpw=
|
||||
k8s.io/client-go v0.33.4/go.mod h1:LsA0+hBG2DPwovjd931L/AoaezMPX9CmBgyVyBZmbCY=
|
||||
k8s.io/cluster-bootstrap v0.32.3 h1:AqIpsUhB6MUeaAsl1WvaUw54AHRd2hfZrESlKChtd8s=
|
||||
k8s.io/cluster-bootstrap v0.32.3/go.mod h1:CHbBwgOb6liDV6JFUTkx5t85T2xidy0sChBDoyYw344=
|
||||
k8s.io/component-base v0.33.1 h1:EoJ0xA+wr77T+G8p6T3l4efT2oNwbqBVKR71E0tBIaI=
|
||||
|
||||
@@ -85,6 +85,10 @@ func (c *capsuleConfiguration) UserGroups() []string {
|
||||
return c.retrievalFn().Spec.UserGroups
|
||||
}
|
||||
|
||||
func (c *capsuleConfiguration) IgnoreUserWithGroups() []string {
|
||||
return c.retrievalFn().Spec.IgnoreUserWithGroups
|
||||
}
|
||||
|
||||
func (c *capsuleConfiguration) ForbiddenUserNodeLabels() *capsuleapi.ForbiddenListSpec {
|
||||
if c.retrievalFn().Spec.NodeMetadata == nil {
|
||||
return nil
|
||||
|
||||
@@ -24,6 +24,7 @@ type Configuration interface {
|
||||
ValidatingWebhookConfigurationName() string
|
||||
TenantCRDName() string
|
||||
UserGroups() []string
|
||||
IgnoreUserWithGroups() []string
|
||||
ForbiddenUserNodeLabels() *capsuleapi.ForbiddenListSpec
|
||||
ForbiddenUserNodeAnnotations() *capsuleapi.ForbiddenListSpec
|
||||
}
|
||||
|
||||
@@ -74,7 +74,7 @@ func (r *freezedHandler) OnDelete(c client.Client, _ admission.Decoder, recorder
|
||||
|
||||
tnt := tntList.Items[0]
|
||||
|
||||
if tnt.Spec.Cordoned && utils.IsCapsuleUser(ctx, req, c, r.configuration.UserGroups()) {
|
||||
if tnt.Spec.Cordoned && utils.IsCapsuleUser(ctx, req, c, r.configuration.UserGroups(), r.configuration.IgnoreUserWithGroups()) {
|
||||
recorder.Eventf(&tnt, corev1.EventTypeWarning, "TenantFreezed", "Namespace %s cannot be deleted, the current Tenant is freezed", req.Name)
|
||||
|
||||
response := admission.Denied("the selected Tenant is freezed")
|
||||
@@ -106,7 +106,7 @@ func (r *freezedHandler) OnUpdate(c client.Client, decoder admission.Decoder, re
|
||||
|
||||
tnt := tntList.Items[0]
|
||||
|
||||
if tnt.Spec.Cordoned && utils.IsCapsuleUser(ctx, req, c, r.configuration.UserGroups()) {
|
||||
if tnt.Spec.Cordoned && utils.IsCapsuleUser(ctx, req, c, r.configuration.UserGroups(), r.configuration.IgnoreUserWithGroups()) {
|
||||
recorder.Eventf(&tnt, corev1.EventTypeWarning, "TenantFreezed", "Namespace %s cannot be updated, the current Tenant is freezed", ns.GetName())
|
||||
|
||||
response := admission.Denied("the selected Tenant is freezed")
|
||||
|
||||
@@ -66,14 +66,14 @@ func (r *patchHandler) OnUpdate(c client.Client, decoder admission.Decoder, reco
|
||||
return &response
|
||||
}
|
||||
|
||||
if !utils.IsTenantOwner(tnt.Spec.Owners, req.UserInfo) {
|
||||
recorder.Eventf(tnt, corev1.EventTypeWarning, "NamespacePatch", e)
|
||||
response := admission.Denied(e)
|
||||
|
||||
return &response
|
||||
if utils.IsTenantOwner(tnt.Spec.Owners, req.UserInfo) {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
recorder.Eventf(ns, corev1.EventTypeWarning, "NamespacePatch", e)
|
||||
response := admission.Denied(e)
|
||||
|
||||
return &response
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,7 +62,7 @@ func (h *cordoningHandler) cordonHandler(ctx context.Context, clt client.Client,
|
||||
}
|
||||
|
||||
tnt := tntList.Items[0]
|
||||
if tnt.Spec.Cordoned && utils.IsCapsuleUser(ctx, req, clt, h.configuration.UserGroups()) {
|
||||
if tnt.Spec.Cordoned && utils.IsCapsuleUser(ctx, req, clt, h.configuration.UserGroups(), h.configuration.IgnoreUserWithGroups()) {
|
||||
recorder.Eventf(&tnt, corev1.EventTypeWarning, "TenantFreezed", "%s %s/%s cannot be %sd, current Tenant is freezed", req.Kind.String(), req.Namespace, req.Name, strings.ToLower(string(req.Operation)))
|
||||
|
||||
response := admission.Denied(fmt.Sprintf("tenant %s is freezed: please, reach out to the system administrator", tnt.GetName()))
|
||||
|
||||
@@ -26,9 +26,10 @@ type handler struct {
|
||||
handlers []webhook.Handler
|
||||
}
|
||||
|
||||
//nolint:dupl
|
||||
func (h *handler) OnCreate(client client.Client, decoder admission.Decoder, recorder record.EventRecorder) webhook.Func {
|
||||
return func(ctx context.Context, req admission.Request) *admission.Response {
|
||||
if !IsCapsuleUser(ctx, req, client, h.configuration.UserGroups()) {
|
||||
if !IsCapsuleUser(ctx, req, client, h.configuration.UserGroups(), h.configuration.IgnoreUserWithGroups()) {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -42,9 +43,10 @@ func (h *handler) OnCreate(client client.Client, decoder admission.Decoder, reco
|
||||
}
|
||||
}
|
||||
|
||||
//nolint:dupl
|
||||
func (h *handler) OnDelete(client client.Client, decoder admission.Decoder, recorder record.EventRecorder) webhook.Func {
|
||||
return func(ctx context.Context, req admission.Request) *admission.Response {
|
||||
if !IsCapsuleUser(ctx, req, client, h.configuration.UserGroups()) {
|
||||
if !IsCapsuleUser(ctx, req, client, h.configuration.UserGroups(), h.configuration.IgnoreUserWithGroups()) {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -58,9 +60,10 @@ func (h *handler) OnDelete(client client.Client, decoder admission.Decoder, reco
|
||||
}
|
||||
}
|
||||
|
||||
//nolint:dupl
|
||||
func (h *handler) OnUpdate(client client.Client, decoder admission.Decoder, recorder record.EventRecorder) webhook.Func {
|
||||
return func(ctx context.Context, req admission.Request) *admission.Response {
|
||||
if !IsCapsuleUser(ctx, req, client, h.configuration.UserGroups()) {
|
||||
if !IsCapsuleUser(ctx, req, client, h.configuration.UserGroups(), h.configuration.IgnoreUserWithGroups()) {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ import (
|
||||
"github.com/projectcapsule/capsule/pkg/utils"
|
||||
)
|
||||
|
||||
func IsCapsuleUser(ctx context.Context, req admission.Request, clt client.Client, userGroups []string) bool {
|
||||
func IsCapsuleUser(ctx context.Context, req admission.Request, clt client.Client, userGroups []string, ignoreGroups []string) bool {
|
||||
groupList := utils.NewUserGroupList(req.UserInfo.Groups)
|
||||
// if the user is a ServiceAccount belonging to the kube-system namespace, definitely, it's not a Capsule user
|
||||
// and we can skip the check in case of Capsule user group assigned to system:authenticated
|
||||
@@ -44,6 +44,14 @@ func IsCapsuleUser(ctx context.Context, req admission.Request, clt client.Client
|
||||
|
||||
for _, group := range userGroups {
|
||||
if groupList.Find(group) {
|
||||
if len(ignoreGroups) > 0 {
|
||||
for _, ignoreGroup := range ignoreGroups {
|
||||
if groupList.Find(ignoreGroup) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user