This repository includes checks for executable code that may be run by the Puppet server. These files can be used in CI jobs to help ensure that executable code is not committed to your control repository. This repository itself is a simple control repo to facilitate testing and to show an example of how it might be used.
⚠️ Please note that this only checks for specific cases of executable code and does not prevent a malicious user from committing obfuscated malicious Puppet code or malicious custom facts.
scripts/codecheck.rb
will check a file for Ruby code that's not expected in a Puppetfile
.scripts/no_config_version.sh
will ensure that the environment does not specify a config_version
setting.Choose the option below that matches your own usage requirements.
If your workflow consists of developers working in their own fork of your control repository and contributing changes as pull/merge requests then you should configure a CI job to prevent these from being merged when they include executable code:
.gitlab-ci.yml
as a starter example..github/workflows/ci.yml
as a starter example.If your workflow grants developers the ability to create feature branches and contribute code directly,
then you will need to configure server pre-receive
hooks to reject commits with executable code. Create
hooks for each of the files in the scripts
directory.
If you don't have the ability to configure CI jobs or server-side hooks, then you can stand up a webhook server using your platform of choice. The webhook server should clone the repository and then run each of the hook scripts in this repository or incorporate their functionality. Creating that webhook server is beyond the scope of this guide, but you can find some guidance for your Git platform.
This is provided without guarantee of suitability. It is a demonstration of the
official GitLab instructions
for configuring a pre-receive
hook.
Example:
Storage name: default
Relative path: @hashed/8b/94/8b940be7fb78aaa6b6567dd7a3987996947460df1c668e698eb92ca77e425349.git
custom_hooks/pre-receive.d/codecheck.rb
custom_hooks/pre-receive.d/no_config_version.sh
tar -cf custom_hooks.tar custom_hooks
cat custom_hooks.tar | sudo /opt/gitlab/embedded/bin/gitaly hooks set --storage <storage> --repository <relative path> --config <config path>
Working Example:
cat /var/opt/gitlab/test/custom_hooks.tar | /opt/gitlab/embedded/bin/gitaly hooks set \
--storage default \
--repository @hashed/8b/94/8b940be7fb78aaa6b6567dd7a3987996947460df1c668e698eb92ca77e425349.git \
--config /var/opt/gitlab/gitaly/config.toml
Check repo directory for existance of script
ls -la /var/opt/gitlab/git-data/repositories/@hashed/8b/94/8b940be7fb78aaa6b6567dd7a3987996947460df1c668e698eb92ca77e425349.git/custom_hooks
Run a test push to verify execution: Example:
PS C:\Users\paul\Documents\Code\test\test-pre> git push -v origin main
Pushing to https://gitlab.example.com/puppet/test-pre.git
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Delta compression using up to 24 threads
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 299 bytes | 299.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0)
POST git-receive-pack (482 bytes)
remote: /var/opt/gitlab/git-data/repositories/@hashed/8b/94/8b940be7fb78aaa6b6567dd7a3987996947460df1c668e698eb92ca77e425349.git/custom_hooks/pre-receive.d/codecheck.rb:38:in `test': [
remote: {
remote: "name": "puts",
remote: "count": 1
remote: }
remote: ]
To https://gitlab.example.com/puppet/test-pre.git
! [remote rejected] main -> main (pre-receive hook declined)
error: failed to push some refs to 'https://gitlab.example.com/puppet/test-pre.git'
PS C:\Users\paul\Documents\Code\test\test-pre>