├── .bumpversion.cfg ├── .dockerignore ├── .drone.yml ├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md ├── dependabot.yml └── pull_request_template.md ├── .gitignore ├── .rules └── .htmlhintrc ├── CHANGELOG.md ├── Dockerfile ├── LICENSE ├── MAINTENANCE.md ├── README.md ├── app ├── app.py ├── constraints.txt ├── requirements.txt ├── static-content │ ├── logo.svg │ └── semantic.min.css ├── templates │ └── constraints-report.html └── web-client │ ├── .env │ ├── .gitignore │ ├── README.md │ ├── fork-ts-checker.config.js │ ├── package.json │ ├── public │ ├── favicon.ico │ ├── index.html │ ├── logo192.png │ ├── logo512.png │ ├── manifest.json │ ├── robots.txt │ └── touch-icon.png │ ├── src │ ├── App.scss │ ├── App.test.tsx │ ├── App.tsx │ ├── AppContext.ts │ ├── AppContextProvider.tsx │ ├── assets │ │ ├── fonts │ │ │ ├── JetBrainsMono-Bold.ttf │ │ │ ├── JetBrainsMono-Regular.ttf │ │ │ ├── Poppins-Bold.ttf │ │ │ ├── Poppins-Light.ttf │ │ │ ├── Poppins-Medium.ttf │ │ │ ├── Poppins-Regular.ttf │ │ │ └── Poppins-SemiBold.ttf │ │ ├── github-logo.svg │ │ ├── gpm-logo.svg │ │ ├── shield-active.svg │ │ └── shield-inactive.svg │ ├── components │ │ ├── Footer │ │ │ ├── Component.tsx │ │ │ ├── Style.scss │ │ │ └── index.ts │ │ └── Header │ │ │ ├── Component.tsx │ │ │ ├── Style.scss │ │ │ └── index.ts │ ├── hooks │ │ ├── useCurrentElementInView.tsx │ │ └── useScrollToHash.tsx │ ├── index.scss │ ├── index.tsx │ ├── pages │ │ ├── Configurations │ │ │ ├── Component.tsx │ │ │ ├── Style.scss │ │ │ ├── index.ts │ │ │ └── types.ts │ │ ├── ConstraintTemplates │ │ │ ├── Component.tsx │ │ │ ├── Style.scss │ │ │ ├── index.ts │ │ │ └── types.ts │ │ ├── Constraints │ │ │ ├── Component.tsx │ │ │ ├── Style.scss │ │ │ ├── index.ts │ │ │ └── types.ts │ │ ├── Error │ │ │ ├── Component.tsx │ │ │ ├── index.ts │ │ │ └── types.ts │ │ ├── Home │ │ │ ├── Component.tsx │ │ │ └── index.ts │ │ ├── Logout │ │ │ ├── Component.tsx │ │ │ └── index.ts │ │ ├── NotFound │ │ │ ├── Component.tsx │ │ │ └── index.ts │ │ ├── theme.ts │ │ └── types.ts │ ├── react-app-env.d.ts │ ├── reportWebVitals.ts │ ├── setupTests.ts │ ├── theme.ts │ └── utils.tsx │ ├── tsconfig.json │ └── yarn.lock ├── chart ├── .frigate ├── Chart.yaml ├── LICENSE ├── README.md ├── templates │ ├── NOTES.txt │ ├── _helpers.tpl │ ├── deployment.yaml │ ├── hpa.yaml │ ├── ingress.yaml │ ├── rbac.yaml │ ├── secret-multicluster.yaml │ ├── secret-oidc.yaml │ ├── secret.yaml │ ├── service.yaml │ └── serviceaccount.yaml └── values.yaml ├── docs └── releases │ ├── v0.1.md │ ├── v0.2.md │ ├── v0.3.0.md │ ├── v0.4.0.md │ ├── v0.4.1.md │ ├── v0.4.2.md │ ├── v0.5.0.md │ ├── v0.5.1.md │ ├── v1.0.0.md │ ├── v1.0.1.md │ ├── v1.0.10.md │ ├── v1.0.11.md │ ├── v1.0.12.md │ ├── v1.0.13.md │ ├── v1.0.2.md │ ├── v1.0.3.md │ ├── v1.0.4.md │ ├── v1.0.5.md │ ├── v1.0.6.md │ ├── v1.0.7.md │ ├── v1.0.8.md │ └── v1.0.9.md ├── kustomization.yaml ├── manifests ├── deployment.yaml ├── enable-oidc.yaml ├── ingress.yaml ├── multi-cluster.yaml ├── rbac.yaml └── service.yaml ├── renovate.json ├── screenshots ├── 01-home.png ├── 02-constrainttemplates.png ├── 03-constrainttemplates.png ├── 04-constraints.png ├── 05-constraints.png ├── 06-constraints.png ├── 07-configs.png └── 08-multicluster.png └── tests ├── deploy-patch.yaml ├── e2e-tests.yaml ├── e2e ├── .gitignore ├── README.md ├── package.json ├── playwright.config.js ├── tests │ ├── configurations.spec.ts │ ├── configurations.spec.ts-snapshots │ │ └── page-configurations-snapshot-1-linux.png │ ├── constraints.spec.ts │ ├── constraints.spec.ts-snapshots │ │ └── page-constraints-snapshot-1-linux.png │ ├── constrainttemplates.spec.ts │ ├── constrainttemplates.spec.ts-snapshots │ │ └── page-constrainttemplates-snapshot-1-linux.png │ ├── home.spec.ts │ └── home.spec.ts-snapshots │ │ └── page-home-snapshot-1-linux.png └── yarn.lock ├── helper.bash ├── kustomization.yaml └── tests.sh /.bumpversion.cfg: -------------------------------------------------------------------------------- 1 | [bumpversion] 2 | commit = True 3 | tag = True 4 | current_version = 1.0.13 5 | parse = (?P\d+)\.(?P\d+)\.(?P\d+)(\-rc(?P\d+))? 6 | serialize = 7 | {major}.{minor}.{patch}-rc{rc} 8 | {major}.{minor}.{patch} 9 | 10 | [bumpversion:file:README.md] 11 | 12 | [bumpversion:file:kustomization.yaml] 13 | 14 | [bumpversion:file:app/web-client/src/components/Footer/Component.tsx] 15 | 16 | [bumpversion:file:chart/Chart.yaml] 17 | 18 | [bumpversion:file:chart/README.md] 19 | 20 | [bumpversion:file:chart/values.yaml] 21 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | **/node_modules 2 | **/build 3 | **/chart 4 | **/manifests 5 | **/screenshots 6 | **/tests 7 | -------------------------------------------------------------------------------- /.drone.yml: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2022-2024 SIGHUP s.r.l All rights reserved. 2 | # Use of this source code is governed by a BSD-style 3 | # license that can be found in the LICENSE file. 4 | 5 | name: QA 6 | kind: pipeline 7 | type: docker 8 | 9 | trigger: 10 | ref: 11 | exclude: 12 | # this tag is created by Chart Releaser after the release. 13 | - refs/tags/gatekeeper-policy-manager-** 14 | 15 | steps: 16 | - name: Check license headers presence 17 | image: docker.io/library/golang:1.23.2 18 | depends_on: 19 | - clone 20 | commands: 21 | - go install github.com/google/addlicense@latest 22 | - addlicense -c "SIGHUP s.r.l" -v -l bsd -check -ignore 'chart/**' -ignore 'gpm.yaml' -ignore 'rendered_chart.yaml' . 23 | 24 | - name: Lint 25 | image: quay.io/sighup/policeman 26 | pull: always 27 | depends_on: 28 | - clone 29 | environment: 30 | FILTER_REGEX_EXCLUDE: (app/static-content/semantic.min.css|chart/|tests/e2e/|\.github) 31 | # Identifies false positives like missing 'selector'. 32 | # Doing this is valid for Kustomize patches 33 | VALIDATE_KUBERNETES_KUBECONFORM: "false" 34 | VALIDATE_KUBERNETES_KUBEVAL: "false" 35 | # Some duplicated code is intended. 36 | VALIDATE_JSCPD: "false" 37 | TYPESCRIPT_DEFAULT_STYLE: "prettier" 38 | # We ignore the command not found error, because in the linter image we don't have all the binaries being called. 39 | SHELLCHECK_OPTS: "-e SC2317" 40 | 41 | - name: Render manifests 42 | image: quay.io/sighup/e2e-testing:1.1.0_0.11.0_3.12.0_1.9.4_1.29.1_3.5.3_4.33.3 43 | depends_on: 44 | - clone 45 | commands: 46 | - kustomize build . > gpm.yaml 47 | - helm template --set config.secretKey=e2e chart > rendered_chart.yaml 48 | 49 | - name: Check deprecated APIs 50 | image: us-docker.pkg.dev/fairwinds-ops/oss/pluto:v5 51 | pull: always 52 | depends_on: 53 | - "Render manifests" 54 | commands: 55 | # we use --ignore-deprecations because we don't want the CI to fail when the API has not been removed yet. 56 | - /pluto detect gpm.yaml --ignore-deprecations --target-versions=k8s=v1.31.0 57 | - /pluto detect rendered_chart.yaml --ignore-deprecations --target-versions=k8s=v1.31.0 58 | 59 | --- 60 | name: Build test and release 61 | kind: pipeline 62 | type: docker 63 | 64 | depends_on: 65 | - QA 66 | 67 | trigger: 68 | ref: 69 | include: 70 | - refs/tags/** 71 | - refs/heads/main 72 | - refs/heads/dependabot/** 73 | exclude: 74 | # this tag is created by Chart Releaser after the release. 75 | - refs/tags/gatekeeper-policy-manager-** 76 | # exclude this expensive pipeline when releasing only a new version of the chart 77 | - refs/tags/helm-chart-** 78 | 79 | steps: 80 | - name: Build container image 81 | image: docker:dind 82 | pull: always 83 | environment: 84 | CONTAINER_IMAGE_NAME: gatekeeper-policy-manager 85 | CONTAINER_IMAGE_TAG: test-${DRONE_BUILD_NUMBER} 86 | DOCKERFILE: Dockerfile 87 | BUILD_CONTEXT: "." 88 | volumes: 89 | - name: dockerconfig 90 | path: /root/.docker/config.json 91 | - name: dockersock 92 | path: /var/run/docker.sock 93 | commands: 94 | - "apk add git" 95 | - "docker buildx create --name sighup-builder --use" 96 | - "docker buildx build --platform linux/amd64,linux/arm64 --pull -f $${DOCKERFILE} -t $${CONTAINER_IMAGE_NAME}:$${CONTAINER_IMAGE_TAG} $${BUILD_CONTEXT}" 97 | - "docker buildx build --load -t $${CONTAINER_IMAGE_NAME}:$${CONTAINER_IMAGE_TAG} $${BUILD_CONTEXT}" 98 | 99 | - name: Create Kind cluster 100 | image: docker:dind 101 | pull: always 102 | environment: 103 | KIND_VERSION: v0.24.0 104 | CLUSTER_VERSION: v1.31.0 105 | LOAD_IMAGE: gatekeeper-policy-manager:test-${DRONE_BUILD_NUMBER} 106 | CLUSTER_NAME: ${DRONE_REPO_NAME}-${DRONE_BUILD_NUMBER} 107 | volumes: 108 | - name: dockerconfig 109 | path: /root/.docker/config.json 110 | - name: dockersock 111 | path: /var/run/docker.sock 112 | commands: 113 | - wget -qO /usr/local/bin/kind "https://kind.sigs.k8s.io/dl/$${KIND_VERSION}/kind-$(uname)-amd64" 114 | - wget -qO /usr/local/bin/kubectl "https://storage.googleapis.com/kubernetes-release/release/$${CLUSTER_VERSION}/bin/linux/amd64/kubectl" 115 | - chmod +x /usr/local/bin/kind /usr/local/bin/kubectl 116 | - kind create cluster --name $${CLUSTER_NAME} --image registry.sighup.io/fury/kindest/node:$${CLUSTER_VERSION} 117 | - kind load docker-image $${LOAD_IMAGE} --name $${CLUSTER_NAME} 118 | - kind get kubeconfig --name $${CLUSTER_NAME} > kubeconfig.yml 119 | 120 | - name: E2E tests 121 | image: quay.io/sighup/e2e-testing:1.1.0_1.31.1_3.10.0_4.33.3 122 | network_mode: host 123 | environment: 124 | LOAD_IMAGE: gatekeeper-policy-manager:test-${DRONE_BUILD_NUMBER} 125 | commands: 126 | - export KUBECONFIG=$PWD/kubeconfig.yml 127 | - cd tests 128 | - kustomize edit set image quay.io/sighup/gatekeeper-policy-manager=$${LOAD_IMAGE} 129 | - cd - 130 | - bats -t tests/tests.sh 131 | 132 | - name: GPM port-forward 133 | image: quay.io/sighup/e2e-testing:1.1.0_1.31.1_3.10.0_4.33.3 134 | network_mode: host 135 | detach: true 136 | commands: 137 | - export KUBECONFIG=$PWD/kubeconfig.yml 138 | - kubectl port-forward svc/gatekeeper-policy-manager 8080:80 -n gatekeeper-system 139 | 140 | - name: UI tests 141 | # This must match the version in the package.json file 142 | image: mcr.microsoft.com/playwright:v1.30.0-focal 143 | network_mode: host 144 | commands: 145 | - cd tests/e2e && yarn install && yarn test 146 | 147 | - name: Print images diff on fail 148 | # This must match the version in the package.json file 149 | image: mcr.microsoft.com/playwright:v1.30.0-focal 150 | commands: 151 | - for f in tests/e2e/test-results/*/*diff.png; do echo $f; base64 -w 0 $f; echo; done; 152 | - "echo 'Use base64 to decode the images and see the diff'" 153 | when: 154 | status: 155 | - failure 156 | 157 | - name: Destroy Kind cluster 158 | image: docker:dind 159 | pull: always 160 | environment: 161 | KIND_VERSION: v0.24.0 162 | CLUSTER_NAME: ${DRONE_REPO_NAME}-${DRONE_BUILD_NUMBER} 163 | volumes: 164 | - name: dockerconfig 165 | path: /root/.docker/config.json 166 | - name: dockersock 167 | path: /var/run/docker.sock 168 | commands: 169 | - wget -qO /usr/local/bin/kind "https://kind.sigs.k8s.io/dl/$${KIND_VERSION}/kind-$(uname)-amd64" 170 | - chmod +x /usr/local/bin/kind 171 | - kind delete cluster --name $${CLUSTER_NAME} 172 | - rm kubeconfig.yml 173 | when: 174 | status: 175 | - success 176 | - failure 177 | 178 | - name: Push unstable image 179 | image: docker:dind 180 | pull: always 181 | environment: 182 | username: 183 | from_secret: quay_username 184 | password: 185 | from_secret: quay_password 186 | REGISTRY: quay.io 187 | IMAGE_NAME: sighup/gatekeeper-policy-manager 188 | DOCKERFILE: Dockerfile 189 | BUILD_CONTEXT: "." 190 | volumes: 191 | - name: dockersock 192 | path: /var/run/docker.sock 193 | commands: 194 | - "apk add git" 195 | - "docker login $${REGISTRY} -u $${username} -p $${password}" 196 | - "docker buildx create --name sighup-builder --use" 197 | - "docker buildx build --platform linux/amd64,linux/arm64 --pull --push -f $${DOCKERFILE} -t $${REGISTRY}/$${IMAGE_NAME}:${DRONE_COMMIT_SHA} -t $${REGISTRY}/$${IMAGE_NAME}:unstable $${BUILD_CONTEXT}" 198 | when: 199 | ref: 200 | include: 201 | - refs/heads/main 202 | 203 | - name: Push stable image 204 | image: docker:dind 205 | pull: always 206 | environment: 207 | username: 208 | from_secret: quay_username 209 | password: 210 | from_secret: quay_password 211 | REGISTRY: quay.io 212 | IMAGE_NAME: sighup/gatekeeper-policy-manager 213 | DOCKERFILE: Dockerfile 214 | BUILD_CONTEXT: "." 215 | volumes: 216 | - name: dockersock 217 | path: /var/run/docker.sock 218 | commands: 219 | - "apk add git" 220 | - "docker login $${REGISTRY} -u $${username} -p $${password}" 221 | - "docker buildx create --name sighup-builder --use" 222 | - "docker buildx build --platform linux/amd64,linux/arm64 --pull --push -f $${DOCKERFILE} -t $${REGISTRY}/$${IMAGE_NAME}:latest -t $${REGISTRY}/$${IMAGE_NAME}:${DRONE_TAG} $${BUILD_CONTEXT}" 223 | when: 224 | event: 225 | - tag 226 | 227 | - name: Package tar.gz 228 | image: alpine:latest 229 | pull: always 230 | commands: 231 | - tar -zcvf gatekeeper-policy-manager-${DRONE_TAG}.tar.gz manifests/ kustomization.yaml docs/releases/${DRONE_TAG}.md LICENSE README.md 232 | when: 233 | event: 234 | - tag 235 | 236 | - name: Prepare release notes 237 | image: quay.io/sighup/fury-release-notes-plugin:3.7_2.8.4 238 | settings: 239 | release_notes_file_path: release-notes.md 240 | when: 241 | event: 242 | - tag 243 | 244 | - name: Publish Preview Release 245 | image: plugins/github-release 246 | pull: always 247 | settings: 248 | api_key: 249 | from_secret: c3p0 250 | file_exists: overwrite 251 | files: 252 | - gatekeeper-policy-manager-${DRONE_TAG}.tar.gz 253 | prerelease: true 254 | overwrite: true 255 | title: "Release Candidate ${DRONE_TAG}" 256 | note: release-notes.md 257 | checksum: 258 | - md5 259 | - sha256 260 | when: 261 | ref: 262 | include: 263 | - refs/tags/v**-rc** 264 | 265 | - name: Publish Final Release 266 | image: plugins/github-release 267 | pull: always 268 | settings: 269 | api_key: 270 | from_secret: c3p0 271 | file_exists: overwrite 272 | files: 273 | - gatekeeper-policy-manager-${DRONE_TAG}.tar.gz 274 | prerelease: false 275 | overwrite: true 276 | title: "Release ${DRONE_TAG}" 277 | note: release-notes.md 278 | checksum: 279 | - md5 280 | - sha256 281 | when: 282 | ref: 283 | exclude: 284 | - refs/tags/v**-rc** 285 | include: 286 | - refs/tags/v** 287 | 288 | volumes: 289 | - name: dockerconfig 290 | host: 291 | path: /root/.docker/config.json 292 | - name: dockersock 293 | host: 294 | path: /var/run/docker.sock 295 | 296 | --- 297 | name: Release Helm Chart 298 | kind: pipeline 299 | type: docker 300 | 301 | depends_on: 302 | - QA 303 | - "Build test and release" 304 | 305 | trigger: 306 | ref: 307 | include: 308 | # Trigger the Helm Chart Releaser only when tagging 309 | - refs/tags/** 310 | exclude: 311 | # Don't release the chart when tagging Release Candidates 312 | - refs/tags/v**-rc.** 313 | # These kind of tags are generated by `cr` in this pipeline 314 | # we exclude them to avoid a loop. 315 | - refs/tags/gatekeeper-policy-manager-** 316 | 317 | steps: 318 | # We need to manually fetch the gh-pages branch because Drone by default 319 | # only checksout the current branch with a minimal depth 320 | # see: https://docs.drone.io/pipeline/docker/syntax/cloning/ 321 | - name: fetch-gh-pages-branch 322 | image: alpine/git 323 | commands: 324 | - git fetch origin gh-pages 325 | 326 | # We use GitHub Pages as Helm Repository and `cr` (Chart Releaser) 327 | # to help us publish the chart. 328 | - name: chart-releaser 329 | image: quay.io/helmpack/chart-releaser:v1.4.0 330 | environment: 331 | CR_OWNER: sighupio 332 | CR_GIT_REPO: gatekeeper-policy-manager 333 | CR_TOKEN: 334 | from_secret: c3p0 335 | commands: 336 | # For some reason we need to manually create the folder each time 337 | # see: https://github.com/helm/chart-releaser/issues/187 338 | - mkdir -p .cr-index 339 | # Package the chart into a tar.gz 340 | - cr package ./chart 341 | # Upload the tar.gz to a GitHub release 342 | - cr upload --skip-existing 343 | # Update the index.yaml and push it to GitHub Pages 344 | - cr index --push 345 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: bug 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Desktop (please complete the following information):** 27 | - OS: [e.g. iOS] 28 | - Browser [e.g. chrome, safari] 29 | - Version [e.g. 22] 30 | 31 | **Kubernetes (please complete the following information):** 32 | - Kubernetes version: [e.g. 1.30.0] 33 | - OPA Gatekeeper version: [e.g. 3.18.0] 34 | 35 | **Additional context** 36 | Add any other context about the problem here. 37 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: enhancement 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2022 SIGHUP s.r.l All rights reserved. 2 | # Use of this source code is governed by a BSD-style 3 | # license that can be found in the LICENSE file. 4 | 5 | version: 2 6 | updates: 7 | - package-ecosystem: "pip" # See documentation for possible values 8 | directory: "/app" # Location of package manifests 9 | schedule: 10 | interval: "weekly" 11 | 12 | - package-ecosystem: "npm" # See documentation for possible values 13 | directory: "/app/web-client" # Location of package manifests 14 | schedule: 15 | interval: "weekly" 16 | -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | 15 | 16 | ### Summary 💡 17 | 18 | 19 | 20 | 21 | Closes: 22 | 23 | 27 | 28 | ### Description 📝 29 | 30 | 37 | 38 | ### Breaking Changes 💔 39 | 40 | 46 | 47 | ### Tests performed 🧪 48 | 49 | 58 | 59 | ### Future work 🔧 60 | 61 | 65 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | env 2 | .venv 3 | .vscode 4 | __pycache__ 5 | launch.json 6 | app/static-content/* 7 | !app/static-content/logo.svg 8 | !app/static-content/semantic.min.css 9 | tests/e2e/test-results 10 | build/ 11 | node_modules/ 12 | static-content/ 13 | *.tgz 14 | pyrightconfig.json 15 | .mise.toml -------------------------------------------------------------------------------- /.rules/.htmlhintrc: -------------------------------------------------------------------------------- 1 | { 2 | "tagname-lowercase": true, 3 | "attr-lowercase": true, 4 | "attr-value-double-quotes": true, 5 | "attr-value-not-empty": false, 6 | "attr-no-duplication": true, 7 | "tag-pair": true, 8 | "tag-self-close": false, 9 | "id-unique": true, 10 | "src-not-empty": true, 11 | "title-require": true, 12 | "alt-require": true, 13 | "doctype-html5": true, 14 | "style-disabled": false, 15 | "inline-style-disabled": false, 16 | "inline-script-disabled": false, 17 | "space-tab-mixed-disabled": "space", 18 | "id-class-ad-disabled": false, 19 | "href-abs-or-rel": false, 20 | "attr-unsafe-chars": true, 21 | "head-script-disabled": true, 22 | 23 | "__COMMENT__": "From here, custom rules. Jinja2 requires special characters. Also there is some HTML templates.", 24 | 25 | "spec-char-escape": false, 26 | "id-class-value": false, 27 | "doctype-first": false 28 | } 29 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Gatekeeper Policy Manager Changelog 2 | 3 | Changelog has been moved to [docs/releases](docs/releases). There you'll find a file for each version. 4 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2022 SIGHUP s.r.l All rights reserved. 2 | # Use of this source code is governed by a BSD-style 3 | # license that can be found in the LICENSE file. 4 | FROM --platform=$BUILDPLATFORM node:lts-alpine AS node 5 | WORKDIR /web-client 6 | COPY app/web-client/package.json app/web-client/yarn.lock ./ 7 | RUN yarn install && yarn cache clean 8 | COPY app/web-client /web-client 9 | RUN yarn build 10 | 11 | 12 | FROM python:3.12-slim 13 | LABEL org.opencontainers.vendor="SIGHUP.io" 14 | LABEL org.opencontainers.image.authors="SIGHUP https://sighup.io" 15 | LABEL org.opencontainers.image.source="https://github.com/sighupio/gatekeeper-policy-manager" 16 | 17 | RUN groupadd -r gpm && useradd --no-log-init -r -g gpm gpm 18 | 19 | WORKDIR /app 20 | COPY --chown=gpm ./app /app 21 | COPY --from=node --chown=gpm /web-client/build/ /app/static-content/ 22 | # hadolint ignore=DL3013 23 | RUN pip install --no-cache-dir uv && uv pip install --system --no-cache-dir -r /app/requirements.txt 24 | USER 999 25 | EXPOSE 8080 26 | CMD ["gunicorn", "--bind=:8080", "--workers=2", "--threads=4", "--worker-class=gthread", "app:app"] 27 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2020, SIGHUP 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | * Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | * Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /MAINTENANCE.md: -------------------------------------------------------------------------------- 1 | # Gatekeeper Policy Manager Maintenance Guide 2 | 3 | This document is for GPM's maintainers. Here you will find intructions on how to perform maintenance-related activities in the project, like releasing a new version of the app, releasing a new version of the helm chart, etc. 4 | 5 | ## Releasing a new version of GPM 6 | 7 | Releasing a new version of GPM is done automatically with our CI, to trigger the release process follow the next steps: 8 | 9 | 1. Be sure that the current state of `main` branch is ready to be released. 10 | 2. Be sure that you don't have any local modifications to the files. 11 | 3. [Bump the chart version](#releasing-a-new-helm-chart-version). 12 | 4. Create release notes. 13 | 5. Commit all changes. 14 | 6. Run [`bumpversion`](https://github.com/c4urself/bump2version/#installation) to update the version strings automatically everywhere. 15 | 16 | For example, assuming the latest version is 1.0.0, to release a new patch version run: 17 | 18 | ```bash 19 | bumpversion --dry-run --verbose --new-version 1.0.1 bugfix 20 | ``` 21 | 22 | or to release a new minor: 23 | 24 | ```bash 25 | bumpversion --dry-run --verbose --new-version 1.1.0 minor 26 | ``` 27 | 28 | > Notice that the command includes a `--dry-run` flag, drop it to actually perform the change. You can drop the `--verbose` flag too. 29 | 30 | 5. `bumpversion` will create some commits and tags, you'll need to push the commits and then the tags 31 | 32 | ```bash 33 | git push 34 | git push origin 35 | ``` 36 | 37 | ## Releasing a new Helm Chart version 38 | 39 | You should update the version in `/chart/Chart.yaml` file each time you do a release of GPM and/or when the chart content gets updated. 40 | 41 | To release a new Helm Chart version: 42 | 43 | 1. Update the `/chart/Chart.yaml` file accordingly (i.e. bumping the version of the Chart) 44 | 45 | 2. Update the `/chart/README.md` file if you made changes to the chart. You can use [`frigate`](https://frigate.readthedocs.io/) to do it automatically: 46 | 47 | ```bash 48 | cd chart 49 | frigate gen . > README.md 50 | ``` 51 | 52 | > Notice that `frigate` will use the template in the file `/chart/.frigate` for formatting. 53 | 54 | 3. Tag and push the commit. This can be done as part of the release of a version of GPM or independently. 55 | 56 | > If you want to release just a new version of the chart, notice that the pipeline by default executes the Helm Release step only if the GPM release has been successful. You might need to disable the dependency between the pipeline steps. 57 | > 58 | > This is to avoid publishing a chart that references a failed build of GPM. 59 | > You can use a tag like `helm-chart-`. 60 | > 61 | > ⚠️ Notice that the tags `gatekeeper-policy-manager-` are used by helm/chart-releaser. 62 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 |

3 | 4 | Gatekeeper Policy Manager (GPM) 5 |

6 | 7 | 8 | [![Build Status](https://ci.sighup.io/api/badges/sighupio/gatekeeper-policy-manager/status.svg)](https://ci.sighup.io/sighupio/gatekeeper-policy-manager) 9 | ![GPM Release](https://img.shields.io/badge/GPM-v1.0.13-blue) 10 | ![Helm Chart Release](https://img.shields.io/badge/Helm%20Chart-v0.4.1-blue) 11 | ![Slack](https://img.shields.io/badge/slack-@kubernetes/fury-yellow.svg?logo=slack) 12 | ![License](https://img.shields.io/github/license/sighupio/gatekeeper-policy-manager) 13 | 14 | **Gatekeeper Policy Manager** is a simple *read-only* web UI for viewing OPA Gatekeeper policies' status in a Kubernetes Cluster. 15 | 16 | The target Kubernetes Cluster can be the same where GPM is running or some other [remote cluster(s) using a `kubeconfig` file](#multi-cluster-support). You can also run GPM [locally in a client machine](#running-locally) and connect to a remote cluster. 17 | 18 | GPM can display all the defined **Constraint Templates** with their rego code, all the Gatekeeper Configuration CRDs, and all the **Constraints** with their current status, violations, enforcement action, matches definitions, etc. 19 | 20 | [You can see some screenshots below](#screenshots). 21 | 22 | ## Requirements 23 | 24 | You'll need OPA Gatekeeper running in your cluster and at least some constraint templates and constraints defined to take advantage of this tool. 25 | 26 | ℹ You can easily deploy Gatekeeper to your cluster using the (also open source) [Kubernetes Fury OPA](https://github.com/sighupio/fury-kubernetes-opa) module. 27 | 28 | ## Deploying GPM 29 | 30 | ### Deploy using Kustomize 31 | 32 | To deploy Gatekeeper Policy Manager to your cluster, apply the provided [`kustomization`](kustomization.yaml) file running the following command: 33 | 34 | ```shell 35 | kubectl apply -k . 36 | ``` 37 | 38 | By default, this will create a deployment and a service both with the name `gatekeper-policy-manager` in the `gatekeeper-system` namespace. We invite you to take a look into the `kustomization.yaml` file to do further configuration. 39 | 40 | > The app can be run as a POD in a Kubernetes cluster or locally with a `kubeconfig` file. It will try its best to autodetect the correct configuration. 41 | 42 | Once you've deployed the application, if you haven't set up an ingress, you can access the web-UI using port-forward: 43 | 44 | ```bash 45 | kubectl -n gatekeeper-system port-forward svc/gatekeeper-policy-manager 8080:80 46 | ``` 47 | 48 | Then access it with your browser on: [http://127.0.0.1:8080](http://127.0.0.1:8080) 49 | 50 | ### Deploy using Helm 51 | 52 | It is also possible to deploy GPM using the [provided Helm Chart](./chart). 53 | 54 | First create a values file, for example `my-values.yaml`, with your custom values for the release. See the [chart's readme](./chart/README.md) and the [default values.yaml](./chart/values.yaml) for more information. 55 | 56 | Then, execute: 57 | 58 | ```bash 59 | helm repo add gpm https://sighupio.github.io/gatekeeper-policy-manager 60 | helm upgrade --install --namespace gatekeeper-system --set image.tag=v1.0.13 --values my-values.yaml gatekeeper-policy-manager gpm/gatekeeper-policy-manager 61 | ``` 62 | 63 | > don't forget to replace `my-values.yaml` with the path to your values file. 64 | 65 | ## Running locally 66 | 67 | GPM can also be run locally using docker and a `kubeconfig`, assuming that the `kubeconfig` file you want to use is located at `~/.kube/config` the command to run GPM locally would be: 68 | 69 | ```bash 70 | docker run -v ~/.kube/config:/home/gpm/.kube/config -p 8080:8080 quay.io/sighup/gatekeeper-policy-manager:v1.0.13 71 | ``` 72 | 73 | Then access it with your browser on: [http://127.0.0.1:8080](http://127.0.0.1:8080) 74 | 75 | > You can also run the flask app directly, see the [development section](#development) for further information. 76 | 77 | ## Configuration 78 | 79 | GPM is a stateless application, but it can be configured using environment variables. The possible configurations are: 80 | 81 | | Environment Variable Name | Description | Default | 82 | | --------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------- | 83 | | `GPM_SECRET_KEY` | The secret key used to generate tokens. **Change this value in production**. | `g8k1p3rp0l1c7m4n4g3r` | 84 | | `KUBECONFIG` | Path to a [kubeconfig](https://kubernetes.io/docs/concepts/configuration/organize-cluster-access-kubeconfig/) file, if provided while running inside a cluster this configuration file will be used instead of the cluster's API. | 85 | | `GPM_LOG_LEVEL` | Log level (see [python logging docs](https://docs.python.org/2/library/logging.html#levels) for available levels) | `INFO` | 86 | | `GPM_AUTH_ENABLED` | Enable Authentication current options: "Anonymous", "OIDC" | Anonymous | 87 | | `GPM_PREFERRED_URL_SCHEME` | URL scheme to be used while generating links. | `http` | 88 | | `GPM_OIDC_REDIRECT_DOMAIN` | The domain where GPM is being running. This is where the client will be redirected after authenticating | | 89 | | `GPM_OIDC_CLIENT_ID` | The Client ID used to authenticate against the OIDC Provider | | 90 | | `GPM_OIDC_CLIENT_SECRET` | The Client Secret used to authenticate against the OIDC Provider (optional) | | 91 | | `GPM_OIDC_ISSUER` | OIDC Issuer hostname (required if OIDC Auth is enabled) | | 92 | | `GPM_OIDC_AUTHORIZATION_ENDPOINT` | OIDC Authorization Endpoint (optional, setting this parameter disables the discovery of the rest of the provider configuration, set all the other values also if setting this one) | | 93 | | `GPM_OIDC_JWKS_URI` | OIDC JWKS URI (optional, setting this parameter disables the discovery of the rest of the provider configuration, set all the other values also if setting this one) | | 94 | | `GPM_OIDC_TOKEN_ENDPOINT` | OIDC TOKEN Endpoint (optional, setting this parameter disables the discovery of the rest of the provider configuration, set all the other values also if setting this one) | | 95 | | `GPM_OIDC_INTROSPECTION_ENDPOINT` | OIDC Introspection Endpoint (optional, setting this parameter disables the discovery of the rest of the provider configuration, set all the other values also if setting this one) | | 96 | | `GPM_OIDC_USERINFO_ENDPOINT` | OIDC Userinfo Endpoint (optional, setting this parameter disables the discovery of the rest of the provider configuration, set all the other values also if setting this one) | | 97 | | `GPM_OIDC_END_SESSION_ENDPOINT` | OIDC End Session Endpoint (optional, setting this parameter disables the discovery of the rest of the provider configuration, set all the other values also if setting this one) | | 98 | 99 | > ⚠️ Please notice that OIDC Authentication is in beta state. It has been tested to work with Keycloak as a provider. 100 | > 101 | > These environment variables are already provided and ready to be set in the [`manifests/enable-oidc.yaml`](manifests/enable-oidc.yaml) file. 102 | 103 | ### Multi-cluster support 104 | 105 | Since `v1.0.13` GPM has basic multi-cluster support when using a `kubeconfig` with more than one context. GPM will let you chose the context right from the UI. 106 | 107 | If you want to run GPM in a cluster but with multi-cluster support, it's as easy as mounting a `kubeconfig` file in GPM's pod(s) with the cluster access configuration and set the environment variable `KUBECONFIG` with the path to the mounted `kubeconfig` file. Or you can simply mount it in `/home/gpm/.kube/config` and GPM will detect it automatically. 108 | 109 | > Please remember that the user for the clusters should have the right permissions. You can use the [`manifests/rabc.yaml`](manifests/rbac.yaml) file as reference. 110 | > 111 | > Also note that the cluster where GPM is running should be able to reach the other clusters. 112 | 113 | When you run GPM locally, you are already using a `kubeconfig` file to connect to the clusters, now you should see all your defined contexts and you can switch between them easily from the UI. 114 | 115 | #### AWS IAM Authentication 116 | 117 | If you want to use a Kubeconfig with IAM Authentication, you'll need to customize GPM's container image because the IAM authentication uses external AWS binaries that are not included by default in the image. 118 | 119 | You can customize the container image with a `Dockerfile` like the following: 120 | 121 | ```Dockerfile 122 | FROM curlimages/curl:7.81.0 as downloader 123 | RUN curl https://github.com/kubernetes-sigs/aws-iam-authenticator/releases/download/v0.5.5/aws-iam-authenticator_0.5.5_linux_amd64 --output /tmp/aws-iam-authenticator 124 | RUN chmod +x /tmp/aws-iam-authenticator 125 | FROM quay.io/sighup/gatekeeper-policy-manager:v1.0.13 126 | COPY --from=downloader --chown=root:root /tmp/aws-iam-authenticator /usr/local/bin/ 127 | ``` 128 | 129 | You may need to add also the `aws` CLI, you can use the same approach as before. 130 | 131 | Make sure that your `kubeconfig` has the `apiVersion` set as `client.authentication.k8s.io/v1beta1` 132 | 133 | You can read more [in this issue](https://github.com/sighupio/gatekeeper-policy-manager/issues/330). 134 | 135 | ## Screenshots 136 | 137 | ![welcome](screenshots/01-home.png) 138 | 139 | ![Constraint Templates view](screenshots/02-constrainttemplates.png) 140 | 141 | ![Constraint Templates view rego code](screenshots/03-constrainttemplates.png) 142 | 143 | ![Constraint view](screenshots/04-constraints.png) 144 | 145 | ![Constraint view 2](screenshots/05-constraints.png) 146 | 147 | ![Constraint Report 3](screenshots/06-constraints.png) 148 | 149 | ![Configurations view 2](screenshots/07-configs.png) 150 | 151 | ![Cluster Selector](screenshots/08-multicluster.png) 152 | 153 | ## Development 154 | 155 | GPM is written in Python using the Flask framework for the backend and React with Elastic UI and the Fury theme for the frontend. 156 | 157 | To develop GPM, you'll need to create a Python 3 virtual environment, install all the dependencies specified in the provided `requirements.txt`, build the react frontend and you are good to start hacking. 158 | 159 | The following commands should get you up and running: 160 | 161 | ```bash 162 | # Build frontend and copy over to static folder 163 | $ pushd app/web-client 164 | $ yarn install && yarn build 165 | $ cp -r build/* ../static-content/ 166 | $ popd 167 | # Create a virtualenv 168 | $ python3 -m venv env 169 | # Activate it 170 | $ source ./env/bin/activate 171 | # Install all the dependencies 172 | $ pip install -r app/requirements.txt 173 | # Run the development server 174 | $ FLASK_APP=app/app.py flask run 175 | ``` 176 | 177 | > Access to a Kubernetes cluster with OPA Gatekeeper deployed is recommended to debug the application. 178 | > 179 | > You'll need an OIDC provider to test the OIDC authentication. You can use our [fury-kubernetes-keycloak](https://github.com/sighupio/fury-kubernetes-keycloak) module. 180 | 181 | ## Roadmap 182 | 183 | The following is a wishlist of features that we would like to add to GPM (in no particular order): 184 | 185 | - [x] List the constraints that are currently using a `ConstraintTemplate` 186 | - [ ] Polished OIDC authentication 187 | - [ ] LDAP authentication 188 | - [x] Better syntax highlighting for the rego code snippets 189 | - [x] Root-less docker image 190 | - [x] Multi-cluster view 191 | - [ ] Minimal write capabilities? 192 | - [ ] Rewrite app in Golang? 193 | 194 | Please, let us know if you are using GPM and what features would you like to have by creating an issue here on GitHub 💪🏻 195 | -------------------------------------------------------------------------------- /app/constraints.txt: -------------------------------------------------------------------------------- 1 | Beaker==1.13.0 2 | cachetools==5.5.0 3 | certifi==2024.8.30 4 | cffi==1.17.1 5 | charset-normalizer==3.4.0 6 | click==8.1.7 7 | cryptography==43.0.3 8 | defusedxml==0.7.1 9 | future==1.0.0 10 | google-auth==2.35.0 11 | idna==3.10 12 | importlib-resources==6.4.5 13 | itsdangerous==2.2.0 14 | Jinja2==3.1.4 15 | Mako==1.3.5 16 | MarkupSafe==2.1.5 17 | oauthlib==3.2.2 18 | oic==1.6.1 19 | pyasn1==0.6.1 20 | pyasn1-modules==0.4.0 21 | pycparser==2.22 22 | pycryptodomex==3.21.0 23 | pydantic==2.9.2 24 | pyjwkest==1.4.2 25 | python-dateutil==2.9.0.post0 26 | PyYAML==6.0.2 27 | requests==2.32.3 28 | requests-oauthlib==2.0.0 29 | rsa==4.9 30 | six==1.16.0 31 | typing-extensions==4.12.2 32 | urllib3==2.2.3 33 | websocket-client==1.8.0 34 | Werkzeug==3.0.6 35 | zipp==3.20.2 36 | -------------------------------------------------------------------------------- /app/requirements.txt: -------------------------------------------------------------------------------- 1 | -c constraints.txt 2 | Flask==3.0.3 3 | Flask-pyoidc==3.14.3 4 | flask-cors==5.0.0 5 | gunicorn==23.0.0 6 | kubernetes==31.0.0 7 | setuptools>=65.5.1 # not directly required, pinned by Snyk to avoid a vulnerability 8 | -------------------------------------------------------------------------------- /app/static-content/logo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/templates/constraints-report.html: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | Gatekeeper Policy Manager - {{ title }} Violations Report 12 | 13 | 14 | 20 | 21 | 22 | 23 | {% if constraints|length == 0 %} 24 |
25 |
26 | There are no Constraint defined 27 |
28 |
29 | We didn't find any Constraint CRDs defined in the cluster. 30 |
31 |
32 | {% else %} 33 | {% set limited_view = [] %} 34 |
35 |
36 |

GPM - Constraints Violations Report

37 |
38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | {% for constraint in constraints %} 51 | {% if constraint.status.totalViolations is defined and constraint.status.totalViolations > 0 %} 52 | {% if constraint.status.totalViolations > constraint.status.violations|length %} 53 | {{ limited_view.append(constraint.metadata.name) or '' }} 54 | {% endif %} 55 | {% for violation in constraint.status.violations %} 56 | 57 | 58 | 61 | 62 | 63 | 64 | 65 | 66 | {% endfor %} 67 | {% elif constraint.status.totalViolations is not defined %} 68 |
Violations for Constraint 69 | {{constraint.metadata.name}} are unkown. This probably means that the Constraint has not 70 | been processed by Gatekeeper yet. Please, try refreshing the page.
71 | {% endif %} 72 | {% endfor %} 73 | 74 |
ConstraintActionKindNamespaceNameMessage
{{ constraint.metadata.name }}{{ 60 | violation.enforcementAction }}{{ violation.kind }}{{ violation.namespace }}{{ violation.name }}{{ violation.message }}
75 |
76 | {% if limited_view %} 77 |
78 | 79 |
80 |
Not all violations are being shown
81 | Gatekeeper's configuration is limiting the amount of audit violations being shown for Constraints 82 | {{ limited_view|join(', ') }}. 83 |
See Gatekeeper's --constraint-violations-limit 84 | audit configuration flag. 85 |
86 |
87 | {% endif %} 88 |
89 |

violations report generated by GPM running at {{ url_for('index', _external=True) }} on {{ timestamp 90 | }}

91 |
92 | {% endif %} 93 |
94 |
95 | 96 | 97 | -------------------------------------------------------------------------------- /app/web-client/.env: -------------------------------------------------------------------------------- 1 | REACT_APP_LOCAL_GPM_SERVER_URL=http://localhost:5000/ 2 | -------------------------------------------------------------------------------- /app/web-client/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | -------------------------------------------------------------------------------- /app/web-client/README.md: -------------------------------------------------------------------------------- 1 | # Getting Started with Create React App 2 | 3 | This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app). 4 | 5 | ## Available Scripts 6 | 7 | In the project directory, you can run: 8 | 9 | ### `yarn start` 10 | 11 | Runs the app in the development mode.\ 12 | Open [http://localhost:3000](http://localhost:3000) to view it in the browser. 13 | 14 | The page will reload if you make edits.\ 15 | You will also see any lint errors in the console. 16 | 17 | ### `yarn test` 18 | 19 | Launches the test runner in the interactive watch mode.\ 20 | See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information. 21 | 22 | ### `yarn build` 23 | 24 | Builds the app for production to the `build` folder.\ 25 | It correctly bundles React in production mode and optimizes the build for the best performance. 26 | 27 | The build is minified and the filenames include the hashes.\ 28 | Your app is ready to be deployed! 29 | 30 | See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information. 31 | 32 | ### `yarn eject` 33 | 34 | **Note: this is a one-way operation. Once you `eject`, you can’t go back!** 35 | 36 | If you aren’t satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project. 37 | 38 | Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you’re on your own. 39 | 40 | You don’t have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn’t feel obligated to use this feature. However we understand that this tool wouldn’t be useful if you couldn’t customize it when you are ready for it. 41 | 42 | ## Learn More 43 | 44 | You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started). 45 | 46 | To learn React, check out the [React documentation](https://reactjs.org/). 47 | -------------------------------------------------------------------------------- /app/web-client/fork-ts-checker.config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2017-present SIGHUP s.r.l All rights reserved. 3 | * Use of this source code is governed by a BSD-style 4 | * license that can be found in the LICENSE file. 5 | */ 6 | 7 | module.exports = { 8 | logger: { 9 | log: (message) => console.log(message), 10 | error: (message) => console.error(message) 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /app/web-client/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "gatekeeper-policy-manager-frontend", 3 | "version": "1.0.0", 4 | "description": "Gatekeeper Policy Manager Frontend", 5 | "author": "Ramiro Algozino ", 6 | "license": "BSD-2-Clause", 7 | "repository": { 8 | "type": "git", 9 | "url": "https://github.com/sighupio/gatekeeper-policy-manager" 10 | }, 11 | "dependencies": { 12 | "@elastic/eui": "^97.2.0", 13 | "@emotion/css": "^11.13.4", 14 | "@emotion/react": "^11.13.3", 15 | "@testing-library/jest-dom": "^6.6.2", 16 | "@testing-library/react": "^12.1.5", 17 | "@testing-library/user-event": "^14.5.2", 18 | "@types/jest": "^29.5.14", 19 | "@types/node": "^22.8.1", 20 | "@types/react": "^17.0.20", 21 | "@types/react-dom": "^18.3.1", 22 | "lodash.clonedeep": "^4.5.0", 23 | "prop-types": "^15.8.1", 24 | "react": "^17.0.2", 25 | "react-dom": "^18.3.1", 26 | "react-json-tree": "^0.19.0", 27 | "react-router-dom": "^6.27.0", 28 | "react-scripts": "5.0.1", 29 | "sass": "^1.80.4", 30 | "typescript": "^5.6.3", 31 | "web-vitals": "^4.2.4" 32 | }, 33 | "resolutions": { 34 | "fork-ts-checker-webpack-plugin": "^8.0.0", 35 | "@typescript-eslint/parser": "^6.7.0", 36 | "@typescript-eslint/eslint-plugin": "^6.7.0", 37 | "eslint": "^8.49.0" 38 | }, 39 | "scripts": { 40 | "start": "react-scripts start", 41 | "build": "react-scripts build", 42 | "test": "react-scripts test", 43 | "eject": "react-scripts eject" 44 | }, 45 | "eslintConfig": { 46 | "extends": [ 47 | "react-app", 48 | "react-app/jest" 49 | ] 50 | }, 51 | "browserslist": { 52 | "production": [ 53 | ">0.2%", 54 | "not dead", 55 | "not op_mini all" 56 | ], 57 | "development": [ 58 | "last 1 chrome version", 59 | "last 1 firefox version", 60 | "last 1 safari version" 61 | ] 62 | }, 63 | "devDependencies": { 64 | "@elastic/datemath": "^5.0.3", 65 | "@types/lodash.clonedeep": "^4.5.9", 66 | "@types/react-router-dom": "^5.3.3", 67 | "moment": "^2.30.1" 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /app/web-client/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sighupio/gatekeeper-policy-manager/d045289c36afbd2632f75dec38bc690130fd4360/app/web-client/public/favicon.ico -------------------------------------------------------------------------------- /app/web-client/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 19 | 20 | 24 | 25 | 34 | Gatekeeper Policy Manager 35 | 36 | 37 | 38 |
39 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /app/web-client/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sighupio/gatekeeper-policy-manager/d045289c36afbd2632f75dec38bc690130fd4360/app/web-client/public/logo192.png -------------------------------------------------------------------------------- /app/web-client/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sighupio/gatekeeper-policy-manager/d045289c36afbd2632f75dec38bc690130fd4360/app/web-client/public/logo512.png -------------------------------------------------------------------------------- /app/web-client/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "GPM", 3 | "name": "Gatekeeper Policy Manager", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /app/web-client/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /app/web-client/public/touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sighupio/gatekeeper-policy-manager/d045289c36afbd2632f75dec38bc690130fd4360/app/web-client/public/touch-icon.png -------------------------------------------------------------------------------- /app/web-client/src/App.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2017-present SIGHUP s.r.l All rights reserved. 3 | * Use of this source code is governed by a BSD-style 4 | * license that can be found in the LICENSE file. 5 | */ 6 | 7 | /* stylelint-disable selector-class-pattern, max-line-length */ 8 | .gpm-page { 9 | width: 100%; 10 | } 11 | 12 | .gpm-page .euiPanel.euiPanel--plain { 13 | transition: 0.75s ease-out all; 14 | } 15 | 16 | .gpm-page .euiPanel.euiPanel--plain.highlighted { 17 | background-color: rgb(104 40 140 / 7%); 18 | box-shadow: 19 | 0 0.9px 4px -1px rgb(104 40 140 / 18%), 20 | 0 2.6px 8px -1px rgb(104 40 140 / 16%), 21 | 0 5.7px 12px -1px rgb(104 40 140 / 15%), 22 | 0 15px 15px -1px rgb(104 40 140 / 14%); 23 | } 24 | 25 | .gpm-page .euiCodeBlock { 26 | filter: invert(1); 27 | background: white; 28 | } 29 | 30 | .gpm-page .euiCodeBlock .token.comment, 31 | .gpm-page .euiCodeBlock .token.block-comment, 32 | .gpm-page .euiCodeBlock .token.prolog, 33 | .gpm-page .euiCodeBlock .token.doctype, 34 | .gpm-page .euiCodeBlock .token.cdata { 35 | color: #666; 36 | } 37 | 38 | .gpm-page .euiCodeBlock .token.punctuation { 39 | color: #333; 40 | } 41 | 42 | .gpm-page .euiCodeBlock .token.tag, 43 | .gpm-page .euiCodeBlock .token.attr-name, 44 | .gpm-page .euiCodeBlock .token.namespace, 45 | .gpm-page .euiCodeBlock .token.deleted { 46 | color: #1d8885; 47 | } 48 | 49 | .gpm-page .euiCodeBlock .token.function-name { 50 | color: #9e6933; 51 | } 52 | 53 | .gpm-page .euiCodeBlock .token.boolean, 54 | .gpm-page .euiCodeBlock .token.number, 55 | .gpm-page .euiCodeBlock .token.function { 56 | color: #0f72b6; 57 | } 58 | 59 | .gpm-page .euiCodeBlock .token.property, 60 | .gpm-page .euiCodeBlock .token.class-name, 61 | .gpm-page .euiCodeBlock .token.constant, 62 | .gpm-page .euiCodeBlock .token.symbol { 63 | color: #073aaa; 64 | } 65 | 66 | .gpm-page .euiCodeBlock .token.selector, 67 | .gpm-page .euiCodeBlock .token.important, 68 | .gpm-page .euiCodeBlock .token.atrule, 69 | .gpm-page .euiCodeBlock .token.keyword, 70 | .gpm-page .euiCodeBlock .token.builtin { 71 | color: #336632; 72 | } 73 | 74 | .gpm-page .euiCodeBlock .token.string, 75 | .gpm-page .euiCodeBlock .token.char, 76 | .gpm-page .euiCodeBlock .token.attr-value, 77 | .gpm-page .euiCodeBlock .token.regex, 78 | .gpm-page .euiCodeBlock .token.variable { 79 | color: #813966; 80 | } 81 | 82 | .gpm-page .euiCodeBlock .token.operator, 83 | .gpm-page .euiCodeBlock .token.entity, 84 | .gpm-page .euiCodeBlock .token.url { 85 | color: #983233; 86 | } 87 | 88 | .gpm-page .euiCodeBlock .token.important, 89 | .gpm-page .euiCodeBlock .token.bold { 90 | font-weight: bold; 91 | } 92 | 93 | .gpm-page .euiCodeBlock .token.italic { 94 | font-style: italic; 95 | } 96 | 97 | .gpm-page .euiCodeBlock .token.entity { 98 | cursor: help; 99 | } 100 | 101 | .gpm-page .euiCodeBlock .token.inserted { 102 | color: #ff7fff; 103 | } 104 | -------------------------------------------------------------------------------- /app/web-client/src/App.test.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2017-present SIGHUP s.r.l All rights reserved. 3 | * Use of this source code is governed by a BSD-style 4 | * license that can be found in the LICENSE file. 5 | */ 6 | 7 | import React from "react"; 8 | import { render, screen } from "@testing-library/react"; 9 | import App from "./App"; 10 | 11 | test("renders learn react link", () => { 12 | render(); 13 | const linkElement = screen.getByText(/learn react/i); 14 | expect(linkElement).toBeInTheDocument(); 15 | }); 16 | -------------------------------------------------------------------------------- /app/web-client/src/App.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2017-present SIGHUP s.r.l All rights reserved. 3 | * Use of this source code is governed by a BSD-style 4 | * license that can be found in the LICENSE file. 5 | */ 6 | 7 | import React from "react"; 8 | import ContextProvider from "./AppContextProvider"; 9 | import { EuiProvider } from "@elastic/eui"; 10 | import { Routes, Route, useLocation } from "react-router-dom"; 11 | import { Home } from "./pages/Home"; 12 | import { Header } from "./components/Header"; 13 | import { Footer } from "./components/Footer"; 14 | import { ConstraintTemplates } from "./pages/ConstraintTemplates"; 15 | import { Constraints } from "./pages/Constraints"; 16 | import { Configurations } from "./pages/Configurations"; 17 | import { Error } from "./pages/Error"; 18 | import { Logout } from "./pages/Logout"; 19 | import { NotFound } from "./pages/NotFound"; 20 | import { theme } from "./theme"; 21 | import "./App.scss"; 22 | 23 | function App() { 24 | const { pathname } = useLocation(); 25 | 26 | return ( 27 | 31 | 32 | {pathname === "/logout" ? null :
} 33 | 34 | 35 | } /> 36 | } /> 37 | 38 | 39 | } /> 40 | } /> 41 | 42 | 43 | } /> 44 | } /> 45 | 46 | 47 | } /> 48 | } /> 49 | 50 | } /> 51 | } /> 52 | } /> 53 | 54 |