├── docs
├── releases
│ ├── v0.1.md
│ ├── v1.0.4.md
│ ├── v1.0.3.md
│ ├── v1.0.6.md
│ ├── v1.0.7.md
│ ├── v0.3.0.md
│ ├── v1.0.11.md
│ ├── v1.0.14.md
│ ├── v1.0.12.md
│ ├── v1.0.13.md
│ ├── v1.0.9.md
│ ├── v1.0.5.md
│ ├── v1.0.8.md
│ ├── v0.2.md
│ ├── v1.0.2.md
│ ├── v1.0.1.md
│ ├── v1.0.0.md
│ ├── v0.4.0.md
│ ├── v0.4.2.md
│ ├── v1.0.10.md
│ ├── v0.4.1.md
│ ├── v1.1.0.md
│ ├── v0.5.1.md
│ └── v0.5.0.md
└── assets
│ └── logo.svg
├── app
├── web-client
│ ├── .env
│ ├── public
│ │ ├── robots.txt
│ │ ├── favicon.ico
│ │ ├── logo192.png
│ │ ├── logo512.png
│ │ ├── touch-icon.png
│ │ ├── manifest.json
│ │ └── index.html
│ ├── src
│ │ ├── assets
│ │ │ ├── fonts
│ │ │ │ ├── Poppins-Bold.ttf
│ │ │ │ ├── Poppins-Light.ttf
│ │ │ │ ├── Poppins-Medium.ttf
│ │ │ │ ├── Poppins-Regular.ttf
│ │ │ │ ├── JetBrainsMono-Bold.ttf
│ │ │ │ ├── Poppins-SemiBold.ttf
│ │ │ │ └── JetBrainsMono-Regular.ttf
│ │ │ ├── shield-active.svg
│ │ │ ├── shield-inactive.svg
│ │ │ ├── github-logo.svg
│ │ │ └── gpm-logo.svg
│ │ ├── react-app-env.d.ts
│ │ ├── pages
│ │ │ ├── ConstraintTemplates
│ │ │ │ ├── Style.scss
│ │ │ │ ├── index.ts
│ │ │ │ └── types.ts
│ │ │ ├── Home
│ │ │ │ ├── index.ts
│ │ │ │ └── Component.tsx
│ │ │ ├── Error
│ │ │ │ ├── index.ts
│ │ │ │ ├── types.ts
│ │ │ │ └── Component.tsx
│ │ │ ├── Logout
│ │ │ │ ├── index.ts
│ │ │ │ └── Component.tsx
│ │ │ ├── NotFound
│ │ │ │ ├── index.ts
│ │ │ │ └── Component.tsx
│ │ │ ├── Constraints
│ │ │ │ ├── index.ts
│ │ │ │ ├── Style.scss
│ │ │ │ └── types.ts
│ │ │ ├── Configurations
│ │ │ │ ├── index.ts
│ │ │ │ ├── Style.scss
│ │ │ │ ├── types.ts
│ │ │ │ └── Component.tsx
│ │ │ ├── theme.ts
│ │ │ └── types.ts
│ │ ├── components
│ │ │ ├── Footer
│ │ │ │ ├── index.ts
│ │ │ │ ├── Style.scss
│ │ │ │ └── Component.tsx
│ │ │ └── Header
│ │ │ │ ├── index.ts
│ │ │ │ ├── Style.scss
│ │ │ │ └── Component.tsx
│ │ ├── setupTests.ts
│ │ ├── App.test.tsx
│ │ ├── hooks
│ │ │ ├── useScrollToHash.tsx
│ │ │ └── useCurrentElementInView.tsx
│ │ ├── reportWebVitals.ts
│ │ ├── theme.ts
│ │ ├── AppContext.ts
│ │ ├── index.tsx
│ │ ├── utils.tsx
│ │ ├── App.tsx
│ │ ├── App.scss
│ │ ├── index.scss
│ │ └── AppContextProvider.tsx
│ ├── fork-ts-checker.config.js
│ ├── .gitignore
│ ├── tsconfig.json
│ ├── package.json
│ └── README.md
├── requirements.txt
├── constraints.txt
└── templates
│ └── constraints-report.html
├── renovate.json
├── .dockerignore
├── screenshots
├── 01-home.png
├── 07-configs.png
├── 04-constraints.png
├── 05-constraints.png
├── 06-constraints.png
├── 08-multicluster.png
├── 02-constrainttemplates.png
└── 03-constrainttemplates.png
├── CHANGELOG.md
├── tests
├── e2e
│ ├── tests
│ │ ├── home.spec.ts-snapshots
│ │ │ └── page-home-snapshot-1-linux.png
│ │ ├── constraints.spec.ts-snapshots
│ │ │ └── page-constraints-snapshot-1-linux.png
│ │ ├── configurations.spec.ts-snapshots
│ │ │ └── page-configurations-snapshot-1-linux.png
│ │ ├── constrainttemplates.spec.ts-snapshots
│ │ │ └── page-constrainttemplates-snapshot-1-linux.png
│ │ ├── home.spec.ts
│ │ ├── configurations.spec.ts
│ │ ├── constraints.spec.ts
│ │ └── constrainttemplates.spec.ts
│ ├── .gitignore
│ ├── playwright.config.js
│ ├── package.json
│ ├── README.md
│ └── yarn.lock
├── deploy-patch.yaml
├── kustomization.yaml
├── helper.bash
├── e2e-tests.yaml
└── tests.sh
├── .gitignore
├── chart
├── templates
│ ├── secret-multicluster.yaml
│ ├── secret-oidc.yaml
│ ├── secret.yaml
│ ├── serviceaccount.yaml
│ ├── service.yaml
│ ├── hpa.yaml
│ ├── rbac.yaml
│ ├── NOTES.txt
│ ├── ingress.yaml
│ ├── _helpers.tpl
│ └── deployment.yaml
├── .frigate
├── Chart.yaml
├── LICENSE
├── README.md
└── values.yaml
├── manifests
├── service.yaml
├── multi-cluster.yaml
├── ingress.yaml
├── rbac.yaml
├── deployment.yaml
└── enable-oidc.yaml
├── .bumpversion.cfg
├── .github
├── dependabot.yml
├── ISSUE_TEMPLATE
│ ├── feature_request.md
│ └── bug_report.md
└── pull_request_template.md
├── .rules
└── .htmlhintrc
├── Dockerfile
├── kustomization.yaml
├── LICENSE
├── MAINTENANCE.md
├── .drone.yml
└── README.md
/docs/releases/v0.1.md:
--------------------------------------------------------------------------------
1 | # v0.1
2 |
3 | First release.
4 |
--------------------------------------------------------------------------------
/app/web-client/.env:
--------------------------------------------------------------------------------
1 | REACT_APP_LOCAL_GPM_SERVER_URL=http://localhost:5000/
2 |
--------------------------------------------------------------------------------
/renovate.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": [
3 | "config:base"
4 | ]
5 | }
6 |
--------------------------------------------------------------------------------
/.dockerignore:
--------------------------------------------------------------------------------
1 | **/node_modules
2 | **/build
3 | **/chart
4 | **/manifests
5 | **/screenshots
6 | **/tests
7 |
--------------------------------------------------------------------------------
/app/web-client/public/robots.txt:
--------------------------------------------------------------------------------
1 | # https://www.robotstxt.org/robotstxt.html
2 | User-agent: *
3 | Disallow:
4 |
--------------------------------------------------------------------------------
/screenshots/01-home.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sighupio/gatekeeper-policy-manager/HEAD/screenshots/01-home.png
--------------------------------------------------------------------------------
/screenshots/07-configs.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sighupio/gatekeeper-policy-manager/HEAD/screenshots/07-configs.png
--------------------------------------------------------------------------------
/screenshots/04-constraints.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sighupio/gatekeeper-policy-manager/HEAD/screenshots/04-constraints.png
--------------------------------------------------------------------------------
/screenshots/05-constraints.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sighupio/gatekeeper-policy-manager/HEAD/screenshots/05-constraints.png
--------------------------------------------------------------------------------
/screenshots/06-constraints.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sighupio/gatekeeper-policy-manager/HEAD/screenshots/06-constraints.png
--------------------------------------------------------------------------------
/screenshots/08-multicluster.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sighupio/gatekeeper-policy-manager/HEAD/screenshots/08-multicluster.png
--------------------------------------------------------------------------------
/app/web-client/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sighupio/gatekeeper-policy-manager/HEAD/app/web-client/public/favicon.ico
--------------------------------------------------------------------------------
/app/web-client/public/logo192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sighupio/gatekeeper-policy-manager/HEAD/app/web-client/public/logo192.png
--------------------------------------------------------------------------------
/app/web-client/public/logo512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sighupio/gatekeeper-policy-manager/HEAD/app/web-client/public/logo512.png
--------------------------------------------------------------------------------
/app/web-client/public/touch-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sighupio/gatekeeper-policy-manager/HEAD/app/web-client/public/touch-icon.png
--------------------------------------------------------------------------------
/screenshots/02-constrainttemplates.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sighupio/gatekeeper-policy-manager/HEAD/screenshots/02-constrainttemplates.png
--------------------------------------------------------------------------------
/screenshots/03-constrainttemplates.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sighupio/gatekeeper-policy-manager/HEAD/screenshots/03-constrainttemplates.png
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/app/web-client/src/assets/fonts/Poppins-Bold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sighupio/gatekeeper-policy-manager/HEAD/app/web-client/src/assets/fonts/Poppins-Bold.ttf
--------------------------------------------------------------------------------
/app/web-client/src/assets/fonts/Poppins-Light.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sighupio/gatekeeper-policy-manager/HEAD/app/web-client/src/assets/fonts/Poppins-Light.ttf
--------------------------------------------------------------------------------
/app/web-client/src/assets/fonts/Poppins-Medium.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sighupio/gatekeeper-policy-manager/HEAD/app/web-client/src/assets/fonts/Poppins-Medium.ttf
--------------------------------------------------------------------------------
/app/web-client/src/assets/fonts/Poppins-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sighupio/gatekeeper-policy-manager/HEAD/app/web-client/src/assets/fonts/Poppins-Regular.ttf
--------------------------------------------------------------------------------
/app/web-client/src/assets/fonts/JetBrainsMono-Bold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sighupio/gatekeeper-policy-manager/HEAD/app/web-client/src/assets/fonts/JetBrainsMono-Bold.ttf
--------------------------------------------------------------------------------
/app/web-client/src/assets/fonts/Poppins-SemiBold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sighupio/gatekeeper-policy-manager/HEAD/app/web-client/src/assets/fonts/Poppins-SemiBold.ttf
--------------------------------------------------------------------------------
/app/web-client/src/assets/fonts/JetBrainsMono-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sighupio/gatekeeper-policy-manager/HEAD/app/web-client/src/assets/fonts/JetBrainsMono-Regular.ttf
--------------------------------------------------------------------------------
/tests/e2e/tests/home.spec.ts-snapshots/page-home-snapshot-1-linux.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sighupio/gatekeeper-policy-manager/HEAD/tests/e2e/tests/home.spec.ts-snapshots/page-home-snapshot-1-linux.png
--------------------------------------------------------------------------------
/docs/releases/v1.0.4.md:
--------------------------------------------------------------------------------
1 | # GPM v1.0.4
2 |
3 | Welcome to the release of Gatekeeper Policy Manager version 1.0.4.
4 |
5 | This is a maintenance release including improved error messages and updates to all GPM dependencies.
6 |
7 |
--------------------------------------------------------------------------------
/tests/e2e/tests/constraints.spec.ts-snapshots/page-constraints-snapshot-1-linux.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sighupio/gatekeeper-policy-manager/HEAD/tests/e2e/tests/constraints.spec.ts-snapshots/page-constraints-snapshot-1-linux.png
--------------------------------------------------------------------------------
/app/requirements.txt:
--------------------------------------------------------------------------------
1 | -c constraints.txt
2 | Flask==3.1.2
3 | Flask-pyoidc==3.14.3
4 | flask-cors==6.0.1
5 | gunicorn==23.0.0
6 | kubernetes==33.1.0
7 | setuptools>=65.5.1 # not directly required, pinned by Snyk to avoid a vulnerability
8 |
--------------------------------------------------------------------------------
/tests/e2e/tests/configurations.spec.ts-snapshots/page-configurations-snapshot-1-linux.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sighupio/gatekeeper-policy-manager/HEAD/tests/e2e/tests/configurations.spec.ts-snapshots/page-configurations-snapshot-1-linux.png
--------------------------------------------------------------------------------
/tests/e2e/tests/constrainttemplates.spec.ts-snapshots/page-constrainttemplates-snapshot-1-linux.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sighupio/gatekeeper-policy-manager/HEAD/tests/e2e/tests/constrainttemplates.spec.ts-snapshots/page-constrainttemplates-snapshot-1-linux.png
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | env
2 | .venv
3 | .vscode
4 | __pycache__
5 | launch.json
6 | app/static-content/*
7 | !app/static-content/semantic.min.css
8 | tests/e2e/test-results
9 | build/
10 | node_modules/
11 | static-content/
12 | *.tgz
13 | pyrightconfig.json
14 | .mise.toml
--------------------------------------------------------------------------------
/docs/releases/v1.0.3.md:
--------------------------------------------------------------------------------
1 | # GPM v1.0.3
2 |
3 | Welcome to the release of Gatekeeper Policy Manager version 1.0.3.
4 |
5 | This is a patch release including updates to all GPM dependencies and moving to Python 3.11.
6 |
7 | No changes have been done to GPM istself.
8 |
--------------------------------------------------------------------------------
/app/web-client/src/react-app-env.d.ts:
--------------------------------------------------------------------------------
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 | ///
8 |
--------------------------------------------------------------------------------
/app/web-client/src/pages/ConstraintTemplates/Style.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-next-line selector-class-pattern */
8 |
--------------------------------------------------------------------------------
/app/web-client/src/pages/Home/index.ts:
--------------------------------------------------------------------------------
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 HomeComponent from "./Component";
8 |
9 | export { HomeComponent as Home };
10 |
--------------------------------------------------------------------------------
/app/web-client/src/pages/Error/index.ts:
--------------------------------------------------------------------------------
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 ErrorComponent from "./Component";
8 |
9 | export { ErrorComponent as Error };
10 |
--------------------------------------------------------------------------------
/docs/releases/v1.0.6.md:
--------------------------------------------------------------------------------
1 | # GPM v1.0.6
2 |
3 | Welcome to the release of Gatekeeper Policy Manager version 1.0.6 🎉
4 |
5 | This is a maintenance release including:
6 |
7 | - Bumped all JavaScript and Python dependencies
8 | - Helm Chart: Added support for annotations to the Kuberntes service (thanks @Markieta for the PR)
9 |
10 |
--------------------------------------------------------------------------------
/app/web-client/src/pages/Logout/index.ts:
--------------------------------------------------------------------------------
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 LogoutComponent from "./Component";
8 |
9 | export { LogoutComponent as Logout };
10 |
--------------------------------------------------------------------------------
/app/web-client/src/components/Footer/index.ts:
--------------------------------------------------------------------------------
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 FooterComponent from "./Component";
8 |
9 | export { FooterComponent as Footer };
10 |
--------------------------------------------------------------------------------
/app/web-client/src/components/Header/index.ts:
--------------------------------------------------------------------------------
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 HeaderComponent from "./Component";
8 |
9 | export { HeaderComponent as Header };
10 |
--------------------------------------------------------------------------------
/app/web-client/src/pages/NotFound/index.ts:
--------------------------------------------------------------------------------
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 NotFoundComponent from "./Component";
8 |
9 | export { NotFoundComponent as NotFound };
10 |
--------------------------------------------------------------------------------
/app/web-client/src/pages/Constraints/index.ts:
--------------------------------------------------------------------------------
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 ConstraintsComponent from "./Component";
8 |
9 | export { ConstraintsComponent as Constraints };
10 |
--------------------------------------------------------------------------------
/docs/releases/v1.0.7.md:
--------------------------------------------------------------------------------
1 | # GPM v1.0.7
2 |
3 | Welcome to the release of Gatekeeper Policy Manager version 1.0.7 🎉
4 |
5 | This is a maintenance release including:
6 |
7 | - Bumped all JavaScript and Python dependencies
8 | - Helm Chart: Added support for specifing a custom command and arguments for GPM's container (thanks @Markieta for the PR)
9 |
10 |
--------------------------------------------------------------------------------
/app/web-client/src/pages/Configurations/index.ts:
--------------------------------------------------------------------------------
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 ConfigurationsComponent from "./Component";
8 |
9 | export { ConfigurationsComponent as Configurations };
10 |
--------------------------------------------------------------------------------
/app/web-client/src/pages/ConstraintTemplates/index.ts:
--------------------------------------------------------------------------------
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 ConstraintTemplatesComponent from "./Component";
8 |
9 | export { ConstraintTemplatesComponent as ConstraintTemplates };
10 |
--------------------------------------------------------------------------------
/app/web-client/src/pages/Error/types.ts:
--------------------------------------------------------------------------------
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 { BackendError } from "../types";
8 |
9 | export interface ErrorPageState {
10 | error: BackendError;
11 | entity: string;
12 | }
13 |
--------------------------------------------------------------------------------
/docs/releases/v0.3.0.md:
--------------------------------------------------------------------------------
1 | # v0.3.0
2 |
3 | - Added support for offline frontend usage.
4 | - Added favicon.
5 | - Updated base image and pinned OS-level dependencies packages versions.
6 | - Added message when there are no Constraint Templates instead of showing an empty view.
7 | - Fixed crash when constraints don't have any match criteria defined.
8 | - Improved error handling in general
9 |
--------------------------------------------------------------------------------
/docs/releases/v1.0.11.md:
--------------------------------------------------------------------------------
1 | # GPM v1.0.11
2 |
3 | Welcome to the release of Gatekeeper Policy Manager version 1.0.11 🎉
4 |
5 | This is a maintenance and bug-fixing release including:
6 |
7 | - [#1026](https://github.com/sighupio/gatekeeper-policy-manager/pull/1026) Chart: change HPA API version to v2.
8 | - Bumped all JavaScript and Python dependencies to their latest compatible version.
9 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/chart/templates/secret-multicluster.yaml:
--------------------------------------------------------------------------------
1 | {{- if .Values.config.multiCluster.enabled -}}
2 | apiVersion: v1
3 | kind: Secret
4 | metadata:
5 | name: {{ include "gatekeeper-policy-manager.fullname" . }}-multicluster
6 | labels:
7 | {{- include "gatekeeper-policy-manager.labels" . | nindent 4 }}
8 | data:
9 | kubeconfig: {{ .Values.config.multiCluster.kubeconfig | b64enc }}
10 | {{- end -}}
--------------------------------------------------------------------------------
/docs/releases/v1.0.14.md:
--------------------------------------------------------------------------------
1 | # GPM v1.0.14
2 |
3 | Welcome to the release of Gatekeeper Policy Manager version 1.0.14 🎉
4 |
5 | This is a maintenance release including:
6 |
7 | - [[#1899]](https://github.com/sighupio/gatekeeper-policy-manager/pull/1289) Support for rego v1 in constraint templates by @AipNooBest
8 | - Bumped all JavaScript and Python dependencies to their latest compatible version.
9 |
--------------------------------------------------------------------------------
/chart/templates/secret-oidc.yaml:
--------------------------------------------------------------------------------
1 | {{- if and .Values.config.oidc.enabled .Values.config.oidc.clientSecret -}}
2 | apiVersion: v1
3 | kind: Secret
4 | metadata:
5 | name: {{ include "gatekeeper-policy-manager.fullname" . }}-oidc
6 | labels:
7 | {{- include "gatekeeper-policy-manager.labels" . | nindent 4 }}
8 | stringData:
9 | clientSecret: {{ .Values.config.oidc.clientSecret }}
10 | {{- end -}}
--------------------------------------------------------------------------------
/docs/releases/v1.0.12.md:
--------------------------------------------------------------------------------
1 | # GPM v1.0.12
2 |
3 | Welcome to the release of Gatekeeper Policy Manager version 1.0.12 🎉
4 |
5 | This is a maintenance release including:
6 |
7 | - [#1026](https://github.com/sighupio/gatekeeper-policy-manager/pull/1156) Chart: allow setting secret key by referencing a present/custom secret
8 | - Bumped all JavaScript and Python dependencies to their latest compatible version.
9 |
--------------------------------------------------------------------------------
/manifests/service.yaml:
--------------------------------------------------------------------------------
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 |
6 | apiVersion: v1
7 | kind: Service
8 | metadata:
9 | name: gatekeeper-policy-manager
10 | spec:
11 | selector:
12 | app: gatekeeper-policy-manager
13 | ports:
14 | - port: 80
15 | targetPort: http
16 |
--------------------------------------------------------------------------------
/chart/templates/secret.yaml:
--------------------------------------------------------------------------------
1 | {{- if .Values.config.secretKey }}
2 | apiVersion: v1
3 | kind: Secret
4 | metadata:
5 | name: {{ include "gatekeeper-policy-manager.fullname" . }}
6 | labels:
7 | {{- include "gatekeeper-policy-manager.labels" . | nindent 4 }}
8 | stringData:
9 | secretKey: {{ required "A valid .Values.config.secretKey entry required! Choose a secure string" .Values.config.secretKey | quote }}
10 | {{- end }}
11 |
--------------------------------------------------------------------------------
/tests/e2e/.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/.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 |
--------------------------------------------------------------------------------
/chart/templates/serviceaccount.yaml:
--------------------------------------------------------------------------------
1 | {{- if .Values.serviceAccount.create -}}
2 | apiVersion: v1
3 | kind: ServiceAccount
4 | metadata:
5 | name: {{ include "gatekeeper-policy-manager.serviceAccountName" . }}
6 | labels:
7 | {{- include "gatekeeper-policy-manager.labels" . | nindent 4 }}
8 | {{- with .Values.serviceAccount.annotations }}
9 | annotations:
10 | {{- toYaml . | nindent 4 }}
11 | {{- end }}
12 | {{- end }}
13 |
--------------------------------------------------------------------------------
/app/web-client/src/components/Footer/Style.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-next-line selector-class-pattern */
8 | .gpm-footer > .euiFlexGroup {
9 | margin-left: auto;
10 | margin-right: auto;
11 | z-index: 1002;
12 | padding: 0 13%;
13 | }
14 |
--------------------------------------------------------------------------------
/tests/deploy-patch.yaml:
--------------------------------------------------------------------------------
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 | apiVersion: apps/v1
6 | kind: Deployment
7 | metadata:
8 | name: gatekeeper-policy-manager
9 | spec:
10 | template:
11 | spec:
12 | containers:
13 | - name: gatekeeper-policy-manager
14 | imagePullPolicy: IfNotPresent
15 |
--------------------------------------------------------------------------------
/docs/releases/v1.0.13.md:
--------------------------------------------------------------------------------
1 | # GPM v1.0.13
2 |
3 | Welcome to the release of Gatekeeper Policy Manager version 1.0.13 🎉
4 |
5 | This is a maintenance release including:
6 |
7 | - Updated e2e tests to verify compatibility with Kubernetes 1.30, 1.31 and latest versions of OPA Gatekeeper
8 | - Switched to Python 3.12
9 | - Switched to `uv` for dependencies management in Dockerfile
10 | - Bumped all JavaScript and Python dependencies to their latest compatible version.
11 |
--------------------------------------------------------------------------------
/chart/.frigate:
--------------------------------------------------------------------------------
1 | # Gatekeeper Policy Manager Helm Chart - v{{ version }}
2 |
3 | {{ description }}
4 |
5 | ## Configuration options
6 |
7 | The following table lists the configurable parameters of the Gatekeeper Policy Manager chart and their default values.
8 |
9 | | Parameter | Description | Default |
10 | | --------- | ----------- | ------- |
11 | {% for (param, comment, default) in values -%}
12 | | `{{ param }}` | {{comment}} | {{ default }} |
13 | {% endfor -%}
14 |
--------------------------------------------------------------------------------
/tests/e2e/tests/home.spec.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2023 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 { test, expect } from '@playwright/test';
8 |
9 | test('page home snapshot', async ({ page }) => {
10 | await page.goto('/');
11 | await expect(page).toHaveScreenshot({ maxDiffPixels: 100, fullPage: true, mask: [page.locator('.dynamic')] });
12 | });
--------------------------------------------------------------------------------
/docs/releases/v1.0.9.md:
--------------------------------------------------------------------------------
1 | # GPM v1.0.9
2 |
3 | Welcome to the release of Gatekeeper Policy Manager version 1.0.9 🎉
4 |
5 | This is a maintenance release including:
6 |
7 | - [#834](https://github.com/sighupio/gatekeeper-policy-manager/pull/834) Fix a multi-cluster view bug: now you can have several tabs opened viewing different clusters and refreshing the page won't change the cluster.
8 | - Bumped all JavaScript and Python dependencies to their latest compatible version
9 |
10 |
--------------------------------------------------------------------------------
/app/web-client/src/setupTests.ts:
--------------------------------------------------------------------------------
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 | // jest-dom adds custom jest matchers for asserting on DOM nodes.
8 | // allows you to do things like:
9 | // expect(element).toHaveTextContent(/react/i)
10 | // learn more: https://github.com/testing-library/jest-dom
11 | import "@testing-library/jest-dom";
12 |
--------------------------------------------------------------------------------
/tests/e2e/playwright.config.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2023 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 { defineConfig } from "@playwright/test";
8 |
9 | export default defineConfig({
10 | use: {
11 | headless: true,
12 | browserName: "chromium",
13 | ignoreHTTPSErrors: true,
14 | baseURL: "http://localhost:8080",
15 | },
16 | });
17 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/.bumpversion.cfg:
--------------------------------------------------------------------------------
1 | [bumpversion]
2 | commit = True
3 | tag = True
4 | current_version = 1.1.0
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 |
--------------------------------------------------------------------------------
/app/web-client/src/assets/shield-active.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tests/e2e/tests/configurations.spec.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2023 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 { test, expect } from '@playwright/test';
8 |
9 | test('page configurations snapshot', async ({ page }) => {
10 | await page.goto('configurations/');
11 | await page.waitForSelector('#config > .euiPanel');
12 | await expect(page).toHaveScreenshot({ maxDiffPixels: 100, fullPage: true, mask: [page.locator('.dynamic')] });
13 | });
--------------------------------------------------------------------------------
/docs/releases/v1.0.5.md:
--------------------------------------------------------------------------------
1 | # GPM v1.0.5
2 |
3 | Welcome to the release of Gatekeeper Policy Manager version 1.0.5 🎉
4 |
5 | This is a minor release including bugfixes and some minor improvements:
6 |
7 | - OIDC Auth is working again ([#728](https://github.com/sighupio/gatekeeper-policy-manager/issues/728))
8 | - OIDC Auth now supports the `.well-known` endpoint for dynamic provider configuration.
9 | - OIDC Logout does not throw a CORS error anymore ([#725](https://github.com/sighupio/gatekeeper-policy-manager/issues/725))
10 | - Bumped all JavaScript and Python dependencies
11 |
--------------------------------------------------------------------------------
/app/web-client/src/hooks/useScrollToHash.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 { useEffect } from "react";
8 | import { scrollToElement } from "../utils";
9 |
10 | export default function useScrollToHash(hash: string, deps: any[]) {
11 | useEffect(() => {
12 | if (hash) {
13 | scrollToElement(hash, false);
14 | } else {
15 | window.scrollTo(0, 0);
16 | }
17 | }, [...deps]);
18 | }
19 |
--------------------------------------------------------------------------------
/.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 |
--------------------------------------------------------------------------------
/tests/e2e/tests/constraints.spec.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2023 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 { test, expect } from '@playwright/test';
8 |
9 | test('page constraints snapshot', async ({ page }) => {
10 | await page.goto('constraints/');
11 | // await page.waitForSelector('span[title="Constraints"]');
12 | await page.waitForSelector('nav');
13 | await expect(page).toHaveScreenshot({ maxDiffPixels: 100, fullPage: true, mask: [page.locator('.dynamic')] });;
14 | });
--------------------------------------------------------------------------------
/tests/e2e/tests/constrainttemplates.spec.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2023 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 { test, expect } from '@playwright/test';
8 |
9 | test('page constrainttemplates snapshot', async ({ page }) => {
10 | await page.goto('constrainttemplates/', { timeout: 10000 });
11 | await page.waitForSelector('span[title="Constraint Templates"]');
12 | await expect(page).toHaveScreenshot({ maxDiffPixels: 100, fullPage: true, mask: [page.locator('.dynamic')] });
13 | });
--------------------------------------------------------------------------------
/app/web-client/src/assets/shield-inactive.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/chart/templates/service.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: v1
2 | kind: Service
3 | metadata:
4 | name: {{ include "gatekeeper-policy-manager.fullname" . }}
5 | labels:
6 | {{- include "gatekeeper-policy-manager.labels" . | nindent 4 }}
7 | {{- with .Values.service.annotations }}
8 | annotations:
9 | {{- toYaml . | nindent 4 }}
10 | {{- end }}
11 | spec:
12 | type: {{ .Values.service.type }}
13 | ports:
14 | - port: {{ .Values.service.port }}
15 | targetPort: http
16 | protocol: TCP
17 | name: http
18 | selector:
19 | {{- include "gatekeeper-policy-manager.selectorLabels" . | nindent 4 }}
20 |
--------------------------------------------------------------------------------
/docs/releases/v1.0.8.md:
--------------------------------------------------------------------------------
1 | # GPM v1.0.8
2 |
3 | Welcome to the release of Gatekeeper Policy Manager version 1.0.8 🎉
4 |
5 | This is a maintenance release including:
6 |
7 | - [#797](https://github.com/sighupio/gatekeeper-policy-manager/pull/797) Fix Navigation when Constraints have dots or colons in the name (thanks @Markieta for the PR)
8 | - [#804](https://github.com/sighupio/gatekeeper-policy-manager/pull/804) Fix a bug that broke the backend when one or more constraints haven't been audited yet (thanks @Markieta for the PR)
9 | - Bumped all JavaScript and Python dependencies to their latest compatible version
10 |
11 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/docs/releases/v0.2.md:
--------------------------------------------------------------------------------
1 | # v0.2
2 |
3 | We are pleased to announce the release of Gatekeeper Policy Manager v0.2, changes in this new release:
4 |
5 | - Improved layout of violations: now the violations of a Constraint are shown as a table instead of a list, this improves the readability when the count of violations is high. Also, we show a message now when there are no violations.
6 | - Added missing "Scope" to the Constraints match criteria view.
7 | - Show the line numbers in the rego code view ports.
8 | - Added support for Gatekeeper "config" CRDs. Now you can view all the config CRDs as you would with the Constraints and Constraint Templates.
9 |
--------------------------------------------------------------------------------
/docs/releases/v1.0.2.md:
--------------------------------------------------------------------------------
1 | # v1.0.2
2 |
3 | Welcome to the release of Gatekeeper Policy Manager version 1.0.2.
4 |
5 | ## Changes from v1.0.1
6 |
7 | - Enhancement: show a successful logged-out page when logging out instead of asking for login immediately.
8 | - Bugfix: include the selected context in the report download link when in multi-cluster mode.
9 | - Bugfix: improve Constraint violations table display.
10 | - Helm Chart: fix Kubeconfig secret name.
11 | - Helm Chart: delete unused manifests.
12 | - Helm Chart: support for additional custom pod labels.
13 | - Other: updated dependencies.
14 |
15 | ### Breaking changes
16 |
17 | No breaking changes.
18 |
--------------------------------------------------------------------------------
/manifests/multi-cluster.yaml:
--------------------------------------------------------------------------------
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 | apiVersion: apps/v1
6 | kind: Deployment
7 | metadata:
8 | name: gatekeeper-policy-manager
9 | spec:
10 | template:
11 | spec:
12 | containers:
13 | - name: gatekeeper-policy-manager
14 | volumeMounts:
15 | - mountPath: /home/gpm/.kube/config
16 | name: kubeconfig
17 | subPath: kubeconfig
18 | volumes:
19 | - name: kubeconfig
20 | secret:
21 | secretName: kubeconfig
22 |
--------------------------------------------------------------------------------
/app/web-client/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es5",
4 | "lib": [
5 | "dom",
6 | "dom.iterable",
7 | "esnext"
8 | ],
9 | "allowJs": true,
10 | "skipLibCheck": true,
11 | "esModuleInterop": true,
12 | "allowSyntheticDefaultImports": true,
13 | "strict": true,
14 | "forceConsistentCasingInFileNames": true,
15 | "noFallthroughCasesInSwitch": true,
16 | "module": "esnext",
17 | "moduleResolution": "node",
18 | "resolveJsonModule": true,
19 | "isolatedModules": true,
20 | "noEmit": true,
21 | "jsx": "react-jsx"
22 | },
23 | "include": [
24 | "src"
25 | ]
26 | }
27 |
--------------------------------------------------------------------------------
/.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 |
--------------------------------------------------------------------------------
/app/web-client/src/reportWebVitals.ts:
--------------------------------------------------------------------------------
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 { MetricType } from "web-vitals";
8 |
9 | const reportWebVitals = (onPerfEntry?: (metric: MetricType) => void) => {
10 | if (onPerfEntry && onPerfEntry instanceof Function) {
11 | import("web-vitals").then(({ onCLS, onINP, onFCP, onLCP, onTTFB }) => {
12 | onCLS(onPerfEntry);
13 | onINP(onPerfEntry);
14 | onFCP(onPerfEntry);
15 | onLCP(onPerfEntry);
16 | onTTFB(onPerfEntry);
17 | });
18 | }
19 | };
20 |
21 | export default reportWebVitals;
22 |
--------------------------------------------------------------------------------
/app/web-client/src/pages/theme.ts:
--------------------------------------------------------------------------------
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 | export default {
8 | scheme: "sighup",
9 | author: "alessio pragliola (https://github.com/Al-Pragliola)",
10 | base00: "inherit",
11 | base01: "#808280",
12 | base02: "#808280",
13 | base03: "transparent",
14 | base04: "#b4b7b4",
15 | base05: "#c5c8c6",
16 | base06: "#e0e0e0",
17 | base07: "#ffffff",
18 | base08: "#CC342B",
19 | base09: "#F96A38",
20 | base0A: "#FBA922",
21 | base0B: "#373530",
22 | base0C: "#68288C",
23 | base0D: "#68288C",
24 | base0E: "#68288C",
25 | base0F: "#68288C",
26 | };
27 |
--------------------------------------------------------------------------------
/app/web-client/src/theme.ts:
--------------------------------------------------------------------------------
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 | export const theme = {
8 | themeName: "THEME_KARRIER",
9 | colors: {
10 | LIGHT: {
11 | primary: "#6b2d9f",
12 | customPrimaryDarkShade: "#421959",
13 | },
14 | DARK: {
15 | primary: "#6b2d9f",
16 | customPrimaryDarkShade: "#421959",
17 | },
18 | },
19 | font: {
20 | family: "'Poppins', BlinkMacSystemFont, Helvetica, Arial, sans-serif",
21 | familyCode: "'JetBrains Mono', Menlo, Courier, monospace",
22 | },
23 | border: {
24 | radius: {
25 | medium: "8px",
26 | },
27 | },
28 | };
29 |
--------------------------------------------------------------------------------
/app/constraints.txt:
--------------------------------------------------------------------------------
1 | Beaker==1.13.0
2 | cachetools==5.5.0
3 | certifi==2025.8.3
4 | cffi==1.17.1
5 | charset-normalizer==3.4.3
6 | click==8.1.8
7 | cryptography==45.0.6
8 | defusedxml==0.7.1
9 | future==1.0.0
10 | google-auth==2.40.3
11 | idna==3.10
12 | importlib-resources==6.5.2
13 | itsdangerous==2.2.0
14 | Jinja2==3.1.6
15 | Mako==1.3.10
16 | MarkupSafe==3.0.2
17 | oauthlib==3.3.1
18 | oic==1.6.1
19 | pyasn1==0.6.1
20 | pyasn1-modules==0.4.2
21 | pycparser==2.22
22 | pycryptodomex==3.23.0
23 | pydantic==2.11.7
24 | pyjwkest==1.4.2
25 | python-dateutil==2.9.0.post0
26 | PyYAML==6.0.3
27 | requests==2.32.4
28 | requests-oauthlib==2.0.0
29 | rsa==4.9.1
30 | six==1.17.0
31 | typing-extensions==4.14.1
32 | urllib3==2.5.0
33 | websocket-client==1.8.0
34 | Werkzeug==3.1.3
35 | zipp==3.23.0
36 |
--------------------------------------------------------------------------------
/app/web-client/src/pages/Configurations/Style.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-config .euiDescriptionList__title {
9 | max-width: 100px;
10 | text-overflow: ellipsis;
11 | white-space: nowrap;
12 | overflow: hidden;
13 | }
14 |
15 | .gpm-page-config .euiDescriptionList.euiDescriptionList--column.euiDescriptionList--compressed .euiDescriptionList__description,
16 | .gpm-page-config .euiDescriptionList.euiDescriptionList--responsiveColumn.euiDescriptionList--compressed .euiDescriptionList__description {
17 | width: calc(100% - 100px);
18 | }
19 |
--------------------------------------------------------------------------------
/app/web-client/src/AppContext.ts:
--------------------------------------------------------------------------------
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 { createContext } from "react";
8 |
9 | export interface IApplicationContextData {
10 | apiUrl: string;
11 | k8sContexts: string[];
12 | currentK8sContext: string;
13 | authEnabled: boolean;
14 | }
15 |
16 | export interface IApplicationContext {
17 | context: IApplicationContextData;
18 | setContext?: (context: Partial) => void;
19 | }
20 |
21 | export const ApplicationContext = createContext({
22 | context: {
23 | apiUrl: "",
24 | k8sContexts: [],
25 | currentK8sContext: "",
26 | authEnabled: false,
27 | },
28 | });
29 |
--------------------------------------------------------------------------------
/app/web-client/src/index.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 ReactDOM from "react-dom";
9 | import reportWebVitals from "./reportWebVitals";
10 | import App from "./App";
11 | import { BrowserRouter } from "react-router-dom";
12 | import "./index.scss";
13 |
14 | ReactDOM.render(
15 |
16 |
17 | ,
18 | document.getElementById("root")
19 | );
20 |
21 | // If you want to start measuring performance in your app, pass a function
22 | // to log results (for example: reportWebVitals(console.log))
23 | // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
24 | reportWebVitals();
25 |
--------------------------------------------------------------------------------
/app/web-client/src/pages/types.ts:
--------------------------------------------------------------------------------
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 { RenderItem } from "@elastic/eui/src/components/side_nav/side_nav_item";
8 | import { ReactElement } from "react";
9 |
10 | export interface ISideNavItem {
11 | name: string;
12 | id: string;
13 | href?: string;
14 | disabled?: boolean;
15 | renderItem?: RenderItem;
16 | icon?: ReactElement;
17 | isSelected?: boolean;
18 | onClick?: () => void;
19 | }
20 |
21 | export interface ISideNav {
22 | name: string;
23 | id: string;
24 | items: ISideNavItem[];
25 | }
26 |
27 | export interface BackendError {
28 | action: string;
29 | description: string;
30 | error: string;
31 | }
32 |
--------------------------------------------------------------------------------
/tests/kustomization.yaml:
--------------------------------------------------------------------------------
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 | namespace: gatekeeper-system
6 |
7 | resources:
8 | # Deploy Gatekeeper from KFD OPA Module
9 | - github.com/sighupio/module-policy/katalog/gatekeeper/core?ref=v1.14.0
10 | - github.com/sighupio/module-policy/katalog/gatekeeper/rules?ref=v1.14.0
11 | - github.com/sighupio/module-policy/katalog/gatekeeper/monitoring?ref=v1.14.0
12 |
13 | # Deploy GPM itself
14 | - ../manifests/rbac.yaml
15 | - ../manifests/deployment.yaml
16 | - ../manifests/service.yaml
17 |
18 | patches:
19 | - path: deploy-patch.yaml
20 |
21 | images:
22 | - name: quay.io/sighup/gatekeeper-policy-manager
23 | newName: gatekeeper-policy-manager
24 | newTag: test
25 |
--------------------------------------------------------------------------------
/tests/e2e/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "gpm-e2e",
3 | "version": "1.0.0",
4 | "description": "E2E Testing suite for GPM",
5 | "main": "index.js",
6 | "repository": {
7 | "type": "git",
8 | "url": "git+https://github.com/sighupio/gatekeeper-policy-manager.git"
9 | },
10 | "author": "Ramiro Algozino",
11 | "license": " BSD-3-Clause",
12 | "bugs": {
13 | "url": "https://github.com/sighupio/gatekeeper-policy-manager/issues"
14 | },
15 | "homepage": "https://github.com/sighupio/gatekeeper-policy-manager#readme",
16 | "dependencies": {
17 | "playwright": "^1.30.0"
18 | },
19 | "devDependencies": {
20 | "@playwright/test": "^1.30.0"
21 | },
22 | "scripts": {
23 | "test": "playwright test",
24 | "gen:snapshot": "rm -rf tests/*-snapshots && playwright test --update-snapshots --config=playwright.config.js"
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/.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 |
--------------------------------------------------------------------------------
/docs/releases/v1.0.1.md:
--------------------------------------------------------------------------------
1 | # v1.0.1
2 |
3 | Welcome to the release of Gatekeeper Policy Manager version 1.0.1.
4 |
5 | ## Changes from v1.0.0
6 |
7 | - Enhancement: reintroduced line numbers in the rego code viewports.
8 | - Enhancement: new (better and consistent) icons for the Constraint mode.
9 | - Enhancement: Constraint Templates now show their description if available.
10 | - Enhancement: switched from custom fork for the UI to ElasticUI + Fury theme and deleted old SemanticUI dependencies.
11 | - Bugfix: handle expired OIDC sessions properly and reask for login.
12 | - Bugfix: warn icon now shows its tooltip and is aligned like the rest of the icons in the Constraint navbar.
13 | - Helm Chart: new release pointing to the latest version of GPM.
14 | - Helm Chart: set GPM deployment replicas to 2 by default.
15 | - Other: updated all the dependencies.
16 |
17 | ### Breaking changes
18 |
19 | No breaking changes.
20 |
--------------------------------------------------------------------------------
/app/web-client/src/assets/github-logo.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
10 |
11 |
--------------------------------------------------------------------------------
/.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 |
--------------------------------------------------------------------------------
/manifests/ingress.yaml:
--------------------------------------------------------------------------------
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 | apiVersion: networking.k8s.io/v1
6 | kind: Ingress
7 | metadata:
8 | annotations:
9 | kubernetes.io/ingress.class: "nginx"
10 | forecastle.stakater.com/expose: "true"
11 | forecastle.stakater.com/appName: "Gatekeeper Policy Manager"
12 | forecastle.stakater.com/icon: "https://raw.githubusercontent.com/sighupio/gatekeeper-policy-manager/master/docs/assets/logo.svg"
13 | name: gatekeeper-policy-manager
14 | spec:
15 | rules:
16 | # Set the HOST accordingly
17 | - host: gpm.internal.mycompany.com
18 | http:
19 | paths:
20 | - path: /
21 | pathType: ImplementationSpecific
22 | backend:
23 | service:
24 | name: gatekeeper-policy-manager
25 | port:
26 | name: http
27 |
--------------------------------------------------------------------------------
/docs/releases/v1.0.0.md:
--------------------------------------------------------------------------------
1 | # v1.0.0-rc0
2 |
3 | Gatekeeper Policy Manager version 1.0.0
4 |
5 | ## Changes from v0.5.1
6 |
7 | - Enhancement: new branding and frontend using the Fury Design System.
8 | - Enhancement: backend now uses ConstraintTemplates v1 API version against Kubernetes API.
9 | - Bugfix: fixed a bug that made the backend logs to not show up in standard output.
10 | - Bugfix: fixed a bug that made GPM not consider the `WARN` mode for Constraints.
11 | - Helm Chart: switched to Ingress networking.k8s.io/v1 from networking.k8s.io/v1beta1 for Kubernetes >1.22 compatibility (thanks @edify42!).
12 | - Helm Chart: it is now published in GitHub pages for easier usage. See the [readme](https://github.com/sighupio/gatekeeper-policy-manager#deploy-using-helm) for instructions.
13 | - Docs: [Added instructions to use AWS IAM authentication](https://github.com/sighupio/gatekeeper-policy-manager#aws-iam-authentication).
14 | - Updated all the dependencies.
15 |
16 | ### Breaking changes
17 |
18 | No breaking changes.
19 |
--------------------------------------------------------------------------------
/docs/releases/v0.4.0.md:
--------------------------------------------------------------------------------
1 | # v0.4.0
2 |
3 | ## Changes from v0.3.0 to v0.4.0
4 |
5 | A lot of maintenance and some bug-fixing on this release:
6 |
7 | - Clicking on a violation gets "selected", this could be useful when there are several violations and you want to focus on just one.
8 | - Show a message when violations for a Constraint are unknown instead of saying that there are no violations.
9 | - Fixed double "Go back" button on logout message and better Info message style on Index when Authentication is enabled.
10 | - Updated all Python dependencies to the latest version.
11 | - A lot of work has been done to automate the SLC of the project (thanks @angelbarrera92!! 🎉 ):
12 | - We have now automated E2E testing of the app against a Kubernetes cluster with Gatekeeper installed.
13 | - Automatic dependencies update PRs from renovate bot.
14 | - We have now an automated release notes generation
15 | - Automated linting and format check for all languages
16 |
17 | ## Breaking changes
18 |
19 | No breaking changes.
20 |
--------------------------------------------------------------------------------
/docs/releases/v0.4.2.md:
--------------------------------------------------------------------------------
1 | # v0.4.2
2 |
3 | ## Changes from v0.4.1
4 |
5 | Bug fixes:
6 |
7 | - Handle the case of a constraint not having a `spec` section defined.
8 | - Fix several typos on the UI
9 | - Improved Rego syntax highlighting (thanks to the work of @JordanSh on )
10 |
11 | New features:
12 |
13 | - Highlight the Constraint Template / Constraint that you want to see when following a link.
14 |
15 | ## Updated dependencies
16 |
17 | - astroid==2.5.6
18 | - cachetools==4.2.2
19 | - cffi==1.14.5
20 | - cryptography==3.4.7
21 | - defusedxml==0.7.1
22 | - google-auth==1.30.0
23 | - importlib-metadata==4.0.1
24 | - importlib-resources==5.1.2
25 | - isort==v5.8.0
26 | - Jinja2==2.11.3
27 | - lazy-object-proxy==1.6.0
28 | - Mako==1.1.4
29 | - pycryptodomex==3.10.1
30 | - pylint==2.8.2
31 | - PyYAML==5.4.1
32 | - rsa==4.7.2
33 | - typed-ast==v1.4.3
34 | - urllib3==1.26.4
35 | - websocket-client==v0.58.0
36 | - zipp==3.4.1
37 |
38 | ## Breaking changes
39 |
40 | No breaking changes.
41 |
--------------------------------------------------------------------------------
/app/web-client/src/components/Header/Style.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-next-line selector-class-pattern */
8 | .gpm-header .euiHeader {
9 | margin-left: auto;
10 | margin-right: auto;
11 | }
12 |
13 | .gpm-header .header-active {
14 | border-bottom: 1px solid #68288c;
15 | }
16 |
17 | /* stylelint-disable-next-line selector-class-pattern */
18 | .gpm-header .euiHeader.gpm-header--desktop {
19 | z-index: 1002;
20 | padding: 0 13%;
21 | }
22 |
23 | /* stylelint-disable-next-line selector-class-pattern */
24 | .gpm-header .euiHeader.gpm-header--mobile {
25 | height: 54px;
26 | padding-left: 16px;
27 | padding-right: 16px;
28 | }
29 |
30 | @media screen and (width >= 1365px) {
31 | /* stylelint-disable-next-line selector-class-pattern */
32 | .gpm-header .euiHeader .gpm-header--desktop {
33 | padding: 0 25%;
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/tests/helper.bash:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bats
2 |
3 | # shellcheck disable=SC2086,SC2154,SC2034
4 |
5 | apply (){
6 | kustomize build $1 >&2
7 | kustomize build $1 | kubectl apply -f - 2>&3
8 | }
9 |
10 | delete (){
11 | kustomize build $1 >&2
12 | kustomize build $1 | kubectl delete -f - 2>&3
13 | }
14 |
15 | info(){
16 | echo -e "${BATS_TEST_NUMBER}: ${BATS_TEST_DESCRIPTION}" >&3
17 | }
18 |
19 | loop_it(){
20 | retry_counter=0
21 | max_retry=${2:-100}
22 | wait_time=${3:-2}
23 | run ${1}
24 | ko=${status}
25 | loop_it_result=${ko}
26 | while [[ ko -ne 0 ]]
27 | do
28 | if [ $retry_counter -ge $max_retry ]; then
29 | echo "Timeout waiting for the command to success."
30 | echo "Last command output was:"
31 | echo "${output}"
32 | return 1
33 | fi
34 | sleep ${wait_time} && echo "# waiting..." $retry_counter >&3
35 | run ${1}
36 | ko=${status}
37 | loop_it_result=${ko}
38 | loop_it_output=${output}
39 | retry_counter=$((retry_counter + 1))
40 | done
41 | return 0
42 | }
43 |
--------------------------------------------------------------------------------
/app/web-client/src/pages/Constraints/Style.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-constraints .euiAccordion__button:focus {
9 | text-decoration: none !important;
10 | }
11 |
12 | .gpm-page-constraints .euiAccordion__button:hover {
13 | text-decoration: none !important;
14 | }
15 |
16 | .gpm-page-constraints .euiDescriptionList__title {
17 | max-width: 100px;
18 | }
19 |
20 | .gpm-page-constraints .euiPanel .euiBadge svg.euiIcon--small {
21 | width: 14px;
22 | height: 14px;
23 | }
24 |
25 | .gpm-page-constraints .euiDescriptionList.euiDescriptionList--column.euiDescriptionList--compressed .euiDescriptionList__description,
26 | .gpm-page-constraints .euiDescriptionList.euiDescriptionList--responsiveColumn.euiDescriptionList--compressed .euiDescriptionList__description {
27 | width: calc(100% - 100px);
28 | }
29 |
--------------------------------------------------------------------------------
/docs/releases/v1.0.10.md:
--------------------------------------------------------------------------------
1 | # GPM v1.0.10
2 |
3 | Welcome to the release of Gatekeeper Policy Manager version 1.0.10 🎉
4 |
5 | This is a maintenance and bug-fixing release including:
6 |
7 | - [#976](https://github.com/sighupio/gatekeeper-policy-manager/pull/976) Fixed an issue in the Helm Chart preventing OIDC configuration discovery to work properly. Now optional OIDC configuration environment variables are set only when their respective values are set as chart values.
8 | - [#981](https://github.com/sighupio/gatekeeper-policy-manager/pull/981) Fixed an issue that failed to recognise the selected context when its name contained special characters like colons or forward slashes, for example the name that EKS gives to the context by default. Now special characters are supported.
9 | - [#982](https://github.com/sighupio/gatekeeper-policy-manager/pull/982) Improved the context selection drop down for long names, now the width is not hardcoded anymore and hovering with the mouse pointer shows a tooltip with the full context name.
10 | - Bumped all JavaScript and Python dependencies to their latest compatible version
11 |
12 |
--------------------------------------------------------------------------------
/tests/e2e/README.md:
--------------------------------------------------------------------------------
1 | # GPM UI E2E Tests
2 |
3 | This folder contains the test definitions for testing UI regressions in GPM's frontend.
4 |
5 | The best way to use locally these tests is to run them in a docker container, otherwise, you might get different rendering results.
6 |
7 | > Notice that you'll need to have a working instance of GPM accessible at `http://localhost:8080`
8 | >
9 | > For example with:
10 | >
11 | > ```bash
12 | > kubectl port-forward -n gatekeeper-system svc/gatekeeper-policy-manager 8080:80
13 | > ```
14 |
15 | 1. Get the container running:
16 |
17 | ```console
18 | docker run --rm -it --network=host -v $PWD:/app mcr.microsoft.com/playwright:v1.30.0-focal
19 | ```
20 |
21 | 2. Install all the dependencies:
22 |
23 | ```console
24 | cd app/tests/e2e
25 | yarn install
26 | ```
27 |
28 | 3. compare current status with the baseline:
29 |
30 | ```console
31 | yarn test
32 | ```
33 |
34 | 4. (optional) create new baseline for the tests:
35 |
36 | ```console
37 | yarn gen:snapshot
38 | ```
39 |
40 | 5. re-compare current status with the new baseline:
41 |
42 | ```console
43 | yarn test
44 | ```
45 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/docs/releases/v0.4.1.md:
--------------------------------------------------------------------------------
1 | # v0.4.1
2 |
3 | ## Changes from v0.4.0 to v0.4.1
4 |
5 | Bug fixes:
6 |
7 | - Add a warning when the amount of violations audits that can be shown is less than the total violations. See #63.
8 | - Increase uWSGI buffer size for headers (see #61 thanks @kg-ops!)
9 | - Fix Label Selector not showing correctly on constraints view (thanks @lnovara for spotting it)
10 |
11 | Updated Python dependencies:
12 |
13 | - cachetools to 4.2.0
14 | - certifi to v2020.12.5
15 | - cffi to 1.14.4
16 | - chardet to 4.0.0
17 | - cryptography to 3.3.1
18 | - cryptography to v3.2.1
19 | - Flask-pyoidc to 3.7.0
20 | - google-auth to 1.24.0
21 | - google-auth to v1.23.0
22 | - importlib-metadata to 3.3.0
23 | - importlib-resources to 4.1.1
24 | - importlib-resources to v3.3.0
25 | - isort to 5.7.0
26 | - kubernetes to 12.0.0
27 | - lazy-object-proxy to 1.5.2
28 | - oic to 1.2.1
29 | - pycryptodomex to v3.9.9
30 | - requests to v2.25.1
31 | - typed-ast to 1.4.2
32 | - urllib3 to 1.26.2
33 | - zipp to v3.4.0
34 |
35 | Updated OS-level dependencies:
36 |
37 | - musl-dev to 1.1.24-r3
38 |
39 | ## Breaking changes
40 |
41 | No breaking changes.
42 |
--------------------------------------------------------------------------------
/tests/e2e-tests.yaml:
--------------------------------------------------------------------------------
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 | apiVersion: batch/v1
6 | kind: Job
7 | metadata:
8 | name: e2e-tests
9 | spec:
10 | template:
11 | spec:
12 | containers:
13 | - name: configs
14 | image: docker.io/curlimages/curl
15 | command: ["/bin/sh", "-c"]
16 | args: ["curl -s http://gatekeeper-policy-manager.gatekeeper-system.svc.cluster.local/api/v1/configs/ | grep 'kube-system'"]
17 | - name: constrainttemplates
18 | image: docker.io/curlimages/curl
19 | command: ["/bin/sh", "-c"]
20 | args: ["curl -s http://gatekeeper-policy-manager.gatekeeper-system.svc.cluster.local/api/v1/constrainttemplates/ | grep 'target'"]
21 | - name: constraints
22 | image: docker.io/curlimages/curl
23 | command: ["/bin/sh", "-c"]
24 | args: ["curl -s http://gatekeeper-policy-manager.gatekeeper-system.svc.cluster.local/api/v1/constraints/ | grep 'totalViolations'"]
25 | restartPolicy: Never
26 | backoffLimit: 9
27 |
--------------------------------------------------------------------------------
/manifests/rbac.yaml:
--------------------------------------------------------------------------------
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 | apiVersion: v1
6 | kind: ServiceAccount
7 | metadata:
8 | name: gatekeeper-policy-manager
9 |
10 | ---
11 |
12 | apiVersion: rbac.authorization.k8s.io/v1
13 | kind: ClusterRole
14 | metadata:
15 | name: gatekeeper-policy-manager-crd-view
16 | rules:
17 | - apiGroups: ["constraints.gatekeeper.sh"]
18 | resources: ["*"]
19 | verbs: ["get", "list", "watch"]
20 | - apiGroups: ["templates.gatekeeper.sh"]
21 | resources: ["*"]
22 | verbs: ["get", "list", "watch"]
23 | - apiGroups: ["config.gatekeeper.sh"]
24 | resources: ["*"]
25 | verbs: ["get", "list", "watch"]
26 |
27 | ---
28 |
29 | apiVersion: rbac.authorization.k8s.io/v1
30 | kind: ClusterRoleBinding
31 | metadata:
32 | name: gatekeeper-policy-manager-crd-view
33 | roleRef:
34 | apiGroup: rbac.authorization.k8s.io
35 | kind: ClusterRole
36 | name: gatekeeper-policy-manager-crd-view
37 | subjects:
38 | - kind: ServiceAccount
39 | name: gatekeeper-policy-manager
40 | namespace: gatekeeper-system
41 |
--------------------------------------------------------------------------------
/app/web-client/src/hooks/useCurrentElementInView.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 { MutableRefObject, useEffect } from "react";
8 |
9 | export default function useCurrentElementInView(
10 | refs: MutableRefObject,
11 | cb: (id: string) => any,
12 | offset = 0
13 | ) {
14 | const observer = new IntersectionObserver((entries, observer) => {
15 | const elementVisible = entries.filter((element) => {
16 | const top = element.boundingClientRect.top;
17 |
18 | return top + offset >= 0 && top - offset <= window.innerHeight;
19 | })
20 |
21 | if (elementVisible.length > 0) {
22 | cb(elementVisible[0].target.id);
23 | }
24 |
25 | observer.disconnect();
26 | });
27 |
28 | const onScroll = () => {
29 | refs.current.forEach(el => {
30 | observer.observe(el);
31 | })
32 | };
33 |
34 | useEffect(() => {
35 | document.addEventListener("scroll", onScroll, true);
36 | return () => document.removeEventListener("scroll", onScroll, true);
37 | }, []);
38 | }
39 |
--------------------------------------------------------------------------------
/chart/Chart.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: v2
2 | type: application
3 | name: gatekeeper-policy-manager
4 | description:
5 | A Helm chart for Gatekeeper Policy Manager, a simple to use, read-only web UI for
6 | viewing OPA Gatekeeper policies' status in a Kubernetes Cluster.
7 | home: https://sighup.io
8 | sources:
9 | - https://github.com/sighupio/gatekeeper-policy-manager/
10 | icon: https://raw.githubusercontent.com/sighupio/gatekeeper-policy-manager/main/docs/assets/logo.svg
11 | maintainers:
12 | - name: Ramiro Algozino
13 | email: ramiro@sighup.io
14 | keywords:
15 | ["opa", "gatekeeper", "policy", "ui", "dashboard", "web", "rego", "webapp"]
16 |
17 | # This is the chart version. This version number should be incremented each time you make changes
18 | # to the chart and its templates, including the app version.
19 | # Versions are expected to follow Semantic Versioning (https://semver.org/)
20 | version: "0.15.0"
21 |
22 | # This is the version number of the application being deployed. This version number should be
23 | # incremented each time you make changes to the application. Versions are not expected to
24 | # follow Semantic Versioning. They should reflect the version the application is using.
25 | appVersion: "v1.1.0"
26 |
--------------------------------------------------------------------------------
/app/web-client/src/pages/Configurations/types.ts:
--------------------------------------------------------------------------------
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 | export interface IGVK {
8 | group: string;
9 | version: string;
10 | kind: string;
11 | }
12 |
13 | export interface ITrace {
14 | user: string;
15 | kind: IGVK;
16 | dump: string;
17 | }
18 |
19 | export interface IConfigSpecSync {
20 | syncOnly: IGVK[];
21 | }
22 |
23 | export interface IConfigSpecValidation {
24 | traces: ITrace[];
25 | }
26 |
27 | export interface IConfigSpecMatch {
28 | processes: string[];
29 | excludedNamespaces: string[];
30 | }
31 |
32 | export interface IConfigSpecReadiness {
33 | statsEnabled: boolean;
34 | }
35 |
36 | export interface IConfigSpec {
37 | sync?: IConfigSpecSync;
38 | validation?: IConfigSpecValidation;
39 | match?: IConfigSpecMatch[];
40 | readiness?: IConfigSpecReadiness;
41 | }
42 |
43 | export interface IConfig {
44 | apiVersion: string;
45 | kind: string;
46 | metadata: {
47 | name: string;
48 | namespace: string;
49 | creationTimestamp: string;
50 | };
51 | spec?: IConfigSpec;
52 | status?: any;
53 | }
54 |
--------------------------------------------------------------------------------
/docs/releases/v1.1.0.md:
--------------------------------------------------------------------------------
1 | # GPM v1.1.0
2 |
3 | Welcome to the release of Gatekeeper Policy Manager version 1.1.0 🎉
4 |
5 | This is a minor release including user experience improvements, new features and dependencies maintenance:
6 |
7 | - [[#1327]](https://github.com/sighupio/gatekeeper-policy-manager/pull/1327) UX improvements:
8 | - Allow sorting, searching and filtering in the constraints violations table.
9 | - Make the navigation bar for Constraints and Constraints Templates sticky, so it will scroll with the view.
10 | - Clicking a link now scrolls to the top of the item instead of the middle.
11 | - Active item indicator seems to be working properly.
12 | - Disabled text truncating in the Constraints nav bar, is not great but better that not seeing the whole name.
13 | - Rebranding: Kubernetes Fury Distribution to SIGHUP Distribution
14 | - [[#1328]](https://github.com/sighupio/gatekeeper-policy-manager/pull/1328) GPM now uses ConstraintsTemplates `v1` API, this could be a breaking change if you are using older versions of OPA Gatekeeper that were still on v1beta1. `v1` has been available since [Gatekeeper v3.6.0](https://github.com/open-policy-agent/gatekeeper/releases/tag/v3.6.0).
15 | - Bumped all JavaScript and Python dependencies to their latest compatible version.
16 |
--------------------------------------------------------------------------------
/kustomization.yaml:
--------------------------------------------------------------------------------
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 | apiVersion: kustomize.config.k8s.io/v1beta1
5 | kind: Kustomization
6 |
7 | namespace: gatekeeper-system
8 |
9 | resources:
10 | - manifests/rbac.yaml
11 | - manifests/deployment.yaml
12 | - manifests/service.yaml
13 | # Uncomment the following line to create an ingress if you want to expose the
14 | # the app to the outside. Remember to edit the file and set the host accordingly.
15 | # - manifests/ingress.yaml
16 |
17 | # Uncomment the following line if you are using some of the patches below.
18 | #patchesStrategicMerge:
19 | # Uncomment the following patch to enable multi-cluster support.
20 | # - manifests/multi-cluster.yaml
21 | # Uncomment the following patch to enable OIDC authentication.
22 | # Remember to edit the file to set the right values.
23 | # - manifests/enable-oidc.yaml
24 |
25 | # Example secretGenerator to create a secret with the kubeconfig:
26 | # secretGenerator:
27 | # - name: kubeconfig
28 | # namespace: gatekeeper-system
29 | # files:
30 | # - kubeconfig # or the path to your file.
31 |
32 | images:
33 | - name: quay.io/sighup/gatekeeper-policy-manager
34 | newTag: v1.1.0
35 |
--------------------------------------------------------------------------------
/chart/templates/hpa.yaml:
--------------------------------------------------------------------------------
1 | {{- if .Values.autoscaling.enabled }}
2 | apiVersion: autoscaling/v2
3 | kind: HorizontalPodAutoscaler
4 | metadata:
5 | name: {{ include "gatekeeper-policy-manager.fullname" . }}
6 | labels:
7 | {{- include "gatekeeper-policy-manager.labels" . | nindent 4 }}
8 | spec:
9 | scaleTargetRef:
10 | apiVersion: apps/v1
11 | kind: Deployment
12 | name: {{ include "gatekeeper-policy-manager.fullname" . }}
13 | minReplicas: {{ .Values.autoscaling.minReplicas }}
14 | maxReplicas: {{ .Values.autoscaling.maxReplicas }}
15 | metrics:
16 | {{- with .Values.autoscaling.metrics }}
17 | {{- toYaml . | nindent 4 }}
18 | {{- else }}
19 | {{- with .Values.autoscaling.targetMemoryUtilizationPercentage }}
20 | - type: Resource
21 | resource:
22 | name: memory
23 | target:
24 | type: Utilization
25 | averageUtilization: {{ . }}
26 | {{- end }}
27 | {{- with .Values.autoscaling.targetCPUUtilizationPercentage }}
28 | - type: Resource
29 | resource:
30 | name: cpu
31 | target:
32 | type: Utilization
33 | averageUtilization: {{ . }}
34 | {{- end }}
35 | {{- end }}
36 | {{- with .Values.autoscaling.behavior }}
37 | behavior:
38 | {{- toYaml . | nindent 4 }}
39 | {{- end }}
40 | {{- end }}
41 |
--------------------------------------------------------------------------------
/tests/e2e/yarn.lock:
--------------------------------------------------------------------------------
1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
2 | # yarn lockfile v1
3 |
4 |
5 | "@playwright/test@^1.30.0":
6 | version "1.30.0"
7 | resolved "https://registry.yarnpkg.com/@playwright/test/-/test-1.30.0.tgz#8c0c4930ff2c7be7b3ec3fd434b2a3b4465ed7cb"
8 | integrity sha512-SVxkQw1xvn/Wk/EvBnqWIq6NLo1AppwbYOjNLmyU0R1RoQ3rLEBtmjTnElcnz8VEtn11fptj1ECxK0tgURhajw==
9 | dependencies:
10 | "@types/node" "*"
11 | playwright-core "1.30.0"
12 |
13 | "@types/node@*":
14 | version "18.11.18"
15 | resolved "https://registry.yarnpkg.com/@types/node/-/node-18.11.18.tgz#8dfb97f0da23c2293e554c5a50d61ef134d7697f"
16 | integrity sha512-DHQpWGjyQKSHj3ebjFI/wRKcqQcdR+MoFBygntYOZytCqNfkd2ZC4ARDJ2DQqhjH5p85Nnd3jhUJIXrszFX/JA==
17 |
18 | playwright-core@1.30.0:
19 | version "1.30.0"
20 | resolved "https://registry.yarnpkg.com/playwright-core/-/playwright-core-1.30.0.tgz#de987cea2e86669e3b85732d230c277771873285"
21 | integrity sha512-7AnRmTCf+GVYhHbLJsGUtskWTE33SwMZkybJ0v6rqR1boxq2x36U7p1vDRV7HO2IwTZgmycracLxPEJI49wu4g==
22 |
23 | playwright@^1.30.0:
24 | version "1.30.0"
25 | resolved "https://registry.yarnpkg.com/playwright/-/playwright-1.30.0.tgz#b1d7be2d45d97fbb59f829f36f521f12010fe072"
26 | integrity sha512-ENbW5o75HYB3YhnMTKJLTErIBExrSlX2ZZ1C/FzmHjUYIfxj/UnI+DWpQr992m+OQVSg0rCExAOlRwB+x+yyIg==
27 | dependencies:
28 | playwright-core "1.30.0"
29 |
--------------------------------------------------------------------------------
/docs/releases/v0.5.1.md:
--------------------------------------------------------------------------------
1 | # v0.5.1
2 |
3 | Gatekeeper Policy Manager version 0.5.1
4 |
5 | ## Changes from v0.5.0
6 |
7 | - Increased default memory limits in Kubernetes manifests and the Helm chart due to reports of missbehaviour with the previous values.
8 | - Update to Python 3.10
9 | - Set explicitly the replica count for Kubernetes deployment
10 | - Fix error on Constraint Templates view when the Template doesn't have a `Properties` key under the OpenAPIv3 Schema.
11 | - Switched `master` to `main`
12 |
13 | ### Updated dependencies
14 |
15 | Backend:
16 |
17 | - Python 3.9 -> 3.10
18 | - cachetools 4.2.2 -> 4.2.4
19 | - certifi 2021.5.30 -> 2021.10.8
20 | - cffi 1.14.6 -> 1.15.0
21 | - charset-normalizer 2.0.4 -> 2.0.7
22 | - click 8.0.1 -> 8.0.3
23 | - cryptography 3.4.7 -> 36.0.1
24 | - Flask-pyoidc 3.7.0 -> 3.8.0
25 | - google-auth 2.0.0 -> 2.3.3
26 | - idna 3.2 -> 3.3
27 | - importlib-resources 5.2.2 -> 5.4.0
28 | - Jinja2 3.0.1 -> 3.0.3
29 | - Mako 1.1.4 -> 1.1.5
30 | - pycparser 2.20 -> 2.21
31 | - pycryptodomex 3.10.1 -> 3.12.0
32 | - PyYAML 5.4.1 -> 6.0
33 | - requests 2.26.0 -> 2.27.1
34 | - rsa 4.7.2 -> 4.8
35 | - typing-extensions 3.10.0.0 -> 4.0.1
36 | - urllib3 1.26.6 -> 1.26.8
37 | - websocket-client 1.2.1 -> 1.2.3
38 | - Werkzeug 2.0.1 -> 2.0.2
39 | - zipp 3.5.0 -> 3.7.0
40 |
41 | Frontend:
42 |
43 | - fomantic-ui 2.8.7 -> 2.8.8
44 |
45 | ### Breaking changes
46 |
47 | No breaking changes.
48 |
--------------------------------------------------------------------------------
/app/web-client/src/pages/Logout/Component.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 {
8 | EuiButton,
9 | EuiFlexGroup,
10 | EuiFlexItem,
11 | EuiPage,
12 | EuiSpacer,
13 | EuiText,
14 | } from "@elastic/eui";
15 |
16 | function LogoutComponent() {
17 | return (
18 |
28 |
33 |
34 |
35 | You've been successfully logged out!
36 |
37 |
38 |
39 |
45 | Go to home
46 |
47 |
48 |
49 |
50 |
51 | );
52 | }
53 |
54 | export default LogoutComponent;
55 |
--------------------------------------------------------------------------------
/app/web-client/src/utils.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 | export function scrollToElement(hash: string, smooth: boolean = false) {
8 | const element = document.querySelector(hash.replace(/:|\./g, '\\$&'));
9 |
10 | if (!element) {
11 | return;
12 | }
13 |
14 | element?.firstElementChild?.classList.toggle("highlighted");
15 |
16 | if (smooth) {
17 | element.scrollIntoView({ behavior: "smooth", block: "start" });
18 | } else {
19 | element.scrollIntoView({ block: "start" });
20 | }
21 |
22 | setTimeout(() => {
23 | element?.firstElementChild?.classList.toggle("highlighted");
24 | }, 1000);
25 | }
26 |
27 | export function autoLink(text: string) {
28 | const delimiter = /((?:https?:\/\/)(?:(?:[a-z0-9]?(?:[a-z0-9\-]{1,61}[a-z0-9])?\.[^\.|\s])+[a-z\.]*[a-z]+|(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3})(?::\d{1,5})*[a-z0-9.,_\/~#&=;%+?\-\\(\\)]*)/gi;
29 | return (
30 | <>
31 | {text.split(delimiter).map(word => {
32 | const match = word.match(delimiter);
33 | if (match) {
34 | const url = match[0];
35 | return (
36 | {url}
37 | );
38 | }
39 | return word;
40 | })}
41 | >
42 | );
43 | };
--------------------------------------------------------------------------------
/manifests/deployment.yaml:
--------------------------------------------------------------------------------
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 | apiVersion: apps/v1
6 | kind: Deployment
7 | metadata:
8 | name: gatekeeper-policy-manager
9 | spec:
10 | replicas: 1
11 | selector:
12 | matchLabels:
13 | app: gatekeeper-policy-manager
14 | template:
15 | metadata:
16 | labels:
17 | app: gatekeeper-policy-manager
18 | spec:
19 | serviceAccountName: gatekeeper-policy-manager
20 | containers:
21 | - name: gatekeeper-policy-manager
22 | image: quay.io/sighup/gatekeeper-policy-manager
23 | imagePullPolicy: Always
24 | resources:
25 | requests:
26 | memory: "128Mi"
27 | cpu: "100m"
28 | limits:
29 | memory: "256Mi"
30 | cpu: "500m"
31 | livenessProbe:
32 | httpGet:
33 | path: /health
34 | port: http
35 | readinessProbe:
36 | httpGet:
37 | path: /health
38 | port: http
39 | ports:
40 | - containerPort: 8080
41 | name: http
42 | securityContext:
43 | privileged: false
44 | runAsNonRoot: true
45 | allowPrivilegeEscalation: false
46 | seccompProfile:
47 | type: RuntimeDefault
48 | capabilities:
49 | drop:
50 | - ALL
51 |
--------------------------------------------------------------------------------
/chart/templates/rbac.yaml:
--------------------------------------------------------------------------------
1 | {{- if and .Values.rbac.create (eq .Values.clusterRole.create true) -}}
2 | apiVersion: rbac.authorization.k8s.io/v1
3 | kind: ClusterRole
4 | metadata:
5 | name: {{ template "gatekeeper-policy-manager.clusterRoleName" . }}
6 | labels:
7 | app: {{ template "gatekeeper-policy-manager.name" . }}
8 | chart: {{ template "gatekeeper-policy-manager.chart" . }}
9 | release: {{ .Release.Name }}
10 | heritage: {{ .Release.Service }}
11 | rules:
12 | - apiGroups: ["constraints.gatekeeper.sh"]
13 | resources: ["*"]
14 | verbs: ["get", "list", "watch"]
15 | - apiGroups: ["templates.gatekeeper.sh"]
16 | resources: ["*"]
17 | verbs: ["get", "list", "watch"]
18 | - apiGroups: ["config.gatekeeper.sh"]
19 | resources: ["*"]
20 | verbs: ["get", "list", "watch"]
21 | ---
22 | apiVersion: rbac.authorization.k8s.io/v1
23 | kind: ClusterRoleBinding
24 | metadata:
25 | name: {{ template "gatekeeper-policy-manager.clusterRoleName" . }}
26 | labels:
27 | app: {{ template "gatekeeper-policy-manager.name" . }}
28 | chart: {{ template "gatekeeper-policy-manager.chart" . }}
29 | release: {{ .Release.Name }}
30 | heritage: {{ .Release.Service }}
31 | roleRef:
32 | apiGroup: rbac.authorization.k8s.io
33 | kind: ClusterRole
34 | name: {{ template "gatekeeper-policy-manager.clusterRoleName" . }}
35 | subjects:
36 | - name: {{ template "gatekeeper-policy-manager.serviceAccountName" . }}
37 | namespace: {{ .Release.Namespace | quote }}
38 | kind: ServiceAccount
39 | {{- end -}}
--------------------------------------------------------------------------------
/app/web-client/src/pages/NotFound/Component.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 {
8 | EuiButton,
9 | EuiFlexGroup,
10 | EuiFlexItem,
11 | EuiPage,
12 | EuiSpacer,
13 | EuiText,
14 | } from "@elastic/eui";
15 |
16 | function NotFoundComponent() {
17 | return (
18 |
28 |
33 |
34 |
35 | 404
36 |
37 |
38 |
39 |
40 | Page not found
41 |
42 |
43 |
44 |
50 | Go to home
51 |
52 |
53 |
54 |
55 |
56 | );
57 | }
58 |
59 | export default NotFoundComponent;
60 |
--------------------------------------------------------------------------------
/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.
--------------------------------------------------------------------------------
/chart/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.
--------------------------------------------------------------------------------
/app/web-client/src/pages/ConstraintTemplates/types.ts:
--------------------------------------------------------------------------------
1 | import { IConstraint } from "../Constraints/types";
2 |
3 | /**
4 | * Copyright (c) 2017-present SIGHUP s.r.l All rights reserved.
5 | * Use of this source code is governed by a BSD-style
6 | * license that can be found in the LICENSE file.
7 | */
8 |
9 | export interface IConstraintTemplateSpecTarget {
10 | rego?: string;
11 | libs?: string[];
12 | target: string;
13 | code?: IConstraintTemplateSpecTargetCode[];
14 | }
15 |
16 | export interface IConstraintTemplateSpecTargetCode {
17 | engine: string;
18 | source: {
19 | rego: string;
20 | version: string;
21 | };
22 | }
23 |
24 | export interface IConstraintTemplateSpecStatusPod {
25 | id: string;
26 | observedGeneration: number;
27 | operations: string[];
28 | templateUID: string;
29 | }
30 |
31 | export interface IConstraintTemplate {
32 | apiVersion: string;
33 | kind: string;
34 | metadata: {
35 | name: string;
36 | namespace: string;
37 | creationTimestamp: string;
38 | labels: {
39 | [key: string]: string;
40 | };
41 | annotations?: {
42 | [key: string]: string;
43 | };
44 | };
45 | spec: {
46 | crd: {
47 | spec: {
48 | names: {
49 | kind: string;
50 | };
51 | validation: any;
52 | };
53 | };
54 | targets: IConstraintTemplateSpecTarget[];
55 | };
56 | status: {
57 | byPod: IConstraintTemplateSpecStatusPod[];
58 | created: boolean;
59 | };
60 | }
61 |
62 | export interface IRelatedConstraints {
63 | [key: string]: IConstraint[];
64 | }
65 |
66 | export interface IConstraintTemplateResponse {
67 | constrainttemplates: IConstraintTemplate[];
68 | constraints_by_constrainttemplates: IRelatedConstraints;
69 | }
70 |
--------------------------------------------------------------------------------
/app/web-client/src/pages/Constraints/types.ts:
--------------------------------------------------------------------------------
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 | export interface IConstraintStatusPod {
8 | id: string;
9 | observedGeneration: number;
10 | operations: string[];
11 | enforced: boolean;
12 | constraintUID: string;
13 | }
14 |
15 | export interface IConstraintStatusViolation {
16 | enforcementAction: string;
17 | kind: string;
18 | message: string;
19 | name: string;
20 | namespace: string;
21 | }
22 |
23 | export interface IConstraintSpecMatchKinds {
24 | apiGroups: string[];
25 | kinds: string[];
26 | }
27 |
28 | export interface IConstraintSpecMatchLabelSelector {
29 | matchExpressions?: {
30 | key: string;
31 | operator: string;
32 | values: string[];
33 | }[];
34 | matchLabels?: {
35 | [key: string]: string;
36 | };
37 | }
38 |
39 | export interface IConstraintSpec {
40 | enforcementAction: string;
41 | match?: {
42 | kinds?: IConstraintSpecMatchKinds[];
43 | scope?: string;
44 | namespaces?: string[];
45 | excludedNamespaces?: string[];
46 | labelSelector?: IConstraintSpecMatchLabelSelector;
47 | namespaceSelector?: IConstraintSpecMatchLabelSelector;
48 | name?: string;
49 | };
50 | parameters: {
51 | [key: string]: any;
52 | };
53 | }
54 |
55 | export interface IConstraint {
56 | apiVersion: string;
57 | kind: string;
58 | metadata: {
59 | name: string;
60 | creationTimestamp: string;
61 | };
62 | spec?: IConstraintSpec;
63 | status: {
64 | byPod: IConstraintStatusPod[];
65 | auditTimestamp: string;
66 | totalViolations?: number;
67 | violations: IConstraintStatusViolation[];
68 | };
69 | }
70 |
--------------------------------------------------------------------------------
/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": "^99.1.0",
13 | "@emotion/css": "^11.13.5",
14 | "@emotion/react": "^11.14.0",
15 | "@testing-library/jest-dom": "^6.8.0",
16 | "@testing-library/react": "^12.1.5",
17 | "@testing-library/user-event": "^14.6.1",
18 | "@types/jest": "^30.0.0",
19 | "@types/node": "^24.3.0",
20 | "@types/react": "^17.0.20",
21 | "@types/react-dom": "^17.0.2",
22 | "lodash.clonedeep": "^4.5.0",
23 | "prop-types": "^15.8.1",
24 | "react": "^17.0.2",
25 | "react-dom": "^17.0.2",
26 | "react-json-tree": "^0.20.0",
27 | "react-router-dom": "^6.30.2",
28 | "react-scripts": "5.0.1",
29 | "sass": "^1.90.0",
30 | "typescript": "^5.9.2",
31 | "web-vitals": "^5.1.0"
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 | }
--------------------------------------------------------------------------------
/app/web-client/src/pages/Home/Component.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 {
8 | EuiButton,
9 | EuiFlexGroup,
10 | EuiFlexItem,
11 | EuiImage,
12 | EuiPage,
13 | EuiSpacer,
14 | EuiText,
15 | } from "@elastic/eui";
16 | import logo from "../../assets/gpm-logo.svg";
17 | import { useContext } from "react";
18 | import { ApplicationContext } from "../../AppContext";
19 |
20 | function HomeComponent() {
21 | const appContextData = useContext(ApplicationContext);
22 |
23 | return (
24 |
34 |
39 |
40 |
41 |
42 |
43 |
44 | Welcome!
45 |
46 |
47 |
48 |
49 |
50 | Gatekeeper Policy Manager is a simple to use web-based tool to see
51 | the policies deployed in your cluster and their status
52 |
53 |
54 |
55 |
56 |
62 | See Constraints status
63 |
64 |
65 |
66 |
67 |
68 | );
69 | }
70 |
71 | export default HomeComponent;
72 |
--------------------------------------------------------------------------------
/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 | You need to enable JavaScript to run this app.
38 |
39 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/chart/templates/NOTES.txt:
--------------------------------------------------------------------------------
1 |
2 | Thank you for installing SIGHUP Gatekeeper Policy Manager, part of the SIGHUP Distribution
3 | https://docs.sighup.com | https://sighup.io
4 |
5 | This is open source software <3 check out the source code at:
6 | https://github.com/sighupio/gatekeeper-policy-manager
7 |
8 | Feel free to send us feedback and report if you find any issue. Contributions are always apreciated.
9 |
10 | 1. Get the application URL by running these commands:
11 | {{- if .Values.ingress.enabled }}
12 | {{- range $host := .Values.ingress.hosts }}
13 | {{- range .paths }}
14 | http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ . }}
15 | {{- end }}
16 | {{- end }}
17 | {{- else if contains "NodePort" .Values.service.type }}
18 | export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "gatekeeper-policy-manager.fullname" . }})
19 | export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}")
20 | echo http://$NODE_IP:$NODE_PORT
21 | {{- else if contains "LoadBalancer" .Values.service.type }}
22 | NOTE: It may take a few minutes for the LoadBalancer IP to be available.
23 | You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "gatekeeper-policy-manager.fullname" . }}'
24 | export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "gatekeeper-policy-manager.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}")
25 | echo http://$SERVICE_IP:{{ .Values.service.port }}
26 | {{- else if contains "ClusterIP" .Values.service.type }}
27 | export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "gatekeeper-policy-manager.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}")
28 | export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}")
29 | echo "Visit http://127.0.0.1:8080 to use your application"
30 | kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT
31 | {{- end }}
32 |
--------------------------------------------------------------------------------
/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/src/components/Footer/Component.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 {
8 | EuiFlexGroup,
9 | EuiFlexItem,
10 | EuiIcon,
11 | EuiLink,
12 | EuiSpacer,
13 | EuiText,
14 | } from "@elastic/eui";
15 | import githubLogo from "../../assets/github-logo.svg";
16 | import "./Style.scss";
17 |
18 | function FooterComponent() {
19 | return (
20 |
21 |
22 |
23 |
24 |
25 | Gatekeeper Policy Manager v1.1.0
26 |
27 |
28 |
29 | A simple to use web-based Gatekeeper policies manager
30 |
31 |
32 |
33 |
34 |
35 | Proud part of the{" "}
36 |
37 | SIGHUP Distribution
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
53 | Source Code
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 | );
64 | }
65 |
66 | export default FooterComponent;
67 |
--------------------------------------------------------------------------------
/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 |
55 |
56 |
57 | );
58 | }
59 |
60 | export default App;
61 |
--------------------------------------------------------------------------------
/manifests/enable-oidc.yaml:
--------------------------------------------------------------------------------
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 | apiVersion: apps/v1
6 | kind: Deployment
7 | metadata:
8 | name: gatekeeper-policy-manager
9 | spec:
10 | template:
11 | spec:
12 | containers:
13 | - name: gatekeeper-policy-manager
14 | env:
15 | - name: GPM_OIDC_REDIRECT_DOMAIN
16 | value: "127-0-0-1.nip.io:8080"
17 | - name: GPM_SECRET_KEY
18 | value: "changeme!"
19 | # YOU SHOULD USE A KUBERNETES SECRET INSTEAD.
20 | # valueFrom:
21 | # secretKeyRef:
22 | # name: gpm-secrets
23 | # key: secret-key
24 | - name: GPM_PREFERRED_URL_SCHEME
25 | value: http
26 | - name: GPM_AUTH_ENABLED
27 | value: "OIDC"
28 | - name: GPM_OIDC_CLIENT_ID
29 | value: gatekeeper-policy-manager
30 | - name: GPM_OIDC_CLIENT_SECRET
31 | value: "30d6b009-9ae4-42b0-a5c0-b4f65aa6451e"
32 | # YOU SHOULD USE A KUBERNETES SECRET INSTEAD.
33 | # valueFrom:
34 | # secretKeyRef:
35 | # name: gpm-secrets
36 | # key: oidc-client-secret
37 | # The following URLs are an example of a Keycloak OIDC provider:
38 | - name: GPM_OIDC_ISSUER
39 | value: http://192.168.1.6:8081/auth/realms/devops
40 | - name: GPM_OIDC_AUTHORIZATION_ENDPOINT
41 | value: http://192.168.1.6:8081/auth/realms/devops/protocol/openid-connect/auth
42 | - name: GPM_OIDC_JWKS_URI
43 | value: http://192.168.1.6:8081/auth/realms/devops/protocol/openid-connect/certs
44 | - name: GPM_OIDC_TOKEN_ENDPOINT
45 | value: http://192.168.1.6:8081/auth/realms/devops/protocol/openid-connect/token
46 | - name: GPM_OIDC_INTROSPECTION_ENDPOINT
47 | value: http://192.168.1.6:8081/auth/realms/devops/protocol/openid-connect/token/introspect
48 | - name: GPM_OIDC_USERINFO_ENDPOINT
49 | value: http://192.168.1.6:8081/auth/realms/devops/protocol/openid-connect/userinfo
50 | - name: GPM_OIDC_END_SESSION_ENDPOINT
51 | value: http://192.168.1.6:8081/auth/realms/devops/protocol/openid-connect/logout
--------------------------------------------------------------------------------
/docs/releases/v0.5.0.md:
--------------------------------------------------------------------------------
1 | # v0.5.0
2 |
3 | Gatekeeper Policy Manager version 0.5.0
4 |
5 | ## Changes from v0.4.2
6 |
7 | - Added support for multicluster management, just mount a kubeconfig with the contexts defined and you'll be able to select them from the UI, see [the README](/README.md#Multi-cluster-support) for more info.
8 | - Added report generation for constraints violations.
9 | - Added listing all the Constraints for each Constraint Template
10 | - Added an official Helm Chart to the repository (thanks @kg-ops for the contribution! #68).
11 | - Source code quality improvements.
12 | - Changed base docker image (python + uwscgi + nginx) for a simpler one (python + gunicron), dropping the need to run as root.
13 | - We've reviewed all the dependencies, updated the ones that needed to be updated, dropped some of them that were not used anymore and we also divided the `requirements.txt` file into 3:
14 | - `requirements-base.txt`: this file has the base dependencies needed by GPM.
15 | - `requirements-dev.txt`: this file has the dependencies needed to set up a development environment.
16 | - `requirements.txt`: this file has all the base dependencies and their dependencies with the versions pinned.
17 |
18 | ### Bugfixes
19 |
20 | - Fixed a bug in the way ConstraintTemplates' Parameters Schema was shown when having a property that itself has more than one property. Properties will appear more than once inside other properties.
21 |
22 | ### Updated dependencies
23 |
24 | - astroid (dropped)
25 | - certifi 2020.12.5 -> 2021.5.30
26 | - cffi 1.14.5 -> 1.14.6
27 | - chardet (dropped)
28 | - click 7.1.2 -> 8.0.1
29 | - Flask 1.1.2 -> 2.0.1
30 | - google-auth 1.30.0 -> 2.0.0
31 | - gunicorn 20.1.0 (new)
32 | - idna (dropped)
33 | - importlib-metadata (dropped)
34 | - importlib-resources 5.1.2 -> 5.2.2
35 | - isort (dropped)
36 | - itsdangerous 1.1.0 -> 2.0.1
37 | - Jinja2 2.11.3 -> 3.0.1
38 | - kubernetes 12.0.1 -> 18.20.0
39 | - lazy-object-proxy (dropped)
40 | - MarkupSafe 1.1.1 -> 2.0.1
41 | - mccabe (dropped)
42 | - oauthlib 3.1.0 -> 3.1.1
43 | - oic 1.2.1 -> 1.3.0
44 | - python-dateutil 2.8.1 -> 2.8.2
45 | - requests 2.25.1 -> 2.26.0
46 | - six 1.15.0 -> 1.16.0
47 | - typed-ast (dropped)
48 | - typing-extensions 3.7.4.3 -> 3.10.0.0
49 | - urllib3 1.26.4 -> 1.26.6
50 | - websocket-client 0.58.0 -> 1.2.1
51 | - Werkzeug 1.0.1 -> 2.0.1
52 | - wrapt (dropped)
53 | - zipp 3.4.1 -> 3.5.0
54 |
55 | ### Breaking changes
56 |
57 | No breaking changes.
58 |
--------------------------------------------------------------------------------
/chart/templates/ingress.yaml:
--------------------------------------------------------------------------------
1 | {{- if .Values.ingress.enabled -}}
2 | {{- $fullName := include "gatekeeper-policy-manager.fullname" . -}}
3 | {{- $svcPort := .Values.service.port -}}
4 | {{- if .Capabilities.APIVersions.Has "networking.k8s.io/v1" }}
5 | apiVersion: networking.k8s.io/v1
6 | {{ else if .Capabilities.APIVersions.Has "networking.k8s.io/v1beta1" }}
7 | apiVersion: networking.k8s.io/v1beta1
8 | {{ else }}
9 | apiVersion: extensions/v1beta1
10 | {{ end -}}
11 | kind: Ingress
12 | metadata:
13 | name: {{ $fullName }}
14 | labels:
15 | {{- include "gatekeeper-policy-manager.labels" . | nindent 4 }}
16 | {{- with .Values.ingress.labels }}
17 | {{- toYaml . | nindent 4 }}
18 | {{- end }}
19 | {{- with .Values.ingress.annotations }}
20 | annotations:
21 | {{- toYaml . | nindent 4 }}
22 | {{- end }}
23 | {{- if .Capabilities.APIVersions.Has "networking.k8s.io/v1" }}
24 | spec:
25 | {{- if .Values.ingress.ingressClassName }}
26 | ingressClassName: {{ .Values.ingress.ingressClassName }}
27 | {{- end }}
28 | {{- if .Values.ingress.tls }}
29 | tls:
30 | {{- range .Values.ingress.tls }}
31 | - hosts:
32 | {{- range .hosts }}
33 | - {{ . | quote }}
34 | {{- end }}
35 | secretName: {{ .secretName }}
36 | {{- end }}
37 | {{- end }}
38 | rules:
39 | {{- range $key, $value := .Values.ingress.hosts }}
40 | - host: {{ $value.host | quote }}
41 | http:
42 | paths:
43 | {{- range .paths }}
44 | - backend:
45 | service:
46 | name: {{ $fullName }}
47 | port:
48 | number: {{ $svcPort }}
49 | path: {{ . }}
50 | pathType: {{ default "ImplementationSpecific" $value.pathType }}
51 | {{- end }}
52 | {{- end }}
53 | {{ else }}
54 | spec:
55 | {{- if .Values.ingress.tls }}
56 | tls:
57 | {{- range .Values.ingress.tls }}
58 | - hosts:
59 | {{- range .hosts }}
60 | - {{ . | quote }}
61 | {{- end }}
62 | secretName: {{ .secretName }}
63 | {{- end }}
64 | {{- end }}
65 | rules:
66 | {{- range .Values.ingress.hosts }}
67 | - host: {{ .host | quote }}
68 | http:
69 | paths:
70 | {{- range .paths }}
71 | - path: {{ . }}
72 | backend:
73 | serviceName: {{ $fullName }}
74 | servicePort: {{ $svcPort }}
75 | {{- end }}
76 | {{- end }}
77 | {{- end }}
78 | {{- end }}
--------------------------------------------------------------------------------
/chart/templates/_helpers.tpl:
--------------------------------------------------------------------------------
1 | {{/*
2 | Expand the name of the chart.
3 | */}}
4 | {{- define "gatekeeper-policy-manager.name" -}}
5 | {{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
6 | {{- end }}
7 |
8 | {{/*
9 | Create a default fully qualified app name.
10 | We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
11 | If release name contains chart name it will be used as a full name.
12 | */}}
13 | {{- define "gatekeeper-policy-manager.fullname" -}}
14 | {{- if .Values.fullnameOverride }}
15 | {{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
16 | {{- else }}
17 | {{- $name := default .Chart.Name .Values.nameOverride }}
18 | {{- if contains $name .Release.Name }}
19 | {{- .Release.Name | trunc 63 | trimSuffix "-" }}
20 | {{- else }}
21 | {{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
22 | {{- end }}
23 | {{- end }}
24 | {{- end }}
25 |
26 | {{/*
27 | Create chart name and version as used by the chart label.
28 | */}}
29 | {{- define "gatekeeper-policy-manager.chart" -}}
30 | {{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
31 | {{- end }}
32 |
33 | {{/*
34 | Common labels
35 | */}}
36 | {{- define "gatekeeper-policy-manager.labels" -}}
37 | helm.sh/chart: {{ include "gatekeeper-policy-manager.chart" . }}
38 | {{ include "gatekeeper-policy-manager.selectorLabels" . }}
39 | {{- if .Chart.AppVersion }}
40 | app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
41 | {{- end }}
42 | app.kubernetes.io/managed-by: {{ .Release.Service }}
43 | {{- end }}
44 |
45 | {{/*
46 | Selector labels
47 | */}}
48 | {{- define "gatekeeper-policy-manager.selectorLabels" -}}
49 | app.kubernetes.io/name: {{ include "gatekeeper-policy-manager.name" . }}
50 | app.kubernetes.io/instance: {{ .Release.Name }}
51 | {{- end }}
52 |
53 | {{/*
54 | Create the name of the service account to use
55 | */}}
56 | {{- define "gatekeeper-policy-manager.serviceAccountName" -}}
57 | {{- if .Values.serviceAccount.create }}
58 | {{- default (include "gatekeeper-policy-manager.fullname" .) .Values.serviceAccount.name }}
59 | {{- else }}
60 | {{- default "default" .Values.serviceAccount.name }}
61 | {{- end }}
62 | {{- end }}
63 |
64 | {{/*
65 | Create the name of the cluster role to use.
66 | */}}
67 | {{- define "gatekeeper-policy-manager.clusterRoleName" -}}
68 | {{- if .Values.clusterRole.create -}}
69 | {{ default (include "gatekeeper-policy-manager.fullname" .) .Values.clusterRole.name }}
70 | {{- else -}}
71 | {{ default "default" .Values.clusterRole.name }}
72 | {{- end -}}
73 | {{- end -}}
74 |
75 |
--------------------------------------------------------------------------------
/.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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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/pages/Error/Component.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 {
8 | EuiButton,
9 | EuiCallOut,
10 | EuiFlexGroup,
11 | EuiFlexItem,
12 | EuiIcon,
13 | EuiPage,
14 | EuiSpacer,
15 | EuiText,
16 | } from "@elastic/eui";
17 | import { useContext, useEffect, useState } from "react";
18 | import { useLocation, useNavigate } from "react-router-dom";
19 | import { ErrorPageState } from "./types";
20 | import { ApplicationContext } from "../../AppContext";
21 |
22 | function ErrorComponent() {
23 | const { state } = useLocation();
24 | const navigate = useNavigate();
25 | const [initialContext, setInitialContext] = useState();
26 | const appContextData = useContext(ApplicationContext);
27 |
28 | useEffect(() => {
29 | if (
30 | initialContext === undefined &&
31 | appContextData.context.currentK8sContext !== undefined
32 | ) {
33 | setInitialContext(appContextData.context.currentK8sContext);
34 | }
35 |
36 | if (
37 | initialContext !== undefined &&
38 | appContextData.context.currentK8sContext !== initialContext
39 | ) {
40 | navigate("/");
41 | }
42 | }, [appContextData.context.currentK8sContext])
43 |
44 | return (
45 |
55 |
60 |
61 |
62 |
63 |
68 | Error
69 |
70 |
71 |
72 |
73 |
74 | {(state as ErrorPageState)?.error?.error}
75 |
76 |
77 |
78 |
79 | {(state as ErrorPageState)?.error?.action}
80 |
81 |
82 |
83 | {(state as ErrorPageState)?.error?.description}
84 |
85 |
86 |
92 | Go back
93 |
94 |
95 |
96 |
97 |
98 | );
99 | }
100 |
101 | export default ErrorComponent;
102 |
--------------------------------------------------------------------------------
/tests/tests.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bats
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 | # shellcheck disable=SC2154
7 |
8 | load ./helper
9 |
10 | @test "Requirements" {
11 | info
12 | ns(){
13 | kubectl create ns gatekeeper-system
14 | # We create the CRD so the apply doesn't fail. We don't care about the servicemonitor and the rule actually
15 | kubectl apply -f https://raw.githubusercontent.com/sighupio/module-monitoring/v3.5.0/katalog/prometheus-operator/crds/0servicemonitorCustomResourceDefinition.yaml
16 | kubectl apply -f https://raw.githubusercontent.com/sighupio/module-monitoring/v3.5.0/katalog/prometheus-operator/crds/0prometheusruleCustomResourceDefinition.yaml
17 | }
18 | run ns
19 | [ "$status" -eq 0 ]
20 | }
21 |
22 | @test "Deploy" {
23 | info
24 | deploy(){
25 | kustomize build --load-restrictor LoadRestrictionsNone tests/ | kubectl apply -f -
26 | }
27 | loop_it deploy 10 5
28 | status=${loop_it_result}
29 | [ "$status" -eq 0 ]
30 | }
31 |
32 | @test "Wait until Gatekeeper Controller is ready" {
33 | info
34 | ready(){
35 | kubectl -n gatekeeper-system wait --for=condition=available --timeout=120s deployment/gatekeeper-controller-manager
36 | }
37 | run ready
38 | [ "$status" -eq 0 ]
39 | }
40 |
41 | @test "Wait until GPM is ready" {
42 | info
43 | ready(){
44 | kubectl -n gatekeeper-system wait --for=condition=available --timeout=120s deployment/gatekeeper-policy-manager
45 | }
46 | run ready
47 | [ "$status" -eq 0 ]
48 | }
49 |
50 | @test "Run tests" {
51 | info
52 | deploy_test(){
53 | kubectl -n kube-system apply -f tests/e2e-tests.yaml
54 | }
55 | run deploy_test
56 | [ "$status" -eq 0 ]
57 | }
58 |
59 | @test "Check tests result" {
60 | info
61 | test(){
62 | kubectl -n kube-system wait --for=condition=complete --timeout=300s job/e2e-tests
63 | }
64 | run test
65 | [ "$status" -eq 0 ]
66 | }
67 |
68 | @test "[AUDIT] check violations are present" {
69 | info
70 | wait_violations(){
71 | kubectl get k8slivenessprobe.constraints.gatekeeper.sh liveness-probe -o go-template="{{.status.totalViolations}}"
72 | echo "number of violations for liveness-probe constraint is: ${output}"
73 | echo "command status is: ${status}"
74 | [[ "$output" -eq 2 ]]
75 | [[ "$status" -eq 0 ]]
76 | }
77 | loop_it wait_violations 10 5
78 | }
79 |
80 | # Teardown gets called after each test.
81 | # There's also teardown_file that gets called once but I could not make it work.
82 | # Leving this for debug purposes
83 | teardown() {
84 | echo
85 | echo " ---------| EVENTS |-------- "
86 | kubectl get events
87 | echo
88 | echo " ---------| PODS |-------- "
89 | kubectl get pods -A
90 | echo
91 | echo " ---------| PODS DESCRIPTION |-------- "
92 | kubectl describe pods -n gatekeeper-system
93 | echo
94 | echo " ---------| GATEKEEPER LOGS |-------- "
95 | kubectl logs -n gatekeeper-system --selector gatekeeper.sh/system=yes
96 | echo
97 | echo " ---------| KUBEPROXY LOGS |-------- "
98 | kubectl logs -n kube-system --selector k8s-app=kube-proxy
99 | echo
100 | echo " ---------| LOCAL STORAGE LOGS |-------- "
101 | kubectl logs -n local-path-storage --selector app=local-path-provisioner
102 |
103 | # Don't fail test if teardown fails for some reason
104 | return 0
105 | }
106 |
--------------------------------------------------------------------------------
/app/web-client/src/index.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, no-invalid-position-at-import-rule, value-keyword-case */
8 | @font-face {
9 | font-family: Poppins;
10 | src: url("./assets/fonts/Poppins-Light.ttf") format("truetype");
11 | font-weight: 300;
12 | font-style: normal;
13 | }
14 |
15 | @font-face {
16 | font-family: Poppins;
17 | src: url("./assets/fonts/Poppins-Regular.ttf") format("truetype");
18 | font-weight: 400;
19 | font-style: normal;
20 | }
21 |
22 | @font-face {
23 | font-family: Poppins;
24 | src: url("./assets/fonts/Poppins-Medium.ttf") format("truetype");
25 | font-weight: 500;
26 | font-style: normal;
27 | }
28 |
29 | @font-face {
30 | font-family: Poppins;
31 | src: url("./assets/fonts/Poppins-SemiBold.ttf") format("truetype");
32 | font-weight: 600;
33 | font-style: normal;
34 | }
35 |
36 | @font-face {
37 | font-family: Poppins;
38 | src: url("./assets/fonts/Poppins-Bold.ttf") format("truetype");
39 | font-weight: 700;
40 | font-style: normal;
41 | }
42 |
43 | @font-face {
44 | font-family: "JetBrains Mono";
45 | src: url("./assets/fonts/JetBrainsMono-Regular.ttf") format("truetype");
46 | font-weight: 400;
47 | font-style: normal;
48 | }
49 |
50 | @font-face {
51 | font-family: "JetBrains Mono";
52 | src: url("./assets/fonts/JetBrainsMono-Bold.ttf") format("truetype");
53 | font-weight: 800;
54 | font-style: normal;
55 | }
56 |
57 | $euiColorPrimary: #6b2d9f;
58 | $euiFontFamily: "Poppins", -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
59 | $euiCodeFontFamily: "JetBrains Mono", Consolas, Menlo, Courier, monospace;
60 | $euiTitle: "Poppins", -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
61 |
62 | .euiTab.euiTab-isSelected {
63 | box-shadow: inset 0 -2px 0 $euiColorPrimary;
64 |
65 | &.euiTab.euiTab-isSelected .euiTab__content {
66 | color: $euiColorPrimary !important;
67 | }
68 | }
69 |
70 | .euiCodeBlock .euiCodeBlock__code {
71 | font-family: $euiCodeFontFamily;
72 | }
73 |
74 | .euiFormLabel.euiFormLabel-isFocused {
75 | color: $euiColorPrimary;
76 | }
77 |
78 | .euiButton {
79 | border-radius: 8px !important;
80 | }
81 |
82 | .euiPagination__compressedText > span:first-of-type {
83 | color: $euiColorPrimary;
84 | }
85 |
86 | .euiSideNavItemButton.euiSideNavItemButton-isSelected {
87 | color: $euiColorPrimary;
88 | }
89 |
90 | .euiSelect,
91 | .euiTextArea,
92 | .euiFieldText,
93 | .euiFieldNumber,
94 | .euiFieldSearch,
95 | .euiButtonEmpty,
96 | .euiFieldPassword,
97 | .euiComboBox .euiComboBox__inputWrap {
98 | font-family: $euiFontFamily;
99 | }
100 |
101 | .euiFieldText--compressed:focus,
102 | .euiFieldNumber--compressed:focus,
103 | .euiFieldPassword--compressed:focus,
104 | .euiFieldSearch--compressed:focus,
105 | .euiSuperSelectControl:focus,
106 | .euiTextArea:focus,
107 | .euiSelect:focus,
108 | .euiFieldText:focus,
109 | .euiSuperSelectControl.euiSuperSelect--isOpen__button,
110 | .euiFilePicker__input:focus + .euiFilePicker__prompt,
111 | .euiComboBox.euiComboBox-isOpen .euiComboBox__inputWrap,
112 | .euiComboBox.euiComboBox-isOpen .euiComboBox__inputWrap--compressed {
113 | background-image: linear-gradient(to top, $euiColorPrimary, $euiColorPrimary 2px, transparent 2px, transparent 100%);
114 | box-shadow: inset 0 0 0 1px rgb(107 45 159 / 10%);
115 | }
116 |
117 | .euiSuperSelect__item:focus {
118 | background-color: rgb(225 213 236 / 50%);
119 | }
120 |
121 | .euiSwitch .euiSwitch__body {
122 | background-color: $euiColorPrimary;
123 | }
124 |
125 | /* TODO: bug on modals with red background - check after EUI updates */
126 | .euiModalBody .euiModalBody__overflow {
127 | mask-image: none;
128 | }
129 |
130 | body {
131 | margin: 0;
132 | -webkit-font-smoothing: antialiased;
133 | -moz-osx-font-smoothing: grayscale;
134 | }
135 |
--------------------------------------------------------------------------------
/chart/README.md:
--------------------------------------------------------------------------------
1 | # Gatekeeper Policy Manager Helm Chart - v0.14.0
2 |
3 | A Helm chart for Gatekeeper Policy Manager, a simple to use, read-only web UI for viewing OPA Gatekeeper policies' status in a Kubernetes Cluster.
4 |
5 | ## Configuration options
6 |
7 | The following table lists the configurable parameters of the Gatekeeper Policy Manager chart and their default values.
8 |
9 | | Parameter | Description | Default |
10 | | --------- | ----------- | ------- |
11 | | `replicaCount` | | 1 |
12 | | `image.repository` | | "quay.io/sighup/gatekeeper-policy-manager" |
13 | | `image.pullPolicy` | | "IfNotPresent" |
14 | | `image.tag` | | "v1.1.0" |
15 | | `command` | | null |
16 | | `args` | | null |
17 | | `imagePullSecrets` | | [] |
18 | | `nameOverride` | | "" |
19 | | `fullnameOverride` | | "" |
20 | | `serviceAccount.create` | | true |
21 | | `serviceAccount.annotations` | | {} |
22 | | `serviceAccount.name` | | "gatekeeper-policy-manager" |
23 | | `podAnnotations` | | {} |
24 | | `podLabels` | | {} |
25 | | `podSecurityContext.runAsNonRoot` | | true |
26 | | `securityContext.runAsNonRoot` | | true |
27 | | `securityContext.privileged` | | false |
28 | | `securityContext.allowPrivilegeEscalation` | | false |
29 | | `securityContext.seccompProfile.type` | | "RuntimeDefault" |
30 | | `securityContext.capabilities.drop` | | ["ALL"] |
31 | | `service.annotations` | | {} |
32 | | `service.type` | | "ClusterIP" |
33 | | `service.port` | | 80 |
34 | | `ingress.enabled` | | false |
35 | | `ingress.annotations` | | {} |
36 | | `ingress.labels` | | {} |
37 | | `ingress.hosts` | | [{"host": "gpm.local", "paths": []}] |
38 | | `ingress.tls` | | [] |
39 | | `resources.requests.cpu` | | "100m" |
40 | | `resources.requests.memory` | | "128Mi" |
41 | | `resources.limits.cpu` | | "500m" |
42 | | `resources.limits.memory` | | "256Mi" |
43 | | `autoscaling.enabled` | | false |
44 | | `autoscaling.minReplicas` | | 1 |
45 | | `autoscaling.maxReplicas` | | 5 |
46 | | `autoscaling.targetCPUUtilizationPercentage` | | 80 |
47 | | `autoscaling.targetMemoryUtilizationPercentage` | | 80 |
48 | | `autoscaling.behavior` | | {} |
49 | | `autoscaling.metrics` | | [] |
50 | | `nodeSelector` | | {} |
51 | | `tolerations` | | [] |
52 | | `affinity` | | {} |
53 | | `topologySpreadConstraints` | | [] |
54 | | `config.preferredURLScheme` | | "http" |
55 | | `config.logLevel` | | "info" |
56 | | `config.secretKey` | | null |
57 | | `config.secretRef` | | null |
58 | | `config.multiCluster.enabled` | | false |
59 | | `config.multiCluster.kubeconfig` | | "apiVersion: v1\nclusters:\n- cluster:\n certificate-authority-data: REDACTED\n server: https://127.0.0.1:54216\n name: kind-kind\ncontexts:\n- context:\n cluster: kind-kind\n user: kind-kind\n name: kind-kind\ncurrent-context: kind-kind\nkind: Config\npreferences: {}\nusers:\n- name: kind-kind\n user:\n client-certificate-data: REDACTED\n client-key-data: REDACTED\n" |
60 | | `config.oidc.enabled` | | false |
61 | | `config.oidc.issuer` | | null |
62 | | `config.oidc.redirectDomain` | | null |
63 | | `config.oidc.clientID` | | null |
64 | | `config.oidc.clientSecret` | | null |
65 | | `config.oidc.authorizationEndpoint` | | null |
66 | | `config.oidc.jwksURI` | | null |
67 | | `config.oidc.tokenEndpoint` | | null |
68 | | `config.oidc.introspectionEndpoint` | | null |
69 | | `config.oidc.userinfoEndpoint` | | null |
70 | | `config.oidc.endSessionEndpoint` | | null |
71 | | `extraEnvs` | | [] |
72 | | `rbac.create` | | true |
73 | | `clusterRole.create` | | true |
74 | | `clusterRole.name` | | "gatekeeper-policy-manager-crd-view" |
75 | | `livenessProbe.enabled` | | true |
76 | | `livenessProbe.httpGet.path` | | "/health" |
77 | | `livenessProbe.httpGet.port` | | "http" |
78 | | `livenessProbe.initialDelaySeconds` | | 10 |
79 | | `livenessProbe.periodSeconds` | | 10 |
80 | | `livenessProbe.timeoutSeconds` | | 1 |
81 | | `livenessProbe.successThreshold` | | 1 |
82 | | `livenessProbe.failureThreshold` | | 3 |
83 | | `readinessProbe.enabled` | | true |
84 | | `readinessProbe.httpGet.path` | | "/health" |
85 | | `readinessProbe.httpGet.port` | | "http" |
86 | | `readinessProbe.initialDelaySeconds` | | 5 |
87 | | `readinessProbe.periodSeconds` | | 5 |
88 | | `readinessProbe.timeoutSeconds` | | 1 |
89 | | `readinessProbe.successThreshold` | | 1 |
90 | | `readinessProbe.failureThreshold` | | 3 |
91 |
92 |
--------------------------------------------------------------------------------
/docs/assets/logo.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/app/web-client/src/assets/gpm-logo.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/app/web-client/src/AppContextProvider.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, { useCallback, useEffect, useMemo, useState } from "react";
8 | import { ApplicationContext, IApplicationContextData } from "./AppContext";
9 |
10 | interface ContextProviderProps {
11 | children: React.ReactNode;
12 | }
13 |
14 | interface IK8sContext {
15 | context: {
16 | cluster: string;
17 | user: string;
18 | };
19 | name: string;
20 | }
21 |
22 | interface IAuthResponse {
23 | auth_enabled: boolean;
24 | }
25 |
26 | type K8sContextsResponse = IK8sContext[][] | IK8sContext[];
27 |
28 | const getDefaultContext = (): IApplicationContextData => {
29 | return {
30 | apiUrl:
31 | process.env.NODE_ENV !== "production" ? (process.env?.REACT_APP_LOCAL_GPM_SERVER_URL ?? "missing local url") : "/",
32 | authEnabled:
33 | JSON.parse(localStorage.getItem("authEnabled") ?? "false") || false,
34 | currentK8sContext: localStorage.getItem("currentK8sContext") || "",
35 | k8sContexts: localStorage.getItem("k8sContexts")
36 | ? JSON.parse(localStorage.getItem("k8sContexts") || "[]")
37 | : [],
38 | };
39 | };
40 |
41 | const ContextProvider = ({ children }: ContextProviderProps) => {
42 | const [appContext, setAppContext] = useState(
43 | getDefaultContext()
44 | );
45 |
46 | const setCurrentContext = useCallback(
47 | (updates: Partial) => {
48 | setAppContext({
49 | ...appContext,
50 | ...updates,
51 | });
52 |
53 | if (updates.currentK8sContext) {
54 | localStorage.setItem("currentK8sContext", updates.currentK8sContext);
55 | }
56 |
57 | if (updates.k8sContexts) {
58 | localStorage.setItem(
59 | "k8sContexts",
60 | JSON.stringify(updates.k8sContexts)
61 | );
62 | }
63 |
64 | if (updates.authEnabled) {
65 | localStorage.setItem(
66 | "authEnabled",
67 | JSON.stringify(updates.authEnabled)
68 | );
69 | }
70 | },
71 | [appContext, setAppContext]
72 | );
73 |
74 | const contextValue = useMemo(
75 | () => ({
76 | context: appContext,
77 | setContext: setCurrentContext,
78 | }),
79 | [appContext, setCurrentContext]
80 | );
81 |
82 | useEffect(() => {
83 | Promise.allSettled([
84 | fetch(`${appContext.apiUrl}api/v1/contexts/`)
85 | .then((res) => res.json())
86 | .then((body) => {
87 | if ((body?.length ?? 1) > 1) {
88 | const newContexts = (body[0] as IK8sContext[]).map((c) => c.name);
89 | const newCurrentContext =
90 | localStorage.getItem("currentK8sContext") ||
91 | (body[1] as IK8sContext).name;
92 |
93 | localStorage.setItem("k8sContexts", JSON.stringify(newContexts));
94 | localStorage.setItem("currentK8sContext", newCurrentContext);
95 |
96 | setAppContext({
97 | ...appContext,
98 | k8sContexts: newContexts,
99 | currentK8sContext: newCurrentContext,
100 | });
101 | } else {
102 | localStorage.removeItem("k8sContexts");
103 | localStorage.removeItem("currentK8sContext");
104 |
105 | setAppContext({
106 | ...appContext,
107 | k8sContexts: [],
108 | currentK8sContext: "",
109 | });
110 | }
111 | })
112 | .catch((err) => {
113 | localStorage.removeItem("k8sContexts");
114 | localStorage.removeItem("currentK8sContext");
115 | console.error(err);
116 | }),
117 | fetch(`${appContext.apiUrl}api/v1/auth/`)
118 | .then((res) => res.json())
119 | .then((body) => {
120 | localStorage.setItem(
121 | "authEnabled",
122 | JSON.stringify(body.auth_enabled)
123 | );
124 |
125 | setAppContext({
126 | ...appContext,
127 | authEnabled: body.auth_enabled,
128 | });
129 | })
130 | .catch((err) => {
131 | localStorage.setItem("authEnabled", "false");
132 | console.error(err);
133 | }),
134 | ]);
135 | }, []);
136 |
137 | return (
138 |
139 | {children}
140 |
141 | );
142 | };
143 |
144 | export default ContextProvider;
145 |
--------------------------------------------------------------------------------
/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 |
28 |
29 | We didn't find any Constraint CRDs defined in the cluster.
30 |
31 |
32 | {% else %}
33 | {% set limited_view = [] %}
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 | Constraint
42 | Action
43 | Kind
44 | Namespace
45 | Name
46 | Message
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 | {{ constraint.metadata.name }}
58 | {{
60 | violation.enforcementAction }}
61 | {{ violation.kind }}
62 | {{ violation.namespace }}
63 | {{ violation.name }}
64 | {{ violation.message }}
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 |
75 |
76 | {% if limited_view %}
77 |
78 |
79 |
80 |
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/src/components/Header/Component.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 {
8 | EuiButton,
9 | EuiButtonEmpty,
10 | EuiHeader,
11 | EuiHeaderSection,
12 | EuiHeaderSectionItem,
13 | EuiHideFor,
14 | EuiSuperSelect,
15 | EuiText,
16 | } from "@elastic/eui";
17 | import {
18 | MouseEventHandler,
19 | MouseEvent,
20 | useContext,
21 | useEffect,
22 | useState,
23 | } from "react";
24 | import { ApplicationContext } from "../../AppContext";
25 | import { EuiSuperSelectOption } from "@elastic/eui/src/components/form/super_select/super_select_item";
26 | import { useLocation, useNavigate } from "react-router-dom";
27 | import "./Style.scss";
28 |
29 | function HeaderComponent() {
30 | const [optionsFromContexts, setOptionsFromContexts] = useState<
31 | EuiSuperSelectOption[]
32 | >([]);
33 | const { context, setContext } = useContext(ApplicationContext);
34 | const { pathname, hash } = useLocation();
35 | const navigate = useNavigate();
36 |
37 | const pathSplit = pathname.match(/\/([^/]*)/gi);
38 |
39 | const routes = [
40 | {
41 | path: "/",
42 | name: "Home",
43 | },
44 | {
45 | path: "/constrainttemplates",
46 | name: "Constraint Templates",
47 | },
48 | {
49 | path: "/constraints",
50 | name: "Constraints",
51 | },
52 | {
53 | path: "/configurations",
54 | name: "Configurations",
55 | },
56 | ];
57 |
58 | useEffect(() => {
59 | const optionsFromContexts = context.k8sContexts.map((k8sContext) => {
60 | return {
61 | value: k8sContext,
62 | inputDisplay: k8sContext,
63 | dropdownDisplay: (
64 |
73 | {k8sContext}
74 |
75 | ),
76 | };
77 | });
78 | setOptionsFromContexts(optionsFromContexts);
79 |
80 | if (
81 | pathSplit &&
82 | pathSplit.length > 1 &&
83 | pathname !== "/" &&
84 | pathname !== "/error" &&
85 | context.k8sContexts.length > 0
86 | ) {
87 | if (setContext) {
88 | setContext({
89 | currentK8sContext: pathSplit[1].slice(1),
90 | });
91 | }
92 | }
93 | }, [context.k8sContexts]);
94 |
95 | const doLogout: MouseEventHandler = (
96 | event: MouseEvent,
97 | ): void => {
98 | event.preventDefault();
99 | window.location.replace("/logout");
100 | };
101 |
102 | const onChangeContext = (value: string) => {
103 | if (setContext) {
104 | setContext({
105 | currentK8sContext: value,
106 | });
107 |
108 | if (
109 | pathSplit &&
110 | pathSplit.length > 0 &&
111 | pathname !== "/" &&
112 | pathname !== "/error"
113 | ) {
114 | navigate(pathSplit[0] + "/" + encodeURIComponent(value) + hash, {
115 | replace: true,
116 | });
117 | navigate(0);
118 | }
119 | }
120 | };
121 |
122 | return (
123 |
124 |
125 |
126 |
127 | {routes &&
128 | routes.map((route) => {
129 | return (
130 |
138 |
144 | {route.name}
145 |
146 |
147 | );
148 | })}
149 |
150 |
151 | {optionsFromContexts.length > 0 && (
152 |
153 |
154 |
155 | Context:
156 |
157 |
158 | onChangeContext(value)}
164 | hasDividers
165 | placeholder="change current context"
166 | title={decodeURIComponent(context.currentK8sContext)}
167 | />
168 |
169 | )}
170 | {context.authEnabled && (
171 |
172 |
178 | Logout
179 |
180 |
181 | )}
182 |
183 |
184 |
185 |
186 | );
187 | }
188 |
189 | export default HeaderComponent;
190 |
--------------------------------------------------------------------------------
/chart/values.yaml:
--------------------------------------------------------------------------------
1 | # Default values for gatekeeper-policy-manager.
2 | # This is a YAML-formatted file.
3 | # Declare variables to be passed into your templates.
4 |
5 | replicaCount: 1
6 |
7 | image:
8 | repository: quay.io/sighup/gatekeeper-policy-manager
9 | pullPolicy: IfNotPresent
10 | # Overrides the image tag whose default is the chart appVersion.
11 | tag: "v1.1.0"
12 |
13 | # # Override gatekeeper-policy-manager container entrypoint/args
14 | # # See https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/
15 | command:
16 | # - gunicorn
17 | args:
18 | # - --bind=:8080
19 | # - --workers=2
20 | # - --threads=4
21 | # - --worker-class=gthread
22 | # - app:app
23 |
24 | imagePullSecrets: []
25 | nameOverride: ""
26 | fullnameOverride: ""
27 |
28 | serviceAccount:
29 | # Specifies whether a service account should be created
30 | create: true
31 | # Annotations to add to the service account
32 | annotations: {}
33 | # The name of the service account to use.
34 | # If not set and create is true, a name is generated using the fullname template
35 | name: "gatekeeper-policy-manager"
36 |
37 | podAnnotations: {}
38 |
39 | podLabels: {}
40 |
41 | # Specify security settings for the gatekeeper-policy-manager pod
42 | # See https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-pod
43 | podSecurityContext:
44 | runAsNonRoot: true
45 |
46 | # Set the security context for the main gatekeeper-policy-manager container,
47 | # which override settings made at the Pod level when there is overlap
48 | # See https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-container
49 | # and https://kubernetes.io/docs/concepts/security/pod-security-standards/
50 | securityContext:
51 | runAsNonRoot: true
52 | privileged: false
53 | allowPrivilegeEscalation: false
54 | seccompProfile:
55 | type: RuntimeDefault
56 | capabilities:
57 | drop:
58 | - ALL
59 |
60 | service:
61 | annotations: {}
62 | type: ClusterIP
63 | port: 80
64 |
65 | ingress:
66 | enabled: false
67 | # ingressClassName: "nginx"
68 | annotations:
69 | {}
70 | #kubernetes.io/ingress.class: "nginx"
71 | #nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
72 | #nginx.ingress.kubernetes.io/auth-signin: https://$host/oauth2/start?rd=https://$host$request_uri$is_args$args
73 | #nginx.ingress.kubernetes.io/auth-url: https://$host/oauth2/auth
74 | #nginx.ingress.kubernetes.io/proxy-buffer-size: "8k"
75 | #nginx.ingress.kubernetes.io/secure-backends: "true"
76 | #nginx.ingress.kubernetes.io/configuration-snippet: |
77 | # auth_request_set $token $upstream_http_authorization;
78 | # proxy_set_header Authorization $token;
79 | #forecastle.stakater.com/expose: "true"
80 | #forecastle.stakater.com/appName: "Gatekeeper Policy Manager"
81 | #forecastle.stakater.com/icon: "https://raw.githubusercontent.com/sighupio/gatekeeper-policy-manager/main/docs/assets/logo.svg"
82 | labels: {}
83 | hosts:
84 | - host: gpm.local
85 | paths: []
86 | # pathType: ImplementationSpecific
87 | tls: []
88 | # - secretName: gpm-tls
89 | # hosts:
90 | # - gpm.local
91 |
92 | resources:
93 | # We usually recommend not to specify default resources and to leave this as a conscious
94 | # choice for the user. This also increases chances charts run on environments with little
95 | # resources, such as Minikube. If you do want to specify resources, uncomment the following
96 | # lines, adjust them as necessary, and remove the curly braces after 'resources:'.
97 | requests:
98 | cpu: 100m
99 | memory: 128Mi
100 | limits:
101 | cpu: 500m
102 | memory: 256Mi
103 |
104 | autoscaling:
105 | enabled: false
106 | minReplicas: 1
107 | maxReplicas: 5
108 | targetCPUUtilizationPercentage: 80
109 | targetMemoryUtilizationPercentage: 80
110 | behavior: {}
111 | metrics: []
112 |
113 | nodeSelector: {}
114 |
115 | tolerations: []
116 |
117 | affinity: {}
118 |
119 | topologySpreadConstraints: []
120 |
121 | config:
122 | preferredURLScheme: http
123 | logLevel: info
124 | # secret in plain text
125 | secretKey: null
126 | # name of the secret containing the secret key. if set, config.secretKey should be null!
127 | # supported fields: secretKey
128 | secretRef: null
129 | multiCluster:
130 | enabled: false
131 | kubeconfig: |
132 | apiVersion: v1
133 | clusters:
134 | - cluster:
135 | certificate-authority-data: REDACTED
136 | server: https://127.0.0.1:54216
137 | name: kind-kind
138 | contexts:
139 | - context:
140 | cluster: kind-kind
141 | user: kind-kind
142 | name: kind-kind
143 | current-context: kind-kind
144 | kind: Config
145 | preferences: {}
146 | users:
147 | - name: kind-kind
148 | user:
149 | client-certificate-data: REDACTED
150 | client-key-data: REDACTED
151 | oidc:
152 | enabled: false
153 | issuer:
154 | redirectDomain:
155 | clientID:
156 | clientSecret:
157 | authorizationEndpoint:
158 | jwksURI:
159 | tokenEndpoint:
160 | introspectionEndpoint:
161 | userinfoEndpoint:
162 | endSessionEndpoint:
163 |
164 | # Extra env variables to pass to the gatekeeper-policy-manager container
165 | # Uncomment and add OIDC variables for enabling OIDC
166 | extraEnvs: []
167 |
168 | rbac:
169 | # Specifies whether RBAC resources should be created
170 | create: true
171 |
172 | # If create is `false` the Helm Operator will be restricted to the namespace
173 | # where it is deployed, and no ClusterRole or ClusterRoleBinding will be created.
174 | # Additionally, the kubeconfig default context will be set to that namespace.
175 | clusterRole:
176 | create: true
177 | # The name of a cluster role to bind to; if not set and create is
178 | # true, a name based on fullname is generated
179 | name: "gatekeeper-policy-manager-crd-view"
180 | # Health and liveness probe configurations
181 | livenessProbe:
182 | enabled: true
183 | httpGet:
184 | path: /health
185 | port: http
186 | initialDelaySeconds: 10
187 | periodSeconds: 10
188 | timeoutSeconds: 1
189 | successThreshold: 1
190 | failureThreshold: 3
191 |
192 | readinessProbe:
193 | enabled: true
194 | httpGet:
195 | path: /health
196 | port: http
197 | initialDelaySeconds: 5
198 | periodSeconds: 5
199 | timeoutSeconds: 1
200 | successThreshold: 1
201 | failureThreshold: 3
202 |
--------------------------------------------------------------------------------
/chart/templates/deployment.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: apps/v1
2 | kind: Deployment
3 | metadata:
4 | name: {{ include "gatekeeper-policy-manager.fullname" . }}
5 | labels:
6 | {{- include "gatekeeper-policy-manager.labels" . | nindent 4 }}
7 | spec:
8 | {{- if not .Values.autoscaling.enabled }}
9 | replicas: {{ .Values.replicaCount }}
10 | {{- end }}
11 | selector:
12 | matchLabels:
13 | {{- include "gatekeeper-policy-manager.selectorLabels" . | nindent 6 }}
14 | template:
15 | metadata:
16 | {{- with .Values.podAnnotations }}
17 | annotations:
18 | {{- toYaml . | nindent 8 }}
19 | {{- end }}
20 | labels:
21 | {{- include "gatekeeper-policy-manager.selectorLabels" . | nindent 8 }}
22 | {{- with .Values.podLabels }}
23 | {{- toYaml . | nindent 8 }}
24 | {{- end }}
25 | spec:
26 | {{- with .Values.imagePullSecrets }}
27 | imagePullSecrets:
28 | {{- toYaml . | nindent 8 }}
29 | {{- end }}
30 | serviceAccountName: {{ include "gatekeeper-policy-manager.serviceAccountName" . }}
31 | securityContext:
32 | {{- toYaml .Values.podSecurityContext | nindent 8 }}
33 | containers:
34 | - name: {{ .Chart.Name }}
35 | securityContext:
36 | {{- toYaml .Values.securityContext | nindent 12 }}
37 | image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
38 | imagePullPolicy: {{ .Values.image.pullPolicy }}
39 | {{- with .Values.command }}
40 | command:
41 | {{- toYaml . | nindent 12 }}
42 | {{- end }}
43 | {{- with .Values.args }}
44 | args:
45 | {{- toYaml . | nindent 12 }}
46 | {{- end }}
47 | ports:
48 | - name: http
49 | containerPort: 8080
50 | protocol: TCP
51 | {{- if .Values.livenessProbe.enabled }}
52 | livenessProbe:
53 | httpGet:
54 | path: {{ .Values.livenessProbe.httpGet.path }}
55 | port: {{ .Values.livenessProbe.httpGet.port }}
56 | initialDelaySeconds: {{ .Values.livenessProbe.initialDelaySeconds }}
57 | periodSeconds: {{ .Values.livenessProbe.periodSeconds }}
58 | timeoutSeconds: {{ .Values.livenessProbe.timeoutSeconds }}
59 | successThreshold: {{ .Values.livenessProbe.successThreshold }}
60 | failureThreshold: {{ .Values.livenessProbe.failureThreshold }}
61 | {{- end }}
62 | {{- if .Values.readinessProbe.enabled }}
63 | readinessProbe:
64 | httpGet:
65 | path: {{ .Values.readinessProbe.httpGet.path }}
66 | port: {{ .Values.readinessProbe.httpGet.port }}
67 | initialDelaySeconds: {{ .Values.readinessProbe.initialDelaySeconds }}
68 | periodSeconds: {{ .Values.readinessProbe.periodSeconds }}
69 | timeoutSeconds: {{ .Values.readinessProbe.timeoutSeconds }}
70 | successThreshold: {{ .Values.readinessProbe.successThreshold }}
71 | failureThreshold: {{ .Values.readinessProbe.failureThreshold }}
72 | {{- end }}
73 | env:
74 | - name: GPM_LOG_LEVEL
75 | value: {{ .Values.config.logLevel | upper | quote }}
76 | - name: GPM_PREFERRED_URL_SCHEME
77 | value: {{ required "A valid .Values.config.preferredURLScheme entry required! Choose either http or https" .Values.config.preferredURLScheme | quote }}
78 | {{- if .Values.config.secretKey }}
79 | - name: GPM_SECRET_KEY
80 | valueFrom:
81 | secretKeyRef:
82 | name: {{ include "gatekeeper-policy-manager.fullname" . }}
83 | key: secretKey
84 | {{- else if .Values.config.secretRef }}
85 | - name: GPM_SECRET_KEY
86 | valueFrom:
87 | secretKeyRef:
88 | name: {{ .Values.config.secretRef }}
89 | key: secretKey
90 | {{- end }}
91 | {{- if .Values.config.oidc.enabled }}
92 | - name: GPM_AUTH_ENABLED
93 | value: "OIDC"
94 | - name: GPM_OIDC_REDIRECT_DOMAIN
95 | value: {{ .Values.config.oidc.redirectDomain }}
96 | - name: GPM_OIDC_CLIENT_ID
97 | value: {{ .Values.config.oidc.clientID }}
98 | {{- if .Values.config.oidc.clientSecret}}
99 | - name: GPM_OIDC_CLIENT_SECRET
100 | valueFrom:
101 | secretKeyRef:
102 | name: {{ include "gatekeeper-policy-manager.fullname" . }}-oidc
103 | key: clientSecret
104 | {{- end }}
105 | - name: GPM_OIDC_ISSUER
106 | value: {{ .Values.config.oidc.issuer }}
107 | {{- if .Values.config.oidc.authorizationEndpoint }}
108 | - name: GPM_OIDC_AUTHORIZATION_ENDPOINT
109 | value: {{ .Values.config.oidc.authorizationEndpoint }}
110 | {{- end }}
111 | {{- if .Values.config.oidc.jwksURI }}
112 | - name: GPM_OIDC_JWKS_URI
113 | value: {{ .Values.config.oidc.jwksURI }}
114 | {{- end }}
115 | {{- if .Values.config.oidc.tokenEndpoint }}
116 | - name: GPM_OIDC_TOKEN_ENDPOINT
117 | value: {{ .Values.config.oidc.tokenEndpoint }}
118 | {{- end }}
119 | {{- if .Values.config.oidc.introspectionEndpoint }}
120 | - name: GPM_OIDC_INTROSPECTION_ENDPOINT
121 | value: {{ .Values.config.oidc.introspectionEndpoint }}
122 | {{- end }}
123 | {{- if .Values.config.oidc.userinfoEndpoint }}
124 | - name: GPM_OIDC_USERINFO_ENDPOINT
125 | value: {{ .Values.config.oidc.userinfoEndpoint }}
126 | {{- end }}
127 | {{- if .Values.config.oidc.endSessionEndpoint }}
128 | - name: GPM_OIDC_END_SESSION_ENDPOINT
129 | value: {{ .Values.config.oidc.endSessionEndpoint }}
130 | {{- end }}
131 | {{- end }}
132 | {{- if .Values.extraEnvs }}
133 | {{ toYaml .Values.extraEnvs | nindent 12 }}
134 | {{- end }}
135 | resources:
136 | {{- toYaml .Values.resources | nindent 12 }}
137 | {{- if .Values.config.multiCluster.enabled }}
138 | volumeMounts:
139 | - mountPath: /home/gpm/.kube/config
140 | name: kubeconfig
141 | subPath: kubeconfig
142 | volumes:
143 | - name: kubeconfig
144 | secret:
145 | secretName: {{ include "gatekeeper-policy-manager.fullname" . }}-multicluster
146 | {{- end -}}
147 | {{- with .Values.nodeSelector }}
148 | nodeSelector:
149 | {{- toYaml . | nindent 8 }}
150 | {{- end }}
151 | {{- with .Values.affinity }}
152 | affinity:
153 | {{- toYaml . | nindent 8 }}
154 | {{- end }}
155 | {{- with .Values.topologySpreadConstraints }}
156 | topologySpreadConstraints:
157 | {{- toYaml . | nindent 8 }}
158 | {{- end }}
159 | {{- with .Values.tolerations }}
160 | tolerations:
161 | {{- toYaml . | nindent 8 }}
162 | {{- end }}
163 |
--------------------------------------------------------------------------------
/app/web-client/src/pages/Configurations/Component.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 {
8 | EuiAccordion,
9 | EuiCodeBlock,
10 | EuiEmptyPrompt,
11 | EuiFlexGroup,
12 | EuiFlexItem,
13 | EuiHorizontalRule,
14 | EuiIcon,
15 | EuiLoadingSpinner,
16 | EuiPage,
17 | EuiPageBody,
18 | EuiPageSidebar,
19 | EuiPanel,
20 | EuiSideNav,
21 | EuiSpacer,
22 | EuiText,
23 | EuiTitle,
24 | htmlIdGenerator,
25 | } from "@elastic/eui";
26 | import { useCallback, useContext, useEffect, useRef, useState } from "react";
27 | import { BackendError, ISideNav, ISideNavItem } from "../types";
28 | import { ApplicationContext } from "../../AppContext";
29 | import { useLocation, useNavigate, useParams } from "react-router-dom";
30 | import { JSONTree } from "react-json-tree";
31 | import theme from "../theme";
32 | import { scrollToElement } from "../../utils";
33 | import { IConfig } from "./types";
34 | import useScrollToHash from "../../hooks/useScrollToHash";
35 | import useCurrentElementInView from "../../hooks/useCurrentElementInView";
36 | import "./Style.scss";
37 | import clonedeep from "lodash.clonedeep";
38 |
39 | function generateSideNav(list: IConfig[]): ISideNav[] {
40 | const sideBarItems = (list ?? []).map((item, index) => {
41 | return {
42 | key: `${item.metadata.name}-side`,
43 | name: item.metadata.name,
44 | id: htmlIdGenerator("constraints")(),
45 | onClick: () => {
46 | scrollToElement(`#${item.metadata.name}`, true);
47 | },
48 | isSelected: index === 0,
49 | } as ISideNavItem;
50 | });
51 |
52 | return [
53 | {
54 | name: "Configurations",
55 | id: htmlIdGenerator("constraints")(),
56 | items: sideBarItems,
57 | },
58 | ];
59 | }
60 |
61 | function SingleConfig(item: IConfig) {
62 | return (
63 |
64 |
65 |
66 |
71 |
72 |
73 |
74 | {item.metadata.name}
75 |
76 |
77 |
78 |
79 |
80 |
83 | NAMESPACE:{" "}
84 | {" "}
85 | {item.metadata.namespace}
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
101 |
105 | {JSON.stringify(
106 | item,
107 | (k, v) => {
108 | if (typeof v === "string") {
109 | return v.replace(/\n/g, "").replace(/"/g, "'");
110 | }
111 |
112 | return v;
113 | },
114 | 2
115 | )}
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 | {!item.spec ? (
126 | <>
127 |
128 |
129 |
130 |
131 |
132 |
133 | This Configuration has no spec defined
134 |
135 |
136 |
137 | >
138 | ) : (
139 | <>
140 |
141 |
142 |
143 |
144 | Spec definition for configuration
145 |
146 |
147 |
148 |
149 | true}
152 | hideRoot={true}
153 | theme={theme}
154 | invertTheme={false}
155 | />
156 |
157 |
158 | >
159 | )}
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 | created on {item.metadata.creationTimestamp}
169 |
170 |
171 |
172 |
173 | );
174 | }
175 |
176 | function ConfigurationsComponent() {
177 | const [sideNav, setSideNav] = useState([]);
178 | const [isLoading, setIsLoading] = useState(true);
179 | const [items, setItems] = useState([]);
180 | const [currentElementInView, setCurrentElementInView] = useState("");
181 | const [fullyLoadedRefs, setFullyLoadedRefs] = useState(false);
182 | const panelsRef = useRef([]);
183 | const appContextData = useContext(ApplicationContext);
184 | const { hash } = useLocation();
185 | const navigate = useNavigate();
186 | const { context } = useParams<"context">();
187 |
188 | const onRefChange = useCallback(
189 | (element: HTMLDivElement | null, index: number) => {
190 | if (!element) {
191 | return;
192 | }
193 |
194 | panelsRef.current[index] = element;
195 |
196 | if (index === items.length - 1) {
197 | setFullyLoadedRefs(true);
198 | }
199 | },
200 | [panelsRef, items]
201 | );
202 |
203 | useEffect(() => {
204 | setIsLoading(true);
205 | fetch(
206 | `${appContextData.context.apiUrl}api/v1/configs/${context ?
207 | context + "/" : ""}`
208 | )
209 | .then(async (res) => {
210 | const body: IConfig[] = await res.json();
211 |
212 | if (!res.ok) {
213 | throw new Error(JSON.stringify(body));
214 | }
215 |
216 | setSideNav(generateSideNav(body));
217 | setItems(body);
218 | })
219 | .catch((err) => {
220 | let error: BackendError;
221 | try {
222 | error = JSON.parse(err.message);
223 | } catch (e) {
224 | error = {
225 | description: err.message,
226 | error: "An error occurred while fetching the configurations",
227 | action: "Please try again later",
228 | };
229 | }
230 | navigate(`/error`, {
231 | state: { error: error },
232 | });
233 | })
234 | .finally(() => setIsLoading(false));
235 | }, [appContextData.context.currentK8sContext]);
236 |
237 | useScrollToHash(hash, [fullyLoadedRefs]);
238 |
239 | useCurrentElementInView(panelsRef, setCurrentElementInView);
240 |
241 | useEffect(() => {
242 | if (currentElementInView) {
243 | const newSideBar: ISideNav[] = clonedeep(sideNav);
244 |
245 | newSideBar[0].items = newSideBar[0].items.map((item) => {
246 | if (item.name === currentElementInView) {
247 | item.isSelected = true;
248 | } else {
249 | item.isSelected = false;
250 | }
251 |
252 | return item;
253 | });
254 |
255 | setSideNav(newSideBar);
256 | }
257 | }, [currentElementInView]);
258 |
259 | return (
260 | <>
261 | {isLoading ? (
262 |
269 |
270 |
271 | Loading...
272 |
273 |
274 |
275 |
276 |
277 |
278 |
279 | ) : (
280 |
285 |
292 |
293 |
294 |
295 |
299 | <>
300 | {items && items.length > 0 ? (
301 | items.map((item, index) => {
302 | return (
303 | onRefChange(node, index)}
307 | >
308 | {SingleConfig(item)}
309 |
310 | );
311 | })
312 | ) : (
313 | No Configuration found
}
316 | />
317 | )}
318 | >
319 |
320 |
321 |
322 | )}
323 | >
324 | );
325 | }
326 |
327 | export default ConfigurationsComponent;
328 |
--------------------------------------------------------------------------------
/.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' -ignore tests/helper.bash .
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.29.0
104 | CLUSTER_VERSION: v1.33.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://dl.k8s.io/$${CLUSTER_VERSION}/bin/linux/arm/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:2.24.17_1.1.0_3.12.0_1.32.2_5.6.0_1.9.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 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Gatekeeper Policy Manager (GPM)
5 |
6 |
7 |
8 | [](https://ci.sighup.io/sighupio/gatekeeper-policy-manager)
9 | 
10 | 
11 | 
12 |
13 | **Gatekeeper Policy Manager** is a simple *read-only* web UI for viewing OPA Gatekeeper policies' status in a Kubernetes Cluster.
14 |
15 | 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.
16 |
17 | 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.
18 |
19 | [You can see some screenshots below](#screenshots).
20 |
21 | ## Requirements
22 |
23 | You'll need OPA Gatekeeper running in your cluster and at least some constraint templates and constraints defined to take advantage of this tool.
24 |
25 | > [!NOTE]
26 | > You can easily deploy Gatekeeper to your cluster using the (also open source) [SIGHUP Distribution Policy Module](https://github.com/sighupio/module-policy).
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.1.0 --values my-values.yaml gatekeeper-policy-manager gpm/gatekeeper-policy-manager
61 | ```
62 |
63 | > [!IMPORTANT]
64 | > Don't forget to replace `my-values.yaml` with the path to your values file.
65 |
66 | ## Running locally
67 |
68 | 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:
69 |
70 | ```bash
71 | docker run -v ~/.kube/config:/home/gpm/.kube/config -p 8080:8080 quay.io/sighup/gatekeeper-policy-manager:v1.1.0
72 | ```
73 |
74 | Then access it with your browser on: [http://127.0.0.1:8080](http://127.0.0.1:8080)
75 |
76 | > You can also run the flask app directly, see the [development section](#development) for further information.
77 |
78 | ## Configuration
79 |
80 | GPM is a stateless application, but it can be configured using environment variables. The possible configurations are:
81 |
82 | | Environment Variable Name | Description | Default |
83 | | --------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------- |
84 | | `GPM_SECRET_KEY` | The secret key used to generate tokens. **Change this value in production**. | `g8k1p3rp0l1c7m4n4g3r` |
85 | | `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. |
86 | | `GPM_LOG_LEVEL` | Log level (see [python logging docs](https://docs.python.org/2/library/logging.html#levels) for available levels) | `INFO` |
87 | | `GPM_AUTH_ENABLED` | Enable Authentication current options: "Anonymous", "OIDC" | Anonymous |
88 | | `GPM_PREFERRED_URL_SCHEME` | URL scheme to be used while generating links. | `http` |
89 | | `GPM_OIDC_REDIRECT_DOMAIN` | The domain where GPM is being running. This is where the client will be redirected after authenticating | |
90 | | `GPM_OIDC_CLIENT_ID` | The Client ID used to authenticate against the OIDC Provider | |
91 | | `GPM_OIDC_CLIENT_SECRET` | The Client Secret used to authenticate against the OIDC Provider (optional) | |
92 | | `GPM_OIDC_ISSUER` | OIDC Issuer hostname (required if OIDC Auth is enabled) | |
93 | | `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) | |
94 | | `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) | |
95 | | `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) | |
96 | | `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) | |
97 | | `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) | |
98 | | `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) | |
99 |
100 | >[!WARNING]
101 | > Please notice that OIDC Authentication is in beta state. It has been tested to work with Keycloak as a provider.
102 | >
103 | > These environment variables are already provided and ready to be set in the [`manifests/enable-oidc.yaml`](manifests/enable-oidc.yaml) file.
104 |
105 | ### Multi-cluster support
106 |
107 | GPM has multi-cluster support when using a `kubeconfig` with more than one context. GPM will let you chose the context right from the UI.
108 |
109 | If you want to run GPM in-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.
110 |
111 | > [!NOTE]
112 | > 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.
113 | >
114 | > Also note that the cluster where GPM is running should be able to reach the other clusters.
115 |
116 | 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. You can switch between them easily from the UI.
117 |
118 | #### AWS IAM Authentication
119 |
120 | 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.
121 |
122 | You can customize the container image with a `Dockerfile` like the following:
123 |
124 | ```Dockerfile
125 | FROM curlimages/curl:7.81.0 as downloader
126 | 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
127 | RUN chmod +x /tmp/aws-iam-authenticator
128 | FROM quay.io/sighup/gatekeeper-policy-manager:v1.1.0
129 | COPY --from=downloader --chown=root:root /tmp/aws-iam-authenticator /usr/local/bin/
130 | ```
131 |
132 | You may need to add also the `aws` CLI, you can use the same approach as before.
133 |
134 | Make sure that your `kubeconfig` has the `apiVersion` set as `client.authentication.k8s.io/v1beta1`
135 |
136 | You can read more [in this issue](https://github.com/sighupio/gatekeeper-policy-manager/issues/330).
137 |
138 | ## Screenshots
139 |
140 | 
141 |
142 | 
143 |
144 | 
145 |
146 | 
147 |
148 | 
149 |
150 | 
151 |
152 | 
153 |
154 | 
155 |
156 | ## Development
157 |
158 | GPM is written in Python using the Flask framework for the backend and React with Elastic UI and the Fury theme for the frontend.
159 |
160 | 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.
161 |
162 | The following commands should get you up and running:
163 |
164 | ```bash
165 | # Build frontend and copy over to static folder
166 | $ pushd app/web-client
167 | $ yarn install && yarn build
168 | $ cp -r build/* ../static-content/
169 | $ popd
170 | # Create a virtualenv
171 | $ python3 -m venv env
172 | # Activate it
173 | $ source ./env/bin/activate
174 | # Install all the dependencies
175 | $ pip install -r app/requirements.txt
176 | # Run the development server
177 | $ FLASK_APP=app/app.py FLASK_ENV=development flask run
178 | ```
179 |
180 | If you want to test changes to the frontend live, make sure the backend is running (see above) and then run the frontend using `yarn`:
181 |
182 | ```bash
183 | cd app/web-client
184 | yarn start
185 | ```
186 |
187 | A browser window should open, if the React application can't reach the backend, check that the `.env` file points to the right backend endpoint (`REACT_APP_LOCAL_GPM_SERVER_URL`).
188 |
189 | > [!TIP]
190 | > Access to a Kubernetes cluster with OPA Gatekeeper deployed is recommended to debug the application.
191 | >
192 | > You'll need an OIDC provider to test the OIDC authentication. You can use the SIGHUP Distribution [Keycloak add-on module](https://github.com/sighupio/add-on-keycloak).
193 |
194 | ## Roadmap
195 |
196 | The following is a wishlist of features that we would like to add to GPM (in no particular order):
197 |
198 | - [x] List the constraints that are currently using a `ConstraintTemplate`
199 | - [ ] Polished OIDC authentication
200 | - [ ] LDAP authentication
201 | - [x] Better syntax highlighting for the rego code snippets
202 | - [x] Root-less docker image
203 | - [x] Multi-cluster view
204 | - [ ] Minimal write capabilities?
205 | - [ ] Rewrite app in Golang? (WIP in the `feature/go-backend` branch)
206 |
207 | Please, let us know if you are using GPM and what features would you like to have by creating an issue here on GitHub 💪🏻
208 |
--------------------------------------------------------------------------------