We hope to steer development of Connaisseur from demand of the community and are excited about direct contributions to improve the tool!
The following guide is meant to help you get started with contributing to Connaisseur. In case of questions or feedback, feel free to reach out to us.
We are committed to positive interactions between all contributors of the project. To ensure this, please follow the Code of Conduct in all communications.
We are happy you made it here! In case you want to share your feedback, need support, want to discuss issues from using Connaisseur in your own projects, have ideas for new features or just want to connect with us, please reach out via GitHub Discussions. If you want to raise any bugs you found or make a feature request, feel free to create an issue with an informative title and description.
While issues are a great way to discuss problems, bugs and new features, a direct proposal via a pull request can sometimes say more than a thousand words. So be bold and contribute to the code as described in the next section!
In case you require a more private communication, you can reach us via [email protected].
The following steps will help you make code contributions to Connaisseur and ensure good code quality and workflow. This includes the following steps:
- Set up your environment: Set up up your local environment to best interact with the code. Further information is given below.
- Make atomic changes: Changes should be atomic. As such, pull requests should contain only few commits, and each commit should only fix one issue or implement one feature, with a concise commit message.
- Test your changes: Test any changes locally for code quality and functionality and add new tests for any additional code. How to test is described below.
- Create semantic, conventional and signed commits: Any commits should follow a simple semantic convention to help structure the work on Connaisseur. The convention is described below. For security reasons and since integrity is at the core of this project, code merged into master must be signed. How we achieve this is described below.
- Create pull requests:
We consider code review central to quality and security of code.
Therefore, a pull request (PR) to the
develop
branch should be created for each contribution. It will be reviewed, and potential improvements may be discussed within the PR. After approval, changes will be merged and moved to themaster
branch with the next release.
To start contributing, you will need to set up your local environment. First step is to get the source code by cloning this repository:
git clone [email protected]:sse-secure-systems/connaisseur.git
In order to review the effects of your changes, you should create your own Kubernetes cluster and install Connaisseur. This is described in the getting started. A simple starting point may be a minikube cluster with e.g. a Docker Hub repository for maintaining your test images and trust data.
In case you make changes to the Connaisseur container image itself or code for that matter, you need to re-build the image and install it locally for testing. This requires a few steps:
- In
helm/values.yaml
, setimagePullPolicy
toIfNotPresent
. - Configure your local environment to use the Kubernetes Docker daemon. In minikube, this can be done via
eval (minikube docker-env)
. - Build the Connaisseur container image via
make docker
. - Install Connaisseur as usual via
make install
.
Tests and linting are important to ensure code quality, functionality and security. We therefore aim to keep the code coverage high. We are running several automated tests in the CI pipeline. Application code is tested via pytest and linted via pylint. When making changes to the application code, please directly provide tests for your changes.
We recommend using black for autoformatting to simplify linting and reduce review effort. It can be installed via:
pip3 install black
To autoformat the code:
black <path-to-repository>/connaisseur
Changes can also be tested locally. We recommend the following approach for running pytest in a container:
docker run -it --rm -v <path-to-repository>:/data --entrypoint=ash python:alpine
cd data
YARL_NO_EXTENSIONS=1 MULTIDICT_NO_EXTENSIONS=1 pip3 install -r requirements_dev.txt
pytest --cov=connaisseur --cov-report=xml tests/
This helps identify bugs in changes before pushing.
ℹ️ INFO We believe that testing should not only ensure functionality, but also aim to test for expected security issues like injections and appreciate if security tests are added with new functionalities.
Besides the unit testing and before any PR can be merged, an integration test is carried out whereby:
- Connaisseur is successfully installed in a test cluster
- a non-signed image is deployed to the cluster and denied
- an image signed with an unrelated key is denied
- a signed image is deployed to the cluster and passed
- Connaisseur is successfully uninstalled
You can also run this integration test on a local cluster. There is a more detailed guided on how to do that.
If you are changing documentation, you can simply inspect your changes locally via:
docker run --rm -it -p 8000:8000 -v ${PWD}:/docs squidfunk/mkdocs-material
All changes to the develop
and master
branch must be signed which is enforced via branch protection.
This can be achieved by only fast-forwarding signed commits or signing of merge commits by a contributor.
Consequently, we appreciate but do not require that commits in PRs are signed.
A general introduction into signing commits can for example be found in the With Blue Ink blog. For details on setting everything up for GitHub, please follow the steps in the Documentation.
Once you have generated your local GPG key, added it to your GitHub account and informed Git about it, you are set up to create signed commits. We recommend to configure Git to sign commits by default via:
git config commit.gpgsign true
This avoids forgetting to use the -S
flag when committing changes.
In case it happens anyways, you can always rebase to sign earlier commits:
git rebase -i master
You can then mark all commits that need to be signed as edit
and sign them without any other changes via:
git commit -S --amend --no-edit
Finally, you force push to overwrite the unsigned commits via git push -f
.
For Connaisseur, we want to use semantic and conventional commits to ensure good readability of code changes. A good introduction to the topic can be found in this blog post.
Commit messages should consist of header, body and footer. Such a commit message takes the following form:
git commit -m "<header>" -m "<body>" -m "<footer>"
The three parts should consist of the following:
- header: Comprises of a commit type (common types are described below) and a concise description of the actual change, e.g.
fix: extend registry validation regex to custom ports
. - body (optional): Contains information on the motivation behind the change and considerations for the resolution,
The current regex used for validation of the image name does not allow using non-default ports for the image repository name. The regex is extended to optionally provide a port number.
. - footer (optional): Used to reference PRs, issues or contributors and mark consequences such as breaking changes, e.g.
Fix #<issue-number>
We want to use the following common types in the header:
- build: changes to development and building
- ci: CI related changes
- docs: changes in the documentation
- feat: adding of new features
- fix: fixing an issue or bug
- refactor: adjustment of code base to improve code quality or performance but not adding a feature or fixing a bug
- test: testing related changes
- update: updating a dependency
A complete commit message could therefore look as follows:
git commit -m "fix: extend registry validation regex to custom ports" -m "The current regex used for validation of the image name does not allow using non-default ports for the image repository name. The regex is extended to optionally provide a port number." -m "Fix #3"
Please be bold and contribute!