├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md └── stale.yml ├── .gitignore ├── CODEOWNERS ├── LICENSE ├── README.md ├── plugin.yaml └── scripts ├── install.sh └── run.sh /.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 | **Describe the bug** 10 | A clear and concise description of what the bug is. 11 | 12 | **To Reproduce** 13 | Steps to reproduce the behavior: 14 | 1. Run command '...' 15 | 2. Click on '....' 16 | 3. See error 17 | 18 | **Expected behavior** 19 | A clear and concise description of what you expected to happen. 20 | 21 | **Screenshots** 22 | If applicable, add screenshots to help explain your problem. 23 | 24 | **Desktop (please complete the following information):** 25 | - OS: [e.g. Linux] 26 | 27 | **Datree plugin version (run `helm datree verion`):** 28 | - Version: [e.g. 0.1.443] 29 | 30 | **Additional context** 31 | Add any other context about the problem here. 32 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: enhancement 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /.github/stale.yml: -------------------------------------------------------------------------------- 1 | # Number of days of inactivity before an issue becomes stale 2 | daysUntilStale: 7 3 | # Number of days of inactivity before a stale issue is closed 4 | daysUntilClose: 7 5 | # Issues with these labels will never be considered stale 6 | exemptLabels: 7 | - good first issue 8 | - WIP 9 | - up for grabs 10 | # Label to use when marking an issue as stale 11 | staleLabel: stale issue 12 | # Comment to post when marking an issue as stale. Set to `false` to disable 13 | markComment: > 14 | This issue has been automatically marked as stale because it has not had 15 | recent activity. It will be closed if no further activity occurs. Thank you 16 | for your contributions. 17 | # Comment to post when closing a stale issue. Set to `false` to disable 18 | closeComment: false 19 | # Limit to only `issues` or `pulls` 20 | only: issues 21 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | bin/ 2 | -------------------------------------------------------------------------------- /CODEOWNERS: -------------------------------------------------------------------------------- 1 | # by deafult 2 | @datreeio/developers 3 | 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 datree.io 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Datree Helm Plugin 2 | 3 | A [Helm](https://www.datree.io/helm-chart) plugin to validate charts against the Datree policy 4 | 5 | ## Installation 6 | ``` 7 | helm plugin install https://github.com/datreeio/helm-datree 8 | ``` 9 | ⚠️ Helm plugins are not supported on Windows OS ⚠️ 10 | _Windows users can work around this by using [Helm under WSL](https://github.com/helm/helm-2to3#for-windows-using-wsl)_ 11 |
12 | 13 | ### Update Datree's plugin version 14 | ``` 15 | helm plugin update datree 16 | ``` 17 | ### Uninstall 18 | ``` 19 | helm plugin uninstall datree 20 | ``` 21 | 22 | ## Usage 23 | 24 | ### Trigger datree policy check via the helm CLI 25 | ``` 26 | helm datree test [CHART_DIRECTORY] 27 | ``` 28 | 29 | ### Passing arguments 30 | If you need to pass helm arguments to your template, you will need to add `--` before them: 31 | ``` 32 | helm datree test [CHART_DIRECTORY] -- --values values.yaml --set name=prod 33 | ``` 34 | ### Test files 35 | By default, test files generated by Helm will be skipped. If you wish to include test files in your policy check, add the `--include-tests` flag: 36 | ``` 37 | helm datree test --include-tests [CHART_DIRECTORY] 38 | ``` 39 | 40 | ### Check plugin version 41 | ``` 42 | helm datree version 43 | ``` 44 | 45 | ### See help text 46 | ``` 47 | helm datree help 48 | ``` 49 | 50 | ### Using other helm command 51 | Helm might be installed through other tooling like microk8s. The `DATREE_HELM_COMMAND` allows specifying a command to run helm (default: `helm`): 52 | ``` 53 | DATREE_HELM_COMMAND="microk8s helm3" helm datree test [CHART_DIRECTORY] 54 | ``` 55 | 56 | ## Testing multiple charts 57 | 58 | If you have multiple charts inside a single directory, you can test all of them sequentially using the following script: 59 | 60 | ```bash 61 | #!/bin/bash 62 | 63 | path="${1:-.}" 64 | final_exit_code=0 65 | 66 | while read -r helmchart; do 67 | dir="$(dirname "$helmchart")" 68 | echo "*** Proceeding to test Helm chart: $helmchart ***" 69 | set +e 70 | helm datree test "$dir" 71 | exitcode=$? 72 | set -e 73 | if [ "$exitcode" -gt "$final_exit_code" ]; then 74 | final_exit_code="$exitcode" 75 | fi 76 | echo "" 77 | done < <(find "$path" -type f -name 'Chart.y*ml') 78 | 79 | if [ "$final_exit_code" = 0 ]; then 80 | echo "Success" 81 | else 82 | echo "Violations found, returning exit code $final_exit_code" 83 | fi 84 | exit "$final_exit_code" 85 | ``` 86 | 87 | The script will run a policy check against all charts before exiting, and return 0 only if no violations were found in any of them. 88 | This is useful for CI, to avoid the need to call `datree test` multiple times. 89 | 90 | ## Examples 91 | 92 | ### Basic usage 93 | ``` 94 | helm plugin install https://github.com/datreeio/helm-datree 95 | git clone git@github.com:datreeio/examples.git 96 | helm datree test examples/helm-chart/nginx 97 | ``` 98 | 99 | ![image](https://user-images.githubusercontent.com/19731161/131975552-b66a84f8-5aa9-4d70-a08e-aae97aa76116.png) 100 | 101 | ### GitHub Workflow 102 | ```yaml 103 | on: 104 | push: 105 | branches: [ main ] 106 | pull_request: 107 | branches: [ main ] 108 | 109 | env: 110 | DATREE_TOKEN: ${{ secrets.DATREE_TOKEN }} 111 | 112 | jobs: 113 | k8sPolicyCheck: 114 | runs-on: ubuntu-latest 115 | 116 | steps: 117 | - name: Checkout 118 | uses: actions/checkout@v2 119 | 120 | - name: Run Datree Policy Check 121 | uses: datreeio/action-datree@main 122 | with: 123 | path: 'myChartDirectory' 124 | cliArguments: '--only-k8s-files' 125 | isHelmChart: true 126 | helmArguments: '--values values.yaml' 127 | ``` 128 | 129 | ## Troubleshooting 130 | 131 | ### Error: plugin "datree" exited with error 132 | This is actually expected behavior because it's raised by Helm itself every time a plugin returns a [non-zero exit code](https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html#:~:text=A%20non%2Dzero%20exit%20status,N%20as%20the%20exit%20status.). 133 | Therefore, if you will run datree plugin on a Chart that will pass the policy check, it will return 0 as exit code, and you will not see this error. 134 | 135 | ### K8s schema validation error 136 | This error occurs when trying to scan Chart.yaml or values.yaml files instead of the chart directory. 137 | **Solution:** Pass the helm chart directory path to Datree's CLI, instead of to the file itself: 138 | * Correct - `helm datree test examples/helm-chart/nginx` 139 | * Wrong - `helm datree test examples/helm-chart/nginx/values.yaml` 140 | 141 | ### The policy check returns false-positive results 142 | The best way to determine if a false-positive result is a bug or a true misconfiguration, is by rendering the Kubernetes manifest with helm and then checking it manually: 143 | ``` 144 | helm template [CHART_DIRECTORY] 145 | ``` 146 | If after eyeballing the rendered manifest you still suspect it's a bug, please open an issue. 147 | -------------------------------------------------------------------------------- /plugin.yaml: -------------------------------------------------------------------------------- 1 | name: "datree" 2 | usage: "Validate Helm charts" 3 | description: |- 4 | "Run Helm charts against the datree policy" 5 | command: "$HELM_PLUGIN_DIR/scripts/run.sh" 6 | 7 | hooks: 8 | install: "cd $HELM_PLUGIN_DIR; ./scripts/install.sh" 9 | update: "cd $HELM_PLUGIN_DIR; ./scripts/install.sh" 10 | 11 | useTunnel: false 12 | ignoreFlags: false 13 | -------------------------------------------------------------------------------- /scripts/install.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash -e 2 | 3 | cd $HELM_PLUGIN_DIR 4 | echo "Installing helm-datree..." 5 | 6 | osName=$(uname -s) 7 | osArchitecture=$(uname -m) 8 | 9 | if [[ $osArchitecture == *'aarch'* || $osArchitecture == *'arm'* ]]; then 10 | osArchitecture='arm64' 11 | fi 12 | 13 | DOWNLOAD_URL=$(curl --silent "https://api.github.com/repos/datreeio/datree/releases/latest" | grep -o "browser_download_url.*\_${osName}_${osArchitecture}.zip") 14 | 15 | DOWNLOAD_URL=${DOWNLOAD_URL//\"} 16 | DOWNLOAD_URL=${DOWNLOAD_URL/browser_download_url: /} 17 | 18 | echo $DOWNLOAD_URL 19 | OUTPUT_BASENAME=datree-latest 20 | OUTPUT_BASENAME_WITH_POSTFIX=$OUTPUT_BASENAME.zip 21 | 22 | if [ "$DOWNLOAD_URL" = "" ] 23 | then 24 | echo "Unsupported OS / architecture: ${osName}" 25 | exit 1 26 | fi 27 | 28 | if [ -n $(command -v curl) ] 29 | then 30 | curl -L $DOWNLOAD_URL -o $OUTPUT_BASENAME_WITH_POSTFIX 31 | else 32 | echo "Need curl" 33 | exit -1 34 | fi 35 | 36 | rm -rf bin && mkdir bin && unzip $OUTPUT_BASENAME_WITH_POSTFIX -d bin > /dev/null && rm -f $OUTPUT_BASENAME_WITH_POSTFIX 37 | 38 | echo "helm-datree is installed." 39 | echo 40 | echo "See https://hub.datree.io for help getting started." 41 | -------------------------------------------------------------------------------- /scripts/run.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | 3 | set -eo pipefail 4 | 5 | # by default - test files generated by "helm template" will be skipped 6 | helm_options=(--skip-tests) 7 | 8 | datree_options=() 9 | helm_chart_location="" 10 | helm_chart_name="" 11 | datree_command="" 12 | eoo=0 13 | 14 | helm_command=${DATREE_HELM_COMMAND:-helm} 15 | 16 | while [[ $1 ]]; do 17 | if ! ((eoo)); then 18 | if [[ $1 == "--include-tests" ]]; then 19 | helm_options=() 20 | elif [[ $1 == "--" ]]; then 21 | eoo=1 22 | elif [[ $helm_chart_location == "" && $($helm_command show chart $1 2> /dev/null | grep apiVersion) == apiVersion* ]]; then 23 | helm_chart_location=$1 24 | helm_chart_name=$($helm_command show chart $1 | grep -o '^name: .*' | cut -c 7-) 25 | else 26 | datree_options+=("$1") 27 | fi 28 | 29 | shift 30 | else 31 | helm_options+=("$1") 32 | shift 33 | fi 34 | done 35 | 36 | if [[ ${helm_chart_location} != "" ]]; then 37 | currUinxTimestamp=$(date +%s) 38 | tempManifestPath="/tmp/helmtmp-${helm_chart_name}_$currUinxTimestamp.yaml" 39 | $helm_command template "${helm_options[@]}" "$helm_chart_location" > $tempManifestPath 40 | if [ -s $tempManifestPath ]; then 41 | $HELM_PLUGIN_DIR/bin/datree "${datree_options[@]}" $tempManifestPath 42 | else 43 | helm template "${helm_options[@]}" "$helm_chart_location" | $HELM_PLUGIN_DIR/bin/datree "${datree_options[@]}" - 44 | fi 45 | else 46 | $HELM_PLUGIN_DIR/bin/datree "${datree_options[@]}" 47 | fi 48 | --------------------------------------------------------------------------------