├── .github ├── renovate.json └── workflows │ └── test.yaml ├── .gitignore ├── .gitleaks.toml ├── .helmignore ├── .pre-commit-config.yaml ├── .pre-commit └── jsonschema-dereference.py ├── LICENSE ├── OWNERS ├── README.md ├── charts ├── _templates.gotmpl └── trusted-artifact-signer │ ├── .helmignore │ ├── Chart.yaml │ ├── README.md │ ├── README.md.gotmpl │ ├── chart_schema.yaml │ ├── charts │ └── scaffold-0.6.41.tgz │ ├── ci │ └── ci-values.yaml │ ├── templates │ ├── _helpers.tpl │ ├── backfillRedis-cronjob.yaml │ ├── clientserver-deployment.yaml │ ├── clientserver-route.yaml │ ├── clientserver-sa.yaml │ ├── clientserver-service.yaml │ ├── cluster-monitoring-resources.yaml │ ├── consoleclidownload-cosign.yaml │ ├── consoleclidownload-ec.yaml │ ├── consoleclidownload-gitsign.yaml │ ├── consoleclidownload-rekor.yaml │ ├── cosign-deployment.yaml │ ├── cosign-sa.yaml │ ├── fulcio-secret.yaml │ ├── namespace.yaml │ ├── rekor-signer-secret.yaml │ ├── rekor-ui-deployment.yaml │ ├── rekor-ui-route.yaml │ ├── rekor-ui-sa.yaml │ ├── rekor-ui-service.yaml │ ├── rolebinding.yaml │ ├── segment-backup-cronjob.yaml │ ├── segment-backup-job-clusterrole.yaml │ ├── segment-backup-job-clusterrolebinding.yaml │ ├── segment-backup-job-sa.yaml │ ├── segment-backup-job.yaml │ └── tests │ │ ├── test-connection.yaml │ │ └── test-sign-verify.yaml │ ├── values.schema.json │ ├── values.schema.tmpl.json │ └── values.yaml ├── cr.yaml ├── ct-install.yaml ├── ct.yaml ├── docs ├── configure-oidc.md ├── configure-self-signed-cluster.md ├── enable-grafana-monitoring.md ├── keycloak-example.md ├── quick-start-with-keycloak.md ├── requirements-keys-certs.md └── sign-verify.md ├── examples ├── values-kind-byodb.yaml ├── values-kind-sigstore.yaml ├── values-sigstore-openshift-byo-fulcio-root.yaml ├── values-sigstore-openshift-byo-rekor-key.yaml ├── values-sigstore-openshift.yaml └── values.yaml ├── fulcio-create-root-ca-openssl.sh ├── grafana ├── dashboards │ ├── dashboard.yaml │ └── datasource.yaml ├── instance │ ├── instance.yaml │ └── kustomization.yaml ├── operator │ ├── kustomization.yaml │ └── operator.yaml └── resources │ ├── kustomization.yaml │ ├── rolebinding.yaml │ └── token.yaml ├── hack └── fulcio-patch-self-signed-oidc.yaml ├── images ├── add_mapper.png ├── add_urls.png ├── create_mapper_2.png ├── github_login_2.png ├── mapper2.png └── redirect_uri.png ├── keycloak ├── operator │ ├── base │ │ ├── kustomization.yaml │ │ ├── namespace.yaml │ │ └── subscription.yaml │ └── overlay │ │ └── kind │ │ ├── kustomization.yaml │ │ └── patch.yaml └── resources │ ├── base │ ├── keycloak.yaml │ ├── kustomization.yaml │ ├── realm.yaml │ ├── tas-client.yaml │ └── user.yaml │ ├── example-user.yaml │ └── overlay │ └── kind │ ├── keycloak-svc.yaml │ ├── keycloak_patch.yaml │ ├── kustomization.yaml │ └── realm_patch.yaml ├── kind ├── config.yaml ├── kind-up-test.sh └── testing-only-cert-key │ ├── file_ca_key.pem │ ├── file_ca_pub.pem │ ├── fulcio-root.pem │ └── rekor_key.pem ├── rekor-create-signer-key.sh ├── release-plans └── gamma │ └── ReleasePlan.yaml ├── tas-easy-install.sh ├── tas-env-variables.sh ├── tas-grafana-install.sh └── tas-installer ├── cmd ├── envgen.go ├── install.go ├── root.go └── uninstall.go ├── go.mod ├── go.sum ├── internal ├── install │ └── install.go └── uninstall │ └── uninstall.go ├── main.go ├── pkg ├── certs │ └── certs.go ├── helm │ ├── helm.go │ └── values-openshift.tmpl ├── kubernetes │ ├── client.go │ ├── job.go │ ├── namespace.go │ ├── pod.go │ └── secrets.go ├── oidc │ └── type.go └── secrets │ └── secret.go └── ui ├── certPrompt.go └── pullsecretPrompt.go /.github/renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json", 3 | "extends": [ 4 | "config:base", 5 | "helpers:pinGitHubActionDigests" 6 | ] 7 | } 8 | -------------------------------------------------------------------------------- /.github/workflows/test.yaml: -------------------------------------------------------------------------------- 1 | name: Lint Charts 2 | 3 | on: 4 | push: 5 | branches: [ main ] 6 | pull_request: 7 | branches: [ main ] 8 | paths: 9 | - "charts/**" 10 | - "tas-installer/**" 11 | - ".github/**" 12 | 13 | jobs: 14 | check-metadata: 15 | runs-on: ubuntu-latest 16 | env: 17 | GO111MODULE: on 18 | steps: 19 | - name: Checkout 20 | uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 21 | 22 | - uses: actions/setup-python@61a6322f88396a6271a6ee3565807d608ecaddd1 # v4 23 | with: 24 | python-version: 3.7 25 | 26 | - uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4 27 | with: 28 | go-version: ^1 29 | 30 | - name: Setup helm-docs 31 | run: go install github.com/norwoodj/helm-docs/cmd/helm-docs@latest 32 | 33 | - name: Run pre-commit 34 | uses: pre-commit/action@646c83fcd040023954eafda54b4db0192ce70507 # renovate: tag=v3.0.0 35 | with: 36 | extra_args: --show-diff-on-failure 37 | test: 38 | runs-on: ubuntu-latest 39 | env: 40 | REGISTRY_USER: ${{ secrets.REGISTRY_USER }} 41 | IMAGE_REGISTRY: registry.redhat.io 42 | REGISTRY_PASSWORD: ${{ secrets.REGISTRY_PASSWORD }} 43 | steps: 44 | - name: Checkout 45 | uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 46 | with: 47 | fetch-depth: 0 48 | 49 | - name: Set up Helm 50 | uses: azure/setup-helm@5119fcb9089d432beecbf79bb2c7915207344b78 # renovate: tag=v3.5 51 | with: 52 | version: v3.12.3 53 | 54 | - uses: actions/setup-python@61a6322f88396a6271a6ee3565807d608ecaddd1 # v4 55 | with: 56 | python-version: 3.7 57 | 58 | - name: Set up chart-testing 59 | uses: helm/chart-testing-action@e6669bcd63d7cb57cb4380c33043eebe5d111992 # v2.6.1 60 | 61 | - name: Add Sigstore Repository 62 | run: | 63 | helm repo add sigstore "https://sigstore.github.io/helm-charts" 64 | helm repo update 65 | 66 | - name: Run chart-testing (lint) 67 | run: ct lint --config ct.yaml 68 | 69 | - name: Log in to registry.redhat.io 70 | uses: redhat-actions/podman-login@9184318aae1ee5034fbfbacc0388acf12669171f # v1 71 | with: 72 | username: ${{ env.REGISTRY_USER }} 73 | password: ${{ env.REGISTRY_PASSWORD }} 74 | registry: ${{ env.IMAGE_REGISTRY }} 75 | auth_file_path: /tmp/config.json 76 | 77 | - name: Create KinD Cluster 78 | uses: helm/kind-action@dda0770415bac9fc20092cacbc54aa298604d140 # v1.8.0 79 | with: 80 | config: ./kind/config.yaml 81 | 82 | - name: Install OpenShift CLI 83 | run: | 84 | curl -L https://mirror.openshift.com/pub/openshift-v4/clients/oc/latest/linux/oc.tar.gz | tar xvz 85 | sudo mv oc /usr/local/bin/ 86 | oc version 87 | 88 | - name: Configure KinD 89 | run: | 90 | oc create ns fulcio-system 91 | oc create ns rekor-system 92 | oc -n fulcio-system create secret generic fulcio-secret-rh --from-file=private=./kind/testing-only-cert-key/file_ca_key.pem --from-file=public=./kind/testing-only-cert-key/file_ca_pub.pem --from-file=cert=./kind/testing-only-cert-key/fulcio-root.pem --from-literal=password=secure --dry-run=client -o yaml | oc apply -f- 93 | oc -n rekor-system create secret generic rekor-private-key --from-file=private=./kind/testing-only-cert-key/rekor_key.pem --dry-run=client -o yaml | oc apply -f- 94 | shell: bash 95 | 96 | - name: Install Keycloak 97 | run: | 98 | #install OLM 99 | kubectl create -f https://github.com/operator-framework/operator-lifecycle-manager/releases/download/v0.25.0/crds.yaml 100 | # wait for a while to be sure CRDs are installed 101 | sleep 1 102 | kubectl create -f https://github.com/operator-framework/operator-lifecycle-manager/releases/download/v0.25.0/olm.yaml 103 | kubectl create --kustomize keycloak/operator/overlay/kind 104 | until [ ! -z "$(kubectl get pod -l name=keycloak-operator -n keycloak-system 2>/dev/null)" ] 105 | do 106 | echo "Waiting for keycloak operator. Pods in keycloak-system namespace:" 107 | kubectl get pods -n keycloak-system 108 | sleep 10 109 | done 110 | kubectl create --kustomize keycloak/resources/overlay/kind 111 | until [[ $( oc get keycloak keycloak -o jsonpath='{.status.ready}' -n keycloak-system 2>/dev/null) == "true" ]] 112 | do 113 | printf "Waiting for keycloak deployment. \n Keycloak ready: %s\n" $(oc get keycloak keycloak -o jsonpath='{.status.ready}' -n keycloak-system) 114 | sleep 10 115 | done 116 | shell: bash 117 | 118 | # tests are in charts/trusted-artifact-signer/templates/tests 119 | - name: Run chart-testing (install) 120 | run: | 121 | ct install --debug --helm-extra-args "--timeout=10m" --config ct-install.yaml 122 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | Chart.lock 2 | 3 | # Vim swap files 4 | *.swp 5 | 6 | keys-cert 7 | ./keys-cert/*.pem 8 | **/clustercert/** 9 | **ADMIN** 10 | 11 | .idea 12 | 13 | *tas-install* 14 | *pull-secret.json* 15 | -------------------------------------------------------------------------------- /.gitleaks.toml: -------------------------------------------------------------------------------- 1 | [allowlist] 2 | description = "Global Allowlist" 3 | 4 | # Ignore based on any subset of the file path 5 | paths = [ 6 | # Ignore all example certs 7 | '''\/testing-only-cert-key\/*\.pem$''', 8 | ] 9 | -------------------------------------------------------------------------------- /.helmignore: -------------------------------------------------------------------------------- 1 | # Patterns to ignore when building packages. 2 | # This supports shell glob matching, relative path matching, and 3 | # negation (prefixed with !). Only one pattern per line. 4 | .DS_Store 5 | # Common VCS dirs 6 | .git/ 7 | .gitignore 8 | .bzr/ 9 | .bzrignore 10 | .hg/ 11 | .hgignore 12 | .svn/ 13 | # Common backup files 14 | *.swp 15 | *.bak 16 | *.tmp 17 | *.orig 18 | *~ 19 | # Various IDEs 20 | .project 21 | .idea/ 22 | *.tmproj 23 | .vscode/ 24 | -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | repos: 2 | - repo: https://github.com/norwoodj/helm-docs 3 | rev: v1.2.0 4 | hooks: 5 | - id: helm-docs 6 | files: (README\.md(\.gotmpl)?|(Chart|requirements|values)\.ya?ml)$ 7 | args: 8 | # Make the tool search for charts only under the ``charts` directory 9 | - --chart-search-root=charts 10 | # The `./` makes it relative to the chart-search-root set above 11 | - --template-files=./_templates.gotmpl 12 | # A base filename makes it relative to each chart directory found 13 | - --template-files=README.md.gotmpl 14 | - repo: local 15 | hooks: 16 | - id: jsonschema-dereference 17 | name: jsonschema-dereference 18 | entry: python .pre-commit/jsonschema-dereference.py 19 | additional_dependencies: [jsonref, Jinja2, pyyaml] 20 | language: python 21 | types_or: [yaml, json] 22 | -------------------------------------------------------------------------------- /.pre-commit/jsonschema-dereference.py: -------------------------------------------------------------------------------- 1 | import json 2 | from typing import List, Dict, Any 3 | from pathlib import Path 4 | 5 | import jsonref 6 | import yaml 7 | try: 8 | from yaml import CLoader as Loader, CDumper as Dumper 9 | except ImportError: 10 | from yaml import Loader, Dumper 11 | from jinja2 import Template 12 | 13 | JSONSCHEMA_TEMPLATE_NAME = "values.schema.tmpl.json" 14 | JSONSCHEMA_NAME = "values.schema.json" 15 | CHART_LOCK = "Chart.lock" 16 | 17 | def parse_chart_lock(chart_dir: Path): 18 | """Open and load Chart.yaml file.""" 19 | with open(chart_dir / CHART_LOCK, "r") as f: 20 | return yaml.load(f, Loader=Loader) 21 | 22 | def template_schema(chart_dir: Path, lock: Dict[str, Any]): 23 | """Load values.schema.tmpl.json and template it via Jinja2.""" 24 | with open(chart_dir / JSONSCHEMA_TEMPLATE_NAME, "r") as f: 25 | schema_template = Template(f.read()) 26 | 27 | return json.loads(schema_template.render(lock)) 28 | 29 | def tidy_schema(schema: Any): 30 | """Hack to support OCP Form view. 31 | 32 | https://issues.redhat.com/browse/OCPBUGS-14874 33 | https://issues.redhat.com/browse/OCPBUGS-14875 34 | """ 35 | if isinstance(schema, dict): 36 | try: 37 | del schema["$schema"] 38 | except: 39 | pass 40 | try: 41 | del schema["format"] 42 | except: 43 | pass 44 | for v in schema.values(): 45 | tidy_schema(v) 46 | return schema 47 | 48 | def save(chart_dir: Path, schema: Any): 49 | """Take schema containing $refs and dereference them.""" 50 | with open(chart_dir / JSONSCHEMA_NAME, "w") as f: 51 | json.dump(schema, f, indent=4, sort_keys=True) 52 | 53 | if __name__ == '__main__': 54 | charts = [p.parent for p in Path(".").rglob(CHART_LOCK)] 55 | 56 | errors: List[BaseException] = [] 57 | for chart in charts: 58 | try: 59 | lock = parse_chart_lock(chart) 60 | schema_template = template_schema(chart, lock) 61 | schema = jsonref.replace_refs(schema_template) 62 | schema = tidy_schema(schema) 63 | 64 | save(chart, schema) 65 | except BaseException as e: 66 | print(f"Could not process schema for '{chart}': {e}") 67 | errors.append(e) 68 | if errors: 69 | exit(1) 70 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /OWNERS: -------------------------------------------------------------------------------- 1 | approvers: 2 | - cooktheryan 3 | - JasonPowr 4 | - lance 5 | - lkatalin 6 | - sabre1041 7 | - sallyom 8 | - tommyd450 9 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Sigstore Helm Chart for OpenShift 2 | 3 | **This chart offers an opinionated OpenShift-specific experience.** It is based on and directly depends on an upstream canonical [Sigstore Scaffold Helm chart](https://github.com/sigstore/helm-charts/tree/main/charts/scaffold). For less opinionated experience, consider using the upstream chart directly. 4 | 5 | This chart extends all the features in the upstream chart in addition to including OpenShift only features. It is not recommended to use this chart on other platforms. 6 | 7 | ## Usage 8 | 9 | ### Installing from the Chart Repository 10 | 11 | For a quickstart on how to install Sigstore components on OpenShift refer to the 12 | [quickstart quide](docs/quick-start-with-keycloak.md) 13 | 14 | ## Scaffolding Chart 15 | 16 | More information can be found by inspecting the [trusted-artifact-signer chart](charts/trusted-artifact-signer). 17 | 18 | ## Contributing 19 | 20 | Install the [pre-commit](https://pre-commit.com/) package and run `pre-commit run --all-files` before pushing changes, or `pre-commit install` to automatically run the pre-commit hooks with every `git commit`. If it fails, 21 | run the `git commit` command again. It's likely the pre-commit hook fixed the issue and you have to bring in the new changes. 22 | 23 | ### Pull Requests 24 | 25 | Testing this repository requires access to `registry.redhat.io` images. Because of this the tests depend on GitHub 26 | secrets. GitHub secrets are not accessible to forked repositories, so the normal workflow of submitting a PR from your 27 | fork against `github.com/securesign/sigstore-ocp` main branch is not possible when making changes to either the `charts` 28 | or `.github` directories. These directories require a run of the test suite that requires access to `registry.redhat.io`. 29 | PRs are welcome in this repository, however. Please reach out to one of the [OWNERS](./OWNERS) to submit a PR to 30 | `charts` or `.github`. 31 | 32 | ### Testing 33 | 34 | To set up a `kind` cluster and deploy the charts, run the following from the root of this repository 35 | 36 | ```bash 37 | ./kind/kind-up-test.sh 38 | ``` 39 | 40 | This script will setup new KinD cluster for you, deploy the sigstore and execute tests on the deployment. 41 | There are no ingress routes so the sigstore is accessible only from the container. (see https://github.com/securesign/sigstore-ocp/blob/main/sign-verify.md#signing-a-container-using-the-cosign-pod) 42 | 43 | To uninstall helm chart: 44 | 45 | ```bash 46 | helm uninstall trusted-artifact-signer -n sigstore 47 | ``` 48 | 49 | To cleanup the test kind cluster, run: 50 | 51 | ```bash 52 | kind delete cluster 53 | ``` 54 | 55 | -------------------------------------------------------------------------------- /charts/_templates.gotmpl: -------------------------------------------------------------------------------- 1 | {{ define "chart.valuesTable" }} 2 | | Key | Description | Type | Default | 3 | |-----|-------------|------|---------| 4 | {{- range .Values }} 5 | | {{ .Key }} | {{ if .Description }}{{ .Description }}{{ else }}{{ .AutoDescription }}{{ end }} | {{ .Type }} | {{ if .Default }}{{ .Default }}{{ else }}{{ .AutoDefault }}{{ end }} | 6 | {{- end }} 7 | {{ end }} 8 | -------------------------------------------------------------------------------- /charts/trusted-artifact-signer/.helmignore: -------------------------------------------------------------------------------- 1 | # Patterns to ignore when building packages. 2 | # This supports shell glob matching, relative path matching, and 3 | # negation (prefixed with !). Only one pattern per line. 4 | .DS_Store 5 | # Common VCS dirs 6 | .git/ 7 | .gitignore 8 | .bzr/ 9 | .bzrignore 10 | .hg/ 11 | .hgignore 12 | .svn/ 13 | # Common backup files 14 | *.swp 15 | *.bak 16 | *.tmp 17 | *.orig 18 | *~ 19 | # Various IDEs 20 | .project 21 | .idea/ 22 | *.tmproj 23 | .vscode/ 24 | -------------------------------------------------------------------------------- /charts/trusted-artifact-signer/Chart.yaml: -------------------------------------------------------------------------------- 1 | annotations: 2 | artifacthub.io/category: integration-delivery 3 | artifacthub.io/license: Apache-2.0 4 | artifacthub.io/links: | 5 | - name: support 6 | url: https://github.com/securesign/sigstore-ocp/issues 7 | - name: Chart Source 8 | url: https://github.com/securesign/sigstore-ocp 9 | - name: Default Image Source 10 | url: "" 11 | charts.openshift.io/name: TrustedArtifactSigner 12 | charts.openshift.io/provider: TrustedArtifactSigner 13 | charts.openshift.io/supportURL: https://github.com/securesign/sigstore-ocp/issues 14 | apiVersion: v2 15 | name: trusted-artifact-signer 16 | description: A Helm chart for deploying Sigstore scaffold chart that is opinionated for OpenShift 17 | type: application 18 | dependencies: 19 | - name: scaffold 20 | version: 0.6.41 21 | repository: https://sigstore.github.io/helm-charts 22 | alias: scaffold 23 | keywords: 24 | - sigstore 25 | - sign 26 | - cosign 27 | kubeVersion: ">= 1.19.0-0" 28 | maintainers: 29 | - name: TrustedArtifactSigner 30 | url: "" 31 | sources: 32 | - https://github.com/securesign/sigstore-ocp 33 | # This is the chart version. This version number should be incremented each time you make changes 34 | # to the chart and its templates, including the app version. 35 | # Versions are expected to follow Semantic Versioning (https://semver.org/) 36 | version: 0.1.54 37 | -------------------------------------------------------------------------------- /charts/trusted-artifact-signer/README.md.gotmpl: -------------------------------------------------------------------------------- 1 | {{ template "chart.header" . }} 2 | {{ template "chart.description" . }} 3 | 4 | {{ template "chart.versionBadge" . }}{{ template "chart.typeBadge" . }}{{ template "chart.appVersionBadge" . }} 5 | 6 | ## Overview 7 | 8 | This wrapper chart builds on top of the [Scaffold](https://github.com/sigstore/helm-charts/tree/main/charts/scaffold) 9 | chart from the Sigstore project to both simplify and satisfy the requirements for deployment within an OpenShift 10 | 11 | If you have already read this document and want a quick no-fail path to installing a Sigstore stack with RH SSO, 12 | follow [quick start](../../docs/quick-start-with-keycloak.md) 13 | 14 | The chart enhances the scaffold chart by taking care of the following: 15 | 16 | * Provision Namespaces 17 | * Configure `RoleBindings` to enable access to the `anyuid` SecurityContextConstraint 18 | * Inject Fulcio root and Rekor signing keys 19 | 20 | ### Scaffold customization 21 | 22 | Similar to any Helm dependency, values from the upstream `scaffold` chart can be customized by embedding the properties 23 | within the `scaffold` property similar to the following: 24 | 25 | ```yaml 26 | scaffold: 27 | fulcio: 28 | namespace: 29 | name: fulcio-system 30 | create: false 31 | ... 32 | ``` 33 | 34 | ### Sample Implementation 35 | 36 | #### Prerequisites 37 | 38 | The following must be satisfied prior to deploying the sample implementation: 39 | 40 | * Fulcio root CA certificate and signing keys 41 | * More information in [requirements-keys-certs.md](../../docs/requirements-keys-certs.md) 42 | * OpenID Token Issuer endpoint 43 | * Keycloak/RHSSO requirements can be followed and deployed in OpenShift with [keycloak-example.md](../../docs/keycloak-example.md) 44 | 45 | #### Update the values file 46 | 47 | Helm values files are available in the examples directory that provides a baseline to work off of. 48 | It can be customized based on an individual target environment. 49 | Perform the following modifications to the [example values file](../../examples/values-sigstore-openshift.yaml) 50 | to curate the deployment of the chart: 51 | 52 | 1. Modify the OIDC Issuer URL in the fulcio config section of the values file as necessary. 53 | 54 | 2. Perform any additional customizations as desired 55 | 56 | ### Installing the Chart 57 | 58 | When logged in as an elevated OpenShift user, execute the following to install the chart referencing the 59 | customized values file. The OPENSHIFT_APPS_SUBDOMAIN will be substituted in the values file with `envsubst` below: 60 | 61 | ```shell 62 | OPENSHIFT_APPS_SUBDOMAIN=apps.$(oc get dns cluster -o jsonpath='{ .spec.baseDomain }') envsubst < examples/values-sigstore-openshift.yaml | helm upgrade -i trusted-artifact-signer --debug charts/trusted-artifact-signer -n sigstore --create-namespace --values - 63 | ``` 64 | 65 | ### Monitor Sigstore Components with Grafana 66 | 67 | For real-time analytics through Grafana, refer to our [enable-grafana-monitoring.md](../../docs/enable-grafana-monitoring.md) guide. 68 | 69 | ### Sign and/or verify artifacts! 70 | 71 | Follow [this](../../docs/sign-verify.md) to sign and/or verify artifacts. 72 | 73 | {{ template "chart.requirementsSection" . }} 74 | 75 | {{ template "chart.valuesSection" . }} 76 | 77 | -------------------------------------------------------------------------------- /charts/trusted-artifact-signer/chart_schema.yaml: -------------------------------------------------------------------------------- 1 | name: str() 2 | home: str(required=False) 3 | version: str() 4 | appVersion: any(str(), num(), required=False) 5 | description: str(required=False) 6 | keywords: list(str(), required=False) 7 | sources: list(str(), required=False) 8 | maintainers: list(include('maintainer'), required=False) 9 | dependencies: list(include('dependency'), required=False) 10 | icon: str(required=False) 11 | engine: str(required=False) 12 | condition: str(required=False) 13 | tags: str(required=False) 14 | deprecated: bool(required=False) 15 | apiVersion: str() 16 | kubeVersion: str(required=False) 17 | type: str(required=False) 18 | annotations: map(str(), str(), required=False) 19 | --- 20 | maintainer: 21 | name: str(required=False) 22 | email: str(required=False) 23 | url: str(required=False) 24 | --- 25 | dependency: 26 | name: str() 27 | version: str() 28 | repository: str() 29 | condition: str(required=False) 30 | tags: list(str(), required=False) 31 | enabled: bool(required=False) 32 | import-values: any(list(str()), list(include('import-value')), required=False) 33 | alias: str(required=False) 34 | --- 35 | import-value: 36 | child: str() 37 | parent: str() 38 | -------------------------------------------------------------------------------- /charts/trusted-artifact-signer/charts/scaffold-0.6.41.tgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securesign/sigstore-ocp/49c2c70abdc7f0e789349b99622085c5fcfce682/charts/trusted-artifact-signer/charts/scaffold-0.6.41.tgz -------------------------------------------------------------------------------- /charts/trusted-artifact-signer/ci/ci-values.yaml: -------------------------------------------------------------------------------- 1 | # With this example, it is expected that there is a secret with the fulcio root & signing keys 2 | # named 'fulcio-secret-rh' in namespace 'fulcio-system' and a secret 'rekor-private-key' 3 | # with rekor signing keys in the 'rekor-system' namespace. 4 | # secret names must match secret names in scaffold.tuf, that default to 5 | # 'fulcio-secret-rh' and 'rekor-private-key' 6 | # For root & key requirements, see ../requirements-keys-certs.md 7 | # Note: User must substitute for localhost below. 8 | --- 9 | configs: 10 | segment_backup_job: 11 | image: 12 | registry: quay.io 13 | repository: redhat-user-workloads/rhtas-tenant/segment-backup-job/segment-backup-job 14 | clientserver: 15 | consoleDownload: false 16 | route: false 17 | images: 18 | clientserver_cg: 19 | registry: quay.io 20 | repository: redhat-user-workloads/rhtas-tenant/cli/client-server-cg 21 | clientserver_re: 22 | registry: quay.io 23 | repository: redhat-user-workloads/rhtas-tenant/cli/client-server-re 24 | cosign_deploy: 25 | enabled: true 26 | image: 27 | registry: quay.io 28 | repository: redhat-user-workloads/rhtas-tenant/cli/cosign 29 | fulcio: 30 | clusterMonitoring: 31 | enabled: false 32 | namespace_create: false 33 | rekor: 34 | clusterMonitoring: 35 | enabled: false 36 | namespace_create: false 37 | backfillRedis: 38 | enabled: true 39 | image: 40 | registry: quay.io 41 | repository: redhat-user-workloads/rhtas-tenant/rekor/backfill-redis 42 | rekorui: 43 | enabled: false 44 | route: false 45 | 46 | # github.com/sigstore/helm-charts/charts 47 | scaffold: 48 | ctlog: 49 | server: 50 | image: 51 | registry: quay.io 52 | repository: redhat-user-workloads/rhtas-tenant/certificate-transparency-go/certificate-transparency-go 53 | createctconfig: 54 | image: 55 | registry: quay.io 56 | repository: redhat-user-workloads/rhtas-tenant/scaffold/createctconfig 57 | createtree: 58 | image: 59 | registry: quay.io 60 | repository: redhat-user-workloads/rhtas-tenant/scaffold/trillian-createtree 61 | fulcio: 62 | createcerts: 63 | image: 64 | registry: quay.io 65 | repository: redhat-user-workloads/rhtas-tenant/scaffold/fulcio-createcerts 66 | server: 67 | image: 68 | registry: quay.io 69 | repository: redhat-user-workloads/rhtas-tenant/fulcio/fulcio-server 70 | ingress: 71 | enabled: false 72 | http: 73 | enabled: false 74 | config: 75 | contents: 76 | OIDCIssuers: 77 | # https://../auth/realms/trusted-artifact-signer 78 | ? http://keycloak-internal.keycloak-system.svc/auth/realms/trusted-artifact-signer 79 | : IssuerURL: http://keycloak-internal.keycloak-system.svc/auth/realms/trusted-artifact-signer 80 | ClientID: trusted-artifact-signer 81 | Type: email 82 | rekor: 83 | redis: 84 | image: 85 | registry: quay.io 86 | repository: redhat-user-workloads/rhtas-tenant/trillian/redis 87 | server: 88 | image: 89 | registry: quay.io 90 | repository: redhat-user-workloads/rhtas-tenant/rekor/rekor-server 91 | ingress: 92 | enabled: false 93 | http: 94 | enabled: false 95 | createtree: 96 | image: 97 | registry: quay.io 98 | repository: redhat-user-workloads/rhtas-tenant/scaffold/trillian-createtree 99 | trillian: 100 | createdb: 101 | image: 102 | registry: quay.io 103 | repository: redhat-user-workloads/rhtas-tenant/scaffold/trillian-createdb 104 | redis: 105 | image: 106 | registry: quay.io 107 | repository: redhat-user-workloads/rhtas-tenant/trillian/redis 108 | 109 | logSigner: 110 | image: 111 | registry: quay.io 112 | repository: redhat-user-workloads/rhtas-tenant/trillian/logsigner 113 | logServer: 114 | image: 115 | registry: quay.io 116 | repository: redhat-user-workloads/rhtas-tenant/trillian/logserver 117 | mysql: 118 | image: 119 | registry: quay.io 120 | repository: redhat-user-workloads/rhtas-tenant/trillian/database 121 | tuf: 122 | ingress: 123 | create: false 124 | deployment: 125 | registry: quay.io 126 | repository: redhat-user-workloads/rhtas-tenant/scaffold/tuf-server 127 | -------------------------------------------------------------------------------- /charts/trusted-artifact-signer/templates/_helpers.tpl: -------------------------------------------------------------------------------- 1 | {{/* 2 | Expand the name of the chart. 3 | */}} 4 | {{- define "trusted-artifact-signer.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 "trusted-artifact-signer.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 "trusted-artifact-signer.chart" -}} 30 | {{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} 31 | {{- end }} 32 | 33 | {{/* 34 | Common labels 35 | */}} 36 | {{- define "trusted-artifact-signer.labels" -}} 37 | helm.sh/chart: {{ include "trusted-artifact-signer.chart" . }} 38 | {{ include "trusted-artifact-signer.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 "trusted-artifact-signer.selectorLabels" -}} 49 | app.kubernetes.io/name: {{ include "trusted-artifact-signer.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 "trusted-artifact-signer.serviceAccountName" -}} 57 | {{- if .Values.serviceAccount.create }} 58 | {{- default (include "trusted-artifact-signer.fullname" .) .Values.serviceAccount.name }} 59 | {{- else }} 60 | {{- default "default" .Values.serviceAccount.name }} 61 | {{- end }} 62 | {{- end }} 63 | 64 | {{/* 65 | Create the image path for the passed in image field 66 | */}} 67 | {{- define "image" -}} 68 | {{- if eq (substr 0 7 .version) "sha256:" -}} 69 | {{- printf "%s/%s@%s" .registry .repository .version -}} 70 | {{- else -}} 71 | {{- printf "%s/%s:%s" .registry .repository .version -}} 72 | {{- end -}} 73 | {{- end -}} 74 | -------------------------------------------------------------------------------- /charts/trusted-artifact-signer/templates/backfillRedis-cronjob.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.configs.rekor.backfillRedis.enabled }} 2 | apiVersion: batch/v1 3 | kind: CronJob 4 | metadata: 5 | name: backfill-redis 6 | namespace: {{ .Values.configs.rekor.namespace }} 7 | spec: 8 | schedule: {{ .Values.configs.rekor.backfillRedis.schedule | quote }} 9 | jobTemplate: 10 | spec: 11 | template: 12 | spec: 13 | containers: 14 | - name: backfill-redis 15 | image: "{{ template "image" .Values.configs.rekor.backfillRedis.image }}" 16 | command: ["/bin/sh", "-c"] 17 | args: 18 | - > 19 | endIndex=$(curl -sS http://rekor-server/api/v1/log | sed -E 's/.*"treeSize":([0-9]+).*/\1/'); 20 | endIndex=$((endIndex-1)); 21 | if [ $endIndex -lt 0 ]; then 22 | echo "info: no rekor entries found"; 23 | exit 0; 24 | fi; 25 | backfill-redis --hostname=rekor-redis --port=6379 --rekor-address=http://rekor-server --start=0 --end=$endIndex 26 | restartPolicy: OnFailure 27 | {{- end }} 28 | -------------------------------------------------------------------------------- /charts/trusted-artifact-signer/templates/clientserver-deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: {{ .Values.configs.clientserver.name }} 5 | namespace: {{ .Values.configs.clientserver.namespace }} 6 | labels: 7 | app: {{ .Values.configs.clientserver.name }} 8 | spec: 9 | selector: 10 | matchLabels: 11 | app: {{ .Values.configs.clientserver.name }} 12 | template: 13 | metadata: 14 | labels: 15 | app: {{ .Values.configs.clientserver.name }} 16 | spec: 17 | securityContext: 18 | runAsNonRoot: true 19 | runAsUser: 65533 20 | {{- if $.Values.configs.clientserver.rolebindings }} 21 | serviceAccountName: {{ index .Values.configs.clientserver.rolebindings 0 }} 22 | {{- end }} 23 | volumes: 24 | - name: shared-data 25 | emptyDir: {} 26 | initContainers: 27 | - name: "init-shared-data-cg" 28 | image: "{{ template "image" .Values.configs.clientserver.images.clientserver_cg }}" 29 | command: ["sh", "-c", "cp -r /opt/app-root/src/clients/* /var/www/html/clients/"] 30 | volumeMounts: 31 | - name: shared-data 32 | mountPath: /var/www/html/clients/ 33 | - name: "init-shared-data-re" 34 | image: "{{ template "image" .Values.configs.clientserver.images.clientserver_re }}" 35 | command: ["sh", "-c", "cp -r /opt/app-root/src/clients/* /var/www/html/clients/"] 36 | volumeMounts: 37 | - name: shared-data 38 | mountPath: /var/www/html/clients/ 39 | containers: 40 | - name: tas-clients 41 | image: "{{ template "image" .Values.configs.clientserver.images.httpd }}" 42 | volumeMounts: 43 | - name: shared-data 44 | mountPath: /var/www/html/clients/ 45 | imagePullPolicy: IfNotPresent 46 | ports: 47 | - containerPort: 8080 48 | protocol: TCP 49 | securityContext: 50 | allowPrivilegeEscalation: false 51 | capabilities: 52 | drop: 53 | - ALL 54 | -------------------------------------------------------------------------------- /charts/trusted-artifact-signer/templates/clientserver-route.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.configs.clientserver.route }} 2 | apiVersion: route.openshift.io/v1 3 | kind: Route 4 | metadata: 5 | labels: 6 | app: {{ .Values.configs.clientserver.name }} 7 | name: {{ .Values.configs.clientserver.name }} 8 | namespace: {{ .Values.configs.clientserver.namespace }} 9 | spec: 10 | port: 11 | targetPort: 8080-tcp 12 | tls: 13 | insecureEdgeTerminationPolicy: Redirect 14 | termination: edge 15 | to: 16 | kind: Service 17 | name: {{ .Values.configs.clientserver.name }} 18 | weight: 100 19 | wildcardPolicy: None 20 | {{- end }} 21 | 22 | -------------------------------------------------------------------------------- /charts/trusted-artifact-signer/templates/clientserver-sa.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ServiceAccount 3 | metadata: 4 | name: {{ .Values.configs.clientserver.name }} 5 | namespace: {{ .Values.configs.clientserver.namespace }} 6 | 7 | -------------------------------------------------------------------------------- /charts/trusted-artifact-signer/templates/clientserver-service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | labels: 5 | app: {{ .Values.configs.clientserver.name }} 6 | name: {{ .Values.configs.clientserver.name }} 7 | namespace: {{ .Values.configs.clientserver.namespace }} 8 | spec: 9 | ports: 10 | - name: 8080-tcp 11 | port: 8080 12 | protocol: TCP 13 | targetPort: 8080 14 | selector: 15 | app: {{ .Values.configs.clientserver.name }} 16 | type: ClusterIP 17 | 18 | -------------------------------------------------------------------------------- /charts/trusted-artifact-signer/templates/cluster-monitoring-resources.yaml: -------------------------------------------------------------------------------- 1 | {{- range $configKey, $config := .Values.configs }} 2 | {{- if and $config.clusterMonitoring (eq $config.clusterMonitoring.enabled true) }} 3 | --- 4 | apiVersion: rbac.authorization.k8s.io/v1 5 | kind: Role 6 | metadata: 7 | name: prometheus-k8s 8 | namespace: {{ $config.namespace }} 9 | rules: 10 | - apiGroups: 11 | - "" 12 | resources: 13 | - services 14 | - endpoints 15 | - pods 16 | verbs: 17 | - get 18 | - list 19 | - watch 20 | --- 21 | apiVersion: rbac.authorization.k8s.io/v1 22 | kind: RoleBinding 23 | metadata: 24 | name: prometheus-k8s 25 | namespace: {{ $config.namespace }} 26 | roleRef: 27 | apiGroup: rbac.authorization.k8s.io 28 | kind: Role 29 | name: prometheus-k8s 30 | subjects: 31 | - kind: ServiceAccount 32 | name: prometheus-k8s 33 | namespace: openshift-monitoring 34 | --- 35 | apiVersion: monitoring.coreos.com/v1 36 | kind: ServiceMonitor 37 | metadata: 38 | labels: 39 | app.kubernetes.io/name: {{ $config.namespace }} 40 | name: {{ $config.namespace }} 41 | namespace: {{ $config.namespace }} 42 | spec: 43 | endpoints: 44 | {{- range $endpoint := $config.clusterMonitoring.endpoints }} 45 | - interval: {{ $endpoint.interval }} 46 | port: {{ $endpoint.port }} 47 | scheme: {{ $endpoint.scheme }} 48 | {{- end }} 49 | selector: 50 | matchLabels: 51 | app.kubernetes.io/instance: trusted-artifact-signer 52 | {{- end }} 53 | {{- end }} -------------------------------------------------------------------------------- /charts/trusted-artifact-signer/templates/consoleclidownload-cosign.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.configs.clientserver.consoleDownload }} 2 | apiVersion: console.openshift.io/v1 3 | kind: ConsoleCLIDownload 4 | metadata: 5 | name: cosign 6 | labels: 7 | app.kubernetes.io/managed-by: "Helm" 8 | annotations: 9 | meta.helm.sh/release-name: "trusted-artifact-signer" 10 | meta.helm.sh/release-namespace: "trusted-artifact-signer" 11 | spec: 12 | description: cosign is a CLI tool that allows you to 13 | manage sigstore artifacts. 14 | displayName: cosign - Command Line Interface (CLI) 15 | links: 16 | - href: "https://{{ $.Values.configs.clientserver.name }}-{{ $.Values.configs.clientserver.namespace }}.{{ $.Values.global.appsSubdomain }}/clients/linux/cosign-amd64.gz" 17 | text: Download cosign for Linux x86_64 18 | - href: "https://{{ $.Values.configs.clientserver.name }}-{{ $.Values.configs.clientserver.namespace }}.{{ $.Values.global.appsSubdomain }}/clients/linux/cosign-arm64.gz" 19 | text: Download cosign for Linux arm64 20 | - href: "https://{{ $.Values.configs.clientserver.name }}-{{ $.Values.configs.clientserver.namespace }}.{{ $.Values.global.appsSubdomain }}/clients/linux/cosign-ppc64le.gz" 21 | text: Download cosign for Linux ppc64le 22 | - href: "https://{{ $.Values.configs.clientserver.name }}-{{ $.Values.configs.clientserver.namespace }}.{{ $.Values.global.appsSubdomain }}/clients/linux/cosign-s390x.gz" 23 | text: Download cosign for Linux s390x 24 | - href: "https://{{ $.Values.configs.clientserver.name }}-{{ $.Values.configs.clientserver.namespace }}.{{ $.Values.global.appsSubdomain }}/clients/darwin/cosign-amd64.gz" 25 | text: Download cosign for Mac x86_64 26 | - href: "https://{{ $.Values.configs.clientserver.name }}-{{ $.Values.configs.clientserver.namespace }}.{{ $.Values.global.appsSubdomain }}/clients/darwin/cosign-arm64.gz" 27 | text: Download cosign for Mac arm64 28 | - href: "https://{{ $.Values.configs.clientserver.name }}-{{ $.Values.configs.clientserver.namespace }}.{{ $.Values.global.appsSubdomain }}/clients/windows/cosign-amd64.gz" 29 | text: Download cosign for Windows x86_64 30 | {{- end }} 31 | -------------------------------------------------------------------------------- /charts/trusted-artifact-signer/templates/consoleclidownload-ec.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.configs.clientserver.consoleDownload }} 2 | apiVersion: console.openshift.io/v1 3 | kind: ConsoleCLIDownload 4 | metadata: 5 | name: enterprisecontract 6 | labels: 7 | app.kubernetes.io/managed-by: "Helm" 8 | annotations: 9 | meta.helm.sh/release-name: "trusted-artifact-signer" 10 | meta.helm.sh/release-namespace: "trusted-artifact-signer" 11 | spec: 12 | description: Enterprise Contract is a tool for verifying signatures and performing policy checks on container images 13 | displayName: Enterprise Contract - Command Line Interface (CLI) 14 | links: 15 | - href: "https://{{ $.Values.configs.clientserver.name }}-{{ $.Values.configs.clientserver.namespace }}.{{ $.Values.global.appsSubdomain }}/clients/linux/ec-amd64.gz" 16 | text: Download EnterpriseContract for Linux x86_64 17 | - href: "https://{{ $.Values.configs.clientserver.name }}-{{ $.Values.configs.clientserver.namespace }}.{{ $.Values.global.appsSubdomain }}/clients/linux/ec-arm64.gz" 18 | text: Download EnterpriseContract for Linux arm64 19 | - href: "https://{{ $.Values.configs.clientserver.name }}-{{ $.Values.configs.clientserver.namespace }}.{{ $.Values.global.appsSubdomain }}/clients/linux/ec-ppc64le.gz" 20 | text: Download EnterpriseContract for Linux ppc64le 21 | - href: "https://{{ $.Values.configs.clientserver.name }}-{{ $.Values.configs.clientserver.namespace }}.{{ $.Values.global.appsSubdomain }}/clients/linux/ec-s390x.gz" 22 | text: Download EnterpriseContract for Linux s390x 23 | - href: "https://{{ $.Values.configs.clientserver.name }}-{{ $.Values.configs.clientserver.namespace }}.{{ $.Values.global.appsSubdomain }}/clients/darwin/ec-amd64.gz" 24 | text: Download EnterpriseContract for Mac x86_64 25 | - href: "https://{{ $.Values.configs.clientserver.name }}-{{ $.Values.configs.clientserver.namespace }}.{{ $.Values.global.appsSubdomain }}/clients/darwin/ec-arm64.gz" 26 | text: Download EnterpriseContract for Mac arm64 27 | - href: "https://{{ $.Values.configs.clientserver.name }}-{{ $.Values.configs.clientserver.namespace }}.{{ $.Values.global.appsSubdomain }}/clients/windows/ec-amd64.gz" 28 | text: Download EnterpriseContract for Windows x86_64 29 | {{- end }} 30 | -------------------------------------------------------------------------------- /charts/trusted-artifact-signer/templates/consoleclidownload-gitsign.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.configs.clientserver.consoleDownload }} 2 | apiVersion: console.openshift.io/v1 3 | kind: ConsoleCLIDownload 4 | metadata: 5 | name: gitsign 6 | labels: 7 | app.kubernetes.io/managed-by: "Helm" 8 | annotations: 9 | meta.helm.sh/release-name: "trusted-artifact-signer" 10 | meta.helm.sh/release-namespace: "trusted-artifact-signer" 11 | spec: 12 | description: gitsign is a CLI tool that allows you to 13 | digitally sign and verify git commits. 14 | displayName: gitsign - Command Line Interface (CLI) 15 | links: 16 | - href: "https://{{ $.Values.configs.clientserver.name }}-{{ $.Values.configs.clientserver.namespace }}.{{ $.Values.global.appsSubdomain }}/clients/linux/gitsign-amd64.gz" 17 | text: Download gitsign for Linux x86_64 18 | - href: "https://{{ $.Values.configs.clientserver.name }}-{{ $.Values.configs.clientserver.namespace }}.{{ $.Values.global.appsSubdomain }}/clients/linux/gitsign-arm64.gz" 19 | text: Download gitsign for Linux arm64 20 | - href: "https://{{ $.Values.configs.clientserver.name }}-{{ $.Values.configs.clientserver.namespace }}.{{ $.Values.global.appsSubdomain }}/clients/linux/gitsign-ppc64le.gz" 21 | text: Download gitsign for Linux ppc64le 22 | - href: "https://{{ $.Values.configs.clientserver.name }}-{{ $.Values.configs.clientserver.namespace }}.{{ $.Values.global.appsSubdomain }}/clients/linux/gitsign-s390x.gz" 23 | text: Download gitsign for Linux s390x 24 | - href: "https://{{ $.Values.configs.clientserver.name }}-{{ $.Values.configs.clientserver.namespace }}.{{ $.Values.global.appsSubdomain }}/clients/darwin/gitsign-amd64.gz" 25 | text: Download gitsign for Mac x86_64 26 | - href: "https://{{ $.Values.configs.clientserver.name }}-{{ $.Values.configs.clientserver.namespace }}.{{ $.Values.global.appsSubdomain }}/clients/darwin/gitsign-arm64.gz" 27 | text: Download gitsign for Mac arm64 28 | - href: "https://{{ $.Values.configs.clientserver.name }}-{{ $.Values.configs.clientserver.namespace }}.{{ $.Values.global.appsSubdomain }}/clients/windows/gitsign-amd64.gz" 29 | text: Download gitsign for Windows x86_64 30 | {{- end }} 31 | -------------------------------------------------------------------------------- /charts/trusted-artifact-signer/templates/consoleclidownload-rekor.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.configs.clientserver.consoleDownload }} 2 | apiVersion: console.openshift.io/v1 3 | kind: ConsoleCLIDownload 4 | metadata: 5 | name: rekor-cli 6 | labels: 7 | app.kubernetes.io/managed-by: "Helm" 8 | annotations: 9 | meta.helm.sh/release-name: "trusted-artifact-signer" 10 | meta.helm.sh/release-namespace: "trusted-artifact-signer" 11 | spec: 12 | description: rekor-cli is a CLI tool that allows you to 13 | interact with rekor server. 14 | displayName: rekor - Command Line Interface (CLI) 15 | links: 16 | - href: "https://{{ $.Values.configs.clientserver.name }}-{{ $.Values.configs.clientserver.namespace }}.{{ $.Values.global.appsSubdomain }}/clients/linux/rekor-cli-amd64.gz" 17 | text: Download rekor-cli for Linux x86_64 18 | - href: "https://{{ $.Values.configs.clientserver.name }}-{{ $.Values.configs.clientserver.namespace }}.{{ $.Values.global.appsSubdomain }}/clients/linux/rekor-cli-arm64.gz" 19 | text: Download rekor-cli for Linux arm64 20 | - href: "https://{{ $.Values.configs.clientserver.name }}-{{ $.Values.configs.clientserver.namespace }}.{{ $.Values.global.appsSubdomain }}/clients/linux/rekor-cli-ppc64le.gz" 21 | text: Download rekor-cli for Linux ppc64le 22 | - href: "https://{{ $.Values.configs.clientserver.name }}-{{ $.Values.configs.clientserver.namespace }}.{{ $.Values.global.appsSubdomain }}/clients/linux/rekor-cli-s390x.gz" 23 | text: Download rekor-cli for Linux s390x 24 | - href: "https://{{ $.Values.configs.clientserver.name }}-{{ $.Values.configs.clientserver.namespace }}.{{ $.Values.global.appsSubdomain }}/clients/darwin/rekor-cli-amd64.gz" 25 | text: Download rekor-cli for Mac x86_64 26 | - href: "https://{{ $.Values.configs.clientserver.name }}-{{ $.Values.configs.clientserver.namespace }}.{{ $.Values.global.appsSubdomain }}/clients/darwin/rekor-cli-arm64.gz" 27 | text: Download rekor-cli for Mac arm64 28 | - href: "https://{{ $.Values.configs.clientserver.name }}-{{ $.Values.configs.clientserver.namespace }}.{{ $.Values.global.appsSubdomain }}/clients/windows/rekor-cli-amd64.gz" 29 | text: Download rekor-cli for Windows x86_64 30 | {{- end }} 31 | -------------------------------------------------------------------------------- /charts/trusted-artifact-signer/templates/cosign-deployment.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.configs.cosign_deploy.enabled }} 2 | apiVersion: apps/v1 3 | kind: Deployment 4 | metadata: 5 | name: {{ .Values.configs.cosign_deploy.name }} 6 | namespace: {{ .Values.configs.cosign_deploy.namespace }} 7 | spec: 8 | selector: 9 | matchLabels: 10 | app: {{ .Values.configs.cosign_deploy.name }} 11 | template: 12 | metadata: 13 | labels: 14 | app: {{ .Values.configs.cosign_deploy.name }} 15 | spec: 16 | securityContext: 17 | runAsNonRoot: true 18 | runAsUser: 65533 19 | {{- if $.Values.configs.cosign_deploy.rolebindings }} 20 | serviceAccountName: {{ index .Values.configs.cosign_deploy.rolebindings 0 }} 21 | {{- end }} 22 | containers: 23 | - name: {{ .Values.configs.cosign_deploy.name }} 24 | image: "{{ template "image" .Values.configs.cosign_deploy.image }}" 25 | env: 26 | - name: OPENSHIFT_APPS_SUBDOMAIN 27 | value: {{ .Values.global.appsSubdomain }} 28 | - name: OIDC_AUTHENTICATION_REALM 29 | value: "trusted-artifact-signer" 30 | - name: COSIGN_OIDC_CLIENT_ID 31 | value: "trusted-artifact-signer" 32 | - name: COSIGN_FULCIO_URL 33 | value: "https://fulcio.$(OPENSHIFT_APPS_SUBDOMAIN)" 34 | - name: COSIGN_OIDC_ISSUER 35 | value: "https://keycloak-keycloak-system.$(OPENSHIFT_APPS_SUBDOMAIN)/auth/realms/$(OIDC_AUTHENTICATION_REALM)" 36 | - name: COSIGN_CERTIFICATE_OIDC_ISSUER 37 | value: "https://keycloak-keycloak-system.$(OPENSHIFT_APPS_SUBDOMAIN)/auth/realms/$(OIDC_AUTHENTICATION_REALM)" 38 | - name: COSIGN_REKOR_URL 39 | value: "https://rekor.$(OPENSHIFT_APPS_SUBDOMAIN)" 40 | - name: COSIGN_MIRROR 41 | value: "https://tuf.$(OPENSHIFT_APPS_SUBDOMAIN)" 42 | - name: COSIGN_ROOT 43 | value: "https://tuf.$(OPENSHIFT_APPS_SUBDOMAIN)/root.json" 44 | - name: COSIGN_YES 45 | value: "true" 46 | securityContext: 47 | allowPrivilegeEscalation: false 48 | capabilities: 49 | drop: 50 | - ALL 51 | {{- end }} 52 | -------------------------------------------------------------------------------- /charts/trusted-artifact-signer/templates/cosign-sa.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.configs.cosign_deploy.enabled }} 2 | {{- if .Values.configs.cosign_deploy.rolebindings }} 3 | --- 4 | apiVersion: v1 5 | kind: ServiceAccount 6 | metadata: 7 | namespace: {{ .Values.configs.cosign_deploy.namespace }} 8 | name: {{ index .Values.configs.cosign_deploy.rolebindings 0 }} 9 | {{- end }} 10 | {{- end }} 11 | -------------------------------------------------------------------------------- /charts/trusted-artifact-signer/templates/fulcio-secret.yaml: -------------------------------------------------------------------------------- 1 | {{- if and .Values.configs.fulcio.server.secret.name }} 2 | apiVersion: v1 3 | kind: Secret 4 | metadata: 5 | name: {{ .Values.configs.fulcio.server.secret.name }} 6 | namespace: {{ .Values.configs.fulcio.namespace }} 7 | type: Opaque 8 | stringData: 9 | {{- if or .Values.configs.fulcio.server.secret.root_cert .Values.configs.fulcio.server.secret.root_cert_file }} 10 | {{- if .Values.configs.fulcio.server.secret.root_cert }} 11 | cert: {{ (.Values.configs.fulcio.server.secret.root_cert | default .Values.configs.fulcio.server.secret.root_cert (.Files.Get .Values.configs.fulcio.server.secret.root_cert_file)) | toYaml | indent 2 }} 12 | {{- end }} 13 | {{- end }} 14 | {{- if or .Values.configs.fulcio.server.secret.public_key .Values.configs.fulcio.server.secret.public_key_file }} 15 | {{- if .Values.configs.fulcio.server.secret.public_key }} 16 | public: {{ (.Values.configs.fulcio.server.secret.public_key | default .Values.configs.fulcio.server.secret.public_key (.Files.Get .Values.configs.fulcio.server.secret.public_key_file)) | toYaml | indent 2 }} 17 | {{- end }} 18 | {{- end }} 19 | {{- if or .Values.configs.fulcio.server.secret.private_key .Values.configs.fulcio.server.secret.private_key_file }} 20 | {{- if .Values.configs.fulcio.server.secret.private_key }} 21 | private: {{ (.Values.configs.fulcio.server.secret.private_key | default .Values.configs.fulcio.server.secret.private_key (.Files.Get .Values.configs.fulcio.server.secret.private_key_file)) | toYaml | indent 2 }} 22 | {{- end }} 23 | {{- end }} 24 | password: {{ required "A Password is Required for the Fulcio Secret" .Values.configs.fulcio.server.secret.password }} 25 | {{- end }} -------------------------------------------------------------------------------- /charts/trusted-artifact-signer/templates/namespace.yaml: -------------------------------------------------------------------------------- 1 | {{- range $configKey, $config := .Values.configs }} 2 | {{- if $config.namespace_create }} 3 | --- 4 | apiVersion: v1 5 | kind: Namespace 6 | metadata: 7 | name: {{ $config.namespace }} 8 | {{- if and $config.clusterMonitoring (eq $config.clusterMonitoring.enabled true) }} 9 | labels: 10 | openshift.io/cluster-monitoring: "true" 11 | {{- end}} 12 | {{- end }} 13 | {{- end }} -------------------------------------------------------------------------------- /charts/trusted-artifact-signer/templates/rekor-signer-secret.yaml: -------------------------------------------------------------------------------- 1 | {{- if and .Values.configs.rekor.signer.secret.name }} 2 | apiVersion: v1 3 | kind: Secret 4 | metadata: 5 | name: {{ .Values.configs.rekor.signer.secret.name }} 6 | namespace: {{ .Values.configs.rekor.namespace }} 7 | type: Opaque 8 | stringData: 9 | {{- if or .Values.configs.rekor.signer.secret.private_key .Values.configs.rekor.signer.secret.private_key_file }} 10 | private: {{ (.Values.configs.rekor.signer.secret.private_key | default .Values.configs.rekor.signer.secret.private_key (.Files.Get .Values.configs.rekor.signer.secret.private_key_file)) | toYaml | indent 2 }} 11 | {{- end }} 12 | {{- end }} -------------------------------------------------------------------------------- /charts/trusted-artifact-signer/templates/rekor-ui-deployment.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.configs.rekorui.enabled }} 2 | apiVersion: apps/v1 3 | kind: Deployment 4 | metadata: 5 | name: {{ .Values.configs.rekorui.name }} 6 | namespace: {{ .Values.configs.rekorui.namespace }} 7 | labels: 8 | app: {{ .Values.configs.rekorui.name }} 9 | spec: 10 | selector: 11 | matchLabels: 12 | app: {{ .Values.configs.rekorui.name }} 13 | template: 14 | metadata: 15 | labels: 16 | app: {{ .Values.configs.rekorui.name }} 17 | spec: 18 | securityContext: 19 | runAsNonRoot: true 20 | seccompProfile: 21 | type: RuntimeDefault 22 | serviceAccountName: {{ .Values.configs.rekorui.name }} 23 | containers: 24 | - name: rekor-ui 25 | image: "{{ template "image" .Values.configs.rekorui.image }}" 26 | imagePullPolicy: Always 27 | env: 28 | - name: NEXT_PUBLIC_REKOR_DEFAULT_DOMAIN 29 | value: "https://rekor.{{ .Values.global.appsSubdomain }}" 30 | ports: 31 | - containerPort: 3000 32 | protocol: TCP 33 | securityContext: 34 | allowPrivilegeEscalation: false 35 | capabilities: 36 | drop: 37 | - ALL 38 | {{- end }} 39 | -------------------------------------------------------------------------------- /charts/trusted-artifact-signer/templates/rekor-ui-route.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.configs.rekorui.enabled }} 2 | {{- if .Values.configs.rekorui.route }} 3 | apiVersion: route.openshift.io/v1 4 | kind: Route 5 | metadata: 6 | labels: 7 | app: {{ .Values.configs.rekorui.name }} 8 | name: {{ .Values.configs.rekorui.name }} 9 | namespace: {{ .Values.configs.rekorui.namespace }} 10 | spec: 11 | port: 12 | targetPort: 3000-tcp 13 | tls: 14 | insecureEdgeTerminationPolicy: Redirect 15 | termination: edge 16 | to: 17 | kind: Service 18 | name: {{ .Values.configs.rekorui.name }} 19 | weight: 100 20 | wildcardPolicy: None 21 | {{- end }} 22 | {{- end }} 23 | -------------------------------------------------------------------------------- /charts/trusted-artifact-signer/templates/rekor-ui-sa.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.configs.rekorui.enabled }} 2 | apiVersion: v1 3 | kind: ServiceAccount 4 | metadata: 5 | name: {{ .Values.configs.rekorui.name }} 6 | namespace: {{ .Values.configs.rekorui.namespace }} 7 | {{- end }} 8 | -------------------------------------------------------------------------------- /charts/trusted-artifact-signer/templates/rekor-ui-service.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.configs.rekorui.enabled }} 2 | apiVersion: v1 3 | kind: Service 4 | metadata: 5 | labels: 6 | app: {{ .Values.configs.rekorui.name }} 7 | name: {{ .Values.configs.rekorui.name }} 8 | namespace: {{ .Values.configs.rekorui.namespace }} 9 | spec: 10 | ports: 11 | - name: 3000-tcp 12 | port: 3000 13 | protocol: TCP 14 | targetPort: 3000 15 | selector: 16 | app: {{ .Values.configs.rekorui.name }} 17 | type: ClusterIP 18 | {{- end }} 19 | -------------------------------------------------------------------------------- /charts/trusted-artifact-signer/templates/rolebinding.yaml: -------------------------------------------------------------------------------- 1 | {{- range $configKey, $config := .Values.configs }} 2 | {{- if $config.rolebindings }} 3 | {{- if or (not (hasKey $config "enabled")) (eq $config.enabled true) }} 4 | --- 5 | apiVersion: rbac.authorization.k8s.io/v1 6 | kind: RoleBinding 7 | metadata: 8 | name: {{ $.Values.rbac.clusterrole }} 9 | namespace: {{ $config.namespace }} 10 | roleRef: 11 | apiGroup: rbac.authorization.k8s.io 12 | kind: ClusterRole 13 | name: {{ $.Values.rbac.clusterrole }} 14 | subjects: 15 | {{- range $rolebinding := $config.rolebindings }} 16 | - kind: ServiceAccount 17 | name: {{ $rolebinding }} 18 | namespace: {{ $config.namespace }} 19 | {{- end }} 20 | {{- end }} 21 | {{- end }} 22 | {{- end }} -------------------------------------------------------------------------------- /charts/trusted-artifact-signer/templates/segment-backup-cronjob.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.configs.segment_backup_job.enabled }} 2 | apiVersion: batch/v1 3 | kind: CronJob 4 | metadata: 5 | name: {{ .Values.configs.segment_backup_job.name }} 6 | namespace: {{ .Values.configs.segment_backup_job.namespace }} 7 | spec: 8 | schedule: "0 0 * * *" 9 | concurrencyPolicy: "Replace" 10 | startingDeadlineSeconds: 200 11 | suspend: false 12 | successfulJobsHistoryLimit: 7 13 | failedJobsHistoryLimit: 3 14 | jobTemplate: 15 | spec: 16 | template: 17 | metadata: 18 | name: {{ .Values.configs.segment_backup_job.name }} 19 | labels: 20 | parent: "segment-backup-job" 21 | spec: 22 | restartPolicy: OnFailure 23 | serviceAccountName: segment-backup-job 24 | containers: 25 | - name: {{ .Values.configs.segment_backup_job.name }} 26 | # image: "{{ .Values.configs.segment_backup_job.image.registry }}/{{ .Values.configs.segment_backup_job.image.repository }}/{{ .Values.configs.segment_backup_job.image.version }}" 27 | image: "{{ .Values.configs.segment_backup_job.image.registry }}/{{ .Values.configs.segment_backup_job.image.repository }}@{{ .Values.configs.segment_backup_job.image.version }}" 28 | command: ["/bin/bash", "/opt/app-root/src/script.sh"] 29 | env: 30 | - name: RUN_TYPE 31 | value: "nightly" 32 | securityContext: 33 | allowPrivilegeEscalation: false 34 | seccompProfile: 35 | type: RuntimeDefault 36 | capabilities: 37 | drop: 38 | - ALL 39 | {{- end}} -------------------------------------------------------------------------------- /charts/trusted-artifact-signer/templates/segment-backup-job-clusterrole.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.configs.segment_backup_job.enabled }} 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: ClusterRole 4 | metadata: 5 | name: segment-backup-job 6 | rules: 7 | - apiGroups: 8 | - "" 9 | resources: 10 | - secrets 11 | - configmaps 12 | verbs: 13 | - get 14 | - list 15 | - apiGroups: 16 | - "route.openshift.io" 17 | resources: 18 | - routes 19 | verbs: 20 | - get 21 | - list 22 | - apiGroups: 23 | - "operator.openshift.io/v1" 24 | resources: 25 | - console 26 | verbs: 27 | - get 28 | {{- end}} 29 | -------------------------------------------------------------------------------- /charts/trusted-artifact-signer/templates/segment-backup-job-clusterrolebinding.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.configs.segment_backup_job.enabled }} 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: ClusterRoleBinding 4 | metadata: 5 | name: segment-backup-job 6 | roleRef: 7 | apiGroup: rbac.authorization.k8s.io 8 | kind: ClusterRole 9 | name: segment-backup-job 10 | subjects: 11 | - kind: ServiceAccount 12 | name: segment-backup-job 13 | namespace: {{ .Values.configs.segment_backup_job.namespace }} 14 | {{- end}} -------------------------------------------------------------------------------- /charts/trusted-artifact-signer/templates/segment-backup-job-sa.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.configs.segment_backup_job.enabled }} 2 | apiVersion: v1 3 | kind: ServiceAccount 4 | metadata: 5 | name: segment-backup-job 6 | namespace: {{ .Values.configs.segment_backup_job.namespace }} 7 | secrets: 8 | - name: pull-secret 9 | {{- end}} -------------------------------------------------------------------------------- /charts/trusted-artifact-signer/templates/segment-backup-job.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.configs.segment_backup_job.enabled }} 2 | apiVersion: batch/v1 3 | kind: Job 4 | metadata: 5 | name: {{ .Values.configs.segment_backup_job.name }} 6 | namespace: {{ .Values.configs.segment_backup_job.namespace }} 7 | spec: 8 | parallelism: 1 9 | completions: 1 10 | activeDeadlineSeconds: 600 11 | backoffLimit: 5 12 | template: 13 | metadata: 14 | name: {{ .Values.configs.segment_backup_job.name }} 15 | labels: 16 | parent: "segment-backup-job" 17 | spec: 18 | restartPolicy: OnFailure 19 | serviceAccountName: segment-backup-job 20 | containers: 21 | - name: {{ .Values.configs.segment_backup_job.name }} 22 | # image: "{{ .Values.configs.segment_backup_job.image.registry }}/{{ .Values.configs.segment_backup_job.image.repository }}/{{ .Values.configs.segment_backup_job.image.version }}" 23 | image: "{{ .Values.configs.segment_backup_job.image.registry }}/{{ .Values.configs.segment_backup_job.image.repository }}@{{ .Values.configs.segment_backup_job.image.version }}" 24 | command: ["/bin/bash", "/opt/app-root/src/script.sh"] 25 | env: 26 | - name: RUN_TYPE 27 | value: "installation" 28 | securityContext: 29 | allowPrivilegeEscalation: false 30 | seccompProfile: 31 | type: RuntimeDefault 32 | capabilities: 33 | drop: 34 | - ALL 35 | {{- end}} -------------------------------------------------------------------------------- /charts/trusted-artifact-signer/templates/tests/test-connection.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: trusted-artifact-signer-test-connection 5 | labels: 6 | app.kubernetes.io/component: trusted-artifact-signer 7 | annotations: 8 | helm.sh/hook: test 9 | spec: 10 | containers: 11 | - name: curl 12 | image: registry.access.redhat.com/ubi9/ubi-minimal:latest 13 | command: ["/bin/sh", "-c"] 14 | args: 15 | - | 16 | curl --connect-timeout 5 --max-time 10 --retry 10 --retry-delay 5 --retry-max-time 30 --retry-all-errors tuf-server.tuf-system.svc:80 17 | curl --connect-timeout 5 --max-time 10 --retry 10 --retry-delay 5 --retry-max-time 30 --retry-all-errors tuf-server.tuf-system.svc:80/targets/ 18 | curl --connect-timeout 5 --max-time 10 --retry 10 --retry-delay 5 --retry-max-time 30 --retry-all-errors tuf-server.tuf-system.svc:80/targets/ctfe.pub 19 | curl --connect-timeout 5 --max-time 10 --retry 10 --retry-delay 5 --retry-max-time 30 --retry-all-errors tuf-server.tuf-system.svc:80/targets/fulcio-cert 20 | curl --connect-timeout 5 --max-time 10 --retry 10 --retry-delay 5 --retry-max-time 30 --retry-all-errors tuf-server.tuf-system.svc:80/targets/rekor-pubkey 21 | restartPolicy: Never 22 | -------------------------------------------------------------------------------- /charts/trusted-artifact-signer/templates/tests/test-sign-verify.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: trusted-artifact-signer-test-sign-verify 5 | labels: 6 | app.kubernetes.io/component: trusted-artifact-signer 7 | annotations: 8 | helm.sh/hook: test 9 | spec: 10 | initContainers: 11 | - name: buildah 12 | image: quay.io/buildah/stable 13 | command: ["/bin/sh", "-c"] 14 | args: 15 | - | 16 | buildah pull alpine:latest 17 | buildah tag alpine:latest ttl.sh/sigstore-test:5m 18 | buildah push ttl.sh/sigstore-test:5m 19 | securityContext: 20 | privileged: true 21 | runAsUser: 0 22 | containers: 23 | - name: cosign 24 | image: "{{ .Values.configs.cosign_deploy.image.registry }}/{{ .Values.configs.cosign_deploy.image.repository }}@{{ .Values.configs.cosign_deploy.image.version }}" 25 | env: 26 | - name: OIDC_AUTHENTICATION_REALM 27 | value: "trusted-artifact-signer" 28 | - name: COSIGN_OIDC_CLIENT_ID 29 | value: "trusted-artifact-signer" 30 | - name: COSIGN_FULCIO_URL 31 | value: "http://fulcio-server.fulcio-system.svc" 32 | - name: COSIGN_REKOR_URL 33 | value: "http://rekor-server.rekor-system.svc" 34 | - name: COSIGN_OIDC_ISSUER 35 | value: "http://keycloak-internal.keycloak-system.svc/auth/realms/$(OIDC_AUTHENTICATION_REALM)" 36 | - name: COSIGN_CERTIFICATE_OIDC_ISSUER 37 | value: "http://keycloak-internal.keycloak-system.svc/auth/realms/$(OIDC_AUTHENTICATION_REALM)" 38 | - name: COSIGN_MIRROR 39 | value: "http://tuf-server.tuf-system.svc" 40 | - name: COSIGN_ROOT 41 | value: "http://tuf-server.tuf-system.svc/root.json" 42 | - name: COSIGN_YES 43 | value: "true" 44 | command: ["/bin/sh", "-c"] 45 | args: 46 | - | 47 | cosign initialize 48 | TOKEN=$(curl -X POST -H "Content-Type: application/x-www-form-urlencoded" -d "username=jdoe" -d "password=secure" -d "grant_type=password" -d "scope=openid" -d "client_id=trusted-artifact-signer" $COSIGN_OIDC_ISSUER/protocol/openid-connect/token | sed -E 's/.*"access_token":"([^"]*).*/\1/') 49 | cosign sign -y --identity-token=$TOKEN ttl.sh/sigstore-test:5m 50 | cosign verify --certificate-identity-regexp ".*@redhat" ttl.sh/sigstore-test:5m 51 | restartPolicy: Never 52 | -------------------------------------------------------------------------------- /charts/trusted-artifact-signer/values.schema.tmpl.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2020-12/schema", 3 | "$id": "http://example.com/example.json", 4 | "type": "object", 5 | "title": "Root Schema", 6 | "properties": { 7 | "global": { 8 | "type": "object", 9 | "properties": { 10 | "appsSubdomain": { 11 | "type": "string" 12 | } 13 | } 14 | }, 15 | "scaffold": { 16 | "title": "Upstream Sigstore Scaffold chart schema.", 17 | "$ref": "https://raw.githubusercontent.com/sigstore/helm-charts/main/charts/scaffold/values.schema.json" 18 | }, 19 | "configs": { 20 | "type": "object", 21 | "properties": { 22 | "segment_backup_job":{ 23 | "properties": { 24 | "enabled": { 25 | "type": "boolean" 26 | }, 27 | "name": { 28 | "type": "string" 29 | }, 30 | "namespace": { 31 | "type" : "string" 32 | }, 33 | "namespace_create": { 34 | "type": "boolean" 35 | }, 36 | "image": { 37 | "properties": { 38 | "pullPolicy": { 39 | "type": "string" 40 | }, 41 | "registry": { 42 | "type": "string" 43 | }, 44 | "repository": { 45 | "type": "string" 46 | }, 47 | "version": { 48 | "type": "string" 49 | } 50 | } 51 | }, 52 | "rolebindings": { 53 | "items": { 54 | "type": "string" 55 | }, 56 | "type": "array" 57 | } 58 | } 59 | }, 60 | "clientserver": { 61 | "properties": { 62 | "consoleDownload": { 63 | "type": "boolean" 64 | }, 65 | "route": { 66 | "type": "boolean" 67 | }, 68 | "name": { 69 | "type": "string" 70 | }, 71 | "namespace_create": { 72 | "type": "boolean" 73 | }, 74 | "namespace": { 75 | "type": "string" 76 | }, 77 | "image": { 78 | "properties": { 79 | "pullPolicy": { 80 | "type": "string" 81 | }, 82 | "registry": { 83 | "type": "string" 84 | }, 85 | "repository": { 86 | "type": "string" 87 | }, 88 | "version": { 89 | "type": "string" 90 | } 91 | }, 92 | "type": "object" 93 | } 94 | }, 95 | "type": "object" 96 | }, 97 | "cosign_deploy": { 98 | "properties": { 99 | "enabled": { 100 | "type": "boolean" 101 | }, 102 | "namespace_create": { 103 | "type": "boolean" 104 | }, 105 | "namespace": { 106 | "type": "string" 107 | }, 108 | "image": { 109 | "properties": { 110 | "pullPolicy": { 111 | "type": "string" 112 | }, 113 | "registry": { 114 | "type": "string" 115 | }, 116 | "repository": { 117 | "type": "string" 118 | }, 119 | "version": { 120 | "type": "string" 121 | } 122 | }, 123 | "type": "object" 124 | }, 125 | "rolebindings": { 126 | "items": { 127 | "type": "string" 128 | }, 129 | "type": "array" 130 | } 131 | }, 132 | "type": "object" 133 | }, 134 | "ctlog": { 135 | "properties": { 136 | "namespace_create": { 137 | "type": "boolean" 138 | }, 139 | "namespace": { 140 | "type": "string" 141 | }, 142 | "rolebindings": { 143 | "items": { 144 | "type": "string" 145 | }, 146 | "type": "array" 147 | } 148 | }, 149 | "type": "object" 150 | }, 151 | "fulcio": { 152 | "properties": { 153 | "namespace_create": { 154 | "type": "boolean" 155 | }, 156 | "namespace": { 157 | "type": "string" 158 | }, 159 | "rolebindings": { 160 | "items": { 161 | "type": "string" 162 | }, 163 | "type": "array" 164 | }, 165 | "clusterMonitoring": { 166 | "type": "object", 167 | "properties": { 168 | "enabled": { 169 | "type": "boolean" 170 | }, 171 | "endpoints": { 172 | "type": "array", 173 | "items": { 174 | "interval": { 175 | "type": "string" 176 | }, 177 | "port": { 178 | "type": "string" 179 | }, 180 | "scheme": { 181 | "type": "string" 182 | } 183 | } 184 | } 185 | } 186 | }, 187 | "server": { 188 | "properties": { 189 | "secret": { 190 | "properties": { 191 | "name": { 192 | "type": "string" 193 | }, 194 | "password": { 195 | "type": "string" 196 | }, 197 | "private_key": { 198 | "type": "string" 199 | }, 200 | "private_key_file": { 201 | "type": "string" 202 | }, 203 | "public_key": { 204 | "type": "string" 205 | }, 206 | "public_key_file": { 207 | "type": "string" 208 | }, 209 | "root_cert": { 210 | "type": "string" 211 | }, 212 | "root_cert_file": { 213 | "type": "string" 214 | } 215 | }, 216 | "type": "object" 217 | } 218 | }, 219 | "type": "object" 220 | } 221 | }, 222 | "type": "object" 223 | }, 224 | "rekor": { 225 | "properties": { 226 | "namespace_create": { 227 | "type": "boolean" 228 | }, 229 | "namespace": { 230 | "type": "string" 231 | }, 232 | "rolebindings": { 233 | "items": { 234 | "type": "string" 235 | }, 236 | "type": "array" 237 | }, 238 | "clusterMonitoring": { 239 | "type": "object", 240 | "properties": { 241 | "enabled": { 242 | "type": "boolean" 243 | }, 244 | "endpoints": { 245 | "type": "array", 246 | "items": { 247 | "interval": { 248 | "type": "string" 249 | }, 250 | "port": { 251 | "type": "string" 252 | }, 253 | "scheme": { 254 | "type": "string" 255 | } 256 | } 257 | } 258 | } 259 | }, 260 | "signer": { 261 | "properties": { 262 | "secret": { 263 | "properties": { 264 | "name": { 265 | "type": "string" 266 | }, 267 | "private_key": { 268 | "type": "string" 269 | }, 270 | "private_key_file": { 271 | "type": "string" 272 | } 273 | }, 274 | "type": "object" 275 | } 276 | }, 277 | "type": "object" 278 | } 279 | }, 280 | "type": "object" 281 | }, 282 | "trillian": { 283 | "properties": { 284 | "namespace_create": { 285 | "type": "boolean" 286 | }, 287 | "namespace": { 288 | "type": "string" 289 | }, 290 | "rolebindings": { 291 | "items": { 292 | "type": "string" 293 | }, 294 | "type": "array" 295 | } 296 | }, 297 | "type": "object" 298 | }, 299 | "tuf": { 300 | "properties": { 301 | "namespace_create": { 302 | "type": "boolean" 303 | }, 304 | "namespace": { 305 | "type": "string" 306 | }, 307 | "rolebindings": { 308 | "items": { 309 | "type": "string" 310 | }, 311 | "type": "array" 312 | } 313 | }, 314 | "type": "object" 315 | } 316 | } 317 | }, 318 | "rbac": { 319 | "properties": { 320 | "clusterrole": { 321 | "type": "string" 322 | } 323 | }, 324 | "type": "object" 325 | } 326 | } 327 | } -------------------------------------------------------------------------------- /cr.yaml: -------------------------------------------------------------------------------- 1 | generate-release-notes: true 2 | -------------------------------------------------------------------------------- /ct-install.yaml: -------------------------------------------------------------------------------- 1 | chart-dirs: 2 | - charts 3 | validate-maintainers: false 4 | remote: origin 5 | target-branch: main 6 | -------------------------------------------------------------------------------- /ct.yaml: -------------------------------------------------------------------------------- 1 | chart-dirs: 2 | - charts 3 | validate-maintainers: false 4 | remote: origin 5 | target-branch: main 6 | -------------------------------------------------------------------------------- /docs/configure-oidc.md: -------------------------------------------------------------------------------- 1 | # OIDC configuration 2 | 3 | While RHTAS uses the RHSSO operator (based on Keycloak) for OIDC by default, other OIDC options are available. Integrating with these options is described below. These steps should be followed after [RHTAS installation](https://access.redhat.com/documentation/en-us/red_hat_trusted_artifact_signer/2024-q1/html/deployment_guide/index), as they will assume that other components, including the Keycloak client for RHTAS, is present, and that the environment variables for Cosign initialization are [populated](https://github.com/securesign/sigstore-ocp/blob/main/sign-verify.md#signing-a-container-from-the-local-system). You may need to recreate the Keycloak client for RHTAS once the `sigstore` realm has been fully configured as described within this guide. 4 | 5 | ## Google 6 | 7 | ### Obtain Client ID and Secret for Google OAuth 2.0 8 | 9 | To integrate RHTAS with Google as an identity provider, you must have access to a client ID and client secret for OAuth 2.0 via APIs & Services in Google Cloud Console. If you do not have these available, you can create them by following the directions [here](https://developers.google.com/workspace/guides/create-credentials#oauth-client-id) and specifying the following: 10 | 11 | - The type of application required is Web Application 12 | - Authorized redirect URIs must include `http://localhost/auth/callback` 13 | 14 | Once created, the credentials should be available in the Google Cloud Console under APIs & Services -> Credentials -> OAuth 2.0 Client IDs. 15 | 16 | ### Update Fulcio deployment configuration 17 | 18 | Once RHTAS is installed, issue 19 | 20 | ``` 21 | oc edit cm fulcio-server-config -n fulcio-system 22 | ``` 23 | 24 | Update the configuration with the client ID and client secret, as well as the Google IdP issuer URL: 25 | 26 | ``` 27 | apiVersion: v1 28 | data: 29 | config.json: |- 30 | { 31 | "OIDCIssuers": { 32 | "https://accounts.google.com": { 33 | "ClientID": "", 34 | "IssuerURL": "https://accounts.google.com", 35 | "Type": "email" 36 | } 37 | } 38 | } 39 | kind: ConfigMap 40 | ... 41 | ``` 42 | 43 | Restart Fulcio with 44 | 45 | ``` 46 | oc delete $(oc get pods -n fulcio-system -o name) -n fulcio-system 47 | ``` 48 | 49 | You can check that the config updated properly with `oc describe cm fulcio-server-config -n fulcio-system`. 50 | 51 | ### Set OIDC issuer 52 | 53 | The OIDC issuer environment variable must point to Google rather than Keycloak in the terminal where signing and verification with RHTAS are being executed. The correct issuer for Google is https://accounts.google.com. 54 | 55 | ``` 56 | export COSIGN_OIDC_ISSUER=https://accounts.google.com 57 | ``` 58 | This value overrides what is specified in the [sign-verify documentation](sign-verify.md). Be careful to avoid resetting `COSIGN_OIDC_ISSUER` when using the `sign-verify` documentation steps or sourcing the `tas-env-variables.sh` script. You can check what the environment variable's value is by issuing 59 | 60 | ``` 61 | $ echo $COSIGN_OIDC_ISSUER 62 | ``` 63 | 64 | It should show `https://accounts.google.com`. 65 | 66 | 67 | ### Pass in client ID and secret during signing 68 | 69 | Create a client secret file that contains only the client secret: 70 | 71 | `echo > ` 72 | 73 | When issuing a `cosign sign` command, add the flags to pass in the client secret (as a file path) and the client ID (as a string): 74 | 75 | ``` 76 | cosign sign -y $IMAGE --oidc-client-secret-file= --oidc-client-id= 77 | ``` 78 | 79 | ## GitHub (federated via Keycloak) 80 | 81 | GitHub federation via Keycloak can be added either from the CLI or from the Keycloak console. Each option is described below. The client ID and client secret must be obtained from GitHub prior to setting up the identity provider regardless of the option chosen. 82 | 83 | ### Obtain Client ID and Secret from GitHub OAuth App 84 | 85 | To integrate RHTAS with GitHub as an identity provider, you must register your GitHub OAuth App in your Keycloak realm. 86 | 87 | Locate your GitHub OAuth App, or create a new GitHub OAuth App following the directions [here](https://docs.github.com/en/apps/oauth-apps/building-oauth-apps/creating-an-oauth-app). When creating the OAuth App, it is acceptable to enter placeholder values for the Authorization Callback and Homepage URL fields, as these fields will need to be updated to hold values sourced from Keycloak, which will be described later in this guide. 88 | 89 | From the OAuth app's page, locate the client ID and create a new client secret, as these values will be required in later steps. 90 | 91 | ### Option 1: Create a New KeycloakRealm in OpenShift using the CLI 92 | 93 | This option will create a new KeycloakRealm that includes the GitHub Identity Provider and Mapper using the CLI and a Custom Resource file, then add the Redirect URI to the OAuth app. 94 | 95 | #### Create a New KeycloakRealm 96 | 97 | Create a Custom Resource file called `realm-cr.yaml` from which to create the KeycloakRealm with the following content (note that you must add your own client ID and secret): 98 | 99 | ```shell 100 | apiVersion: keycloak.org/v1alpha1 101 | kind: KeycloakRealm 102 | metadata: 103 | labels: 104 | app: sso 105 | name: sigstore 106 | spec: 107 | instanceSelector: 108 | matchLabels: 109 | app: sso 110 | realm: 111 | displayName: Sigstore 112 | enabled: true 113 | id: sigstore 114 | realm: sigstore 115 | sslRequired: none 116 | identityProviders: 117 | - alias: github 118 | displayName: GitHub 119 | enabled: true 120 | firstBrokerLoginFlowAlias: first broker login 121 | internalId: github 122 | providerId: github 123 | trustEmail: true 124 | config: 125 | clientId: # add your client ID 126 | clientSecret: # add your client secret 127 | identityProviderMappers: 128 | - name: github 129 | identityProviderAlias: github 130 | identityProviderMapper: hardcoded-attribute-idp-mapper 131 | config: 132 | attribute.value: "true" 133 | syncMode: INHERIT 134 | attribute: emailVerified 135 | ``` 136 | 137 | In the same namespace where Keycloak is deployed (by default `keycloak-system` with TAS), ensure no existing KeycloakRealm with the `metadata.name` specified in your `realm-cr.yaml` file (by default `sigstore` with TAS) is present in your cluster. If it is present, you must first delete it. 138 | **IMPORTANT:** make sure you are okay with deleting your current `sigstore` KeycloakRealm before issuing the command below. 139 | ```shell 140 | $ oc delete keycloakrealm sigstore -n keycloak-system 141 | ``` 142 | 143 | Create the new KeycloakRealm that includes the GitHub Identity Provider using the custom resource file: 144 | ```shell 145 | $ oc create -f realm-cr.yaml -n keycloak-system 146 | ``` 147 | 148 | Note: The Sigstore Public Good Instance uses [dex](https://github.com/dexidp/dex/) for federation, which uses this same [hardcoded configuration](https://github.com/dexidp/dex/blob/80d530d9bf0e38dfb0549c847c92e3c697b0402b/connector/github/github.go#L253) for the `emailVerified` value in the `identityProviderMapper`. 149 | 150 | #### Add the Homepage and Authorization Callback URLs to the GitHub OAuth app 151 | 152 | Obtain the Homepage URL that the GitHub OAuth app requires: 153 | ```shell 154 | echo "$(oc get routes -n keycloak-system keycloak -o jsonpath='https://{.spec.host}')/auth/realms/sigstore/" 155 | ``` 156 | 157 | Obtain the Authorization Callback URL that the GitHub OAuth app requires: 158 | 159 | ```shell 160 | echo "$(oc get routes -n keycloak-system keycloak -o jsonpath='https://{.spec.host}')/auth/realms/sigstore/broker/github/endpoint" 161 | ``` 162 | 163 | Paste these values into the appropriate OAuth app fields, then click `Update Application`: 164 |

165 | 166 |

167 | 168 | 169 | ### Option 2: Add the GitHub Identity Provider to an existing KeycloakRealm via the Keycloak console 170 | 171 | Alternatively, the GitHub Identity Provider and Mapper can be added to an existing KeycloakRealm through the Keycloak console. 172 | 173 | #### Log in to Keycloak console 174 | 175 | You will need to log in to the Keycloak console to complete some steps of this process. Once RHTAS is installed, this can be achieved by locating the URL for the user interface and admin password. 176 | Note: The command below assumes the name of the route is `keycloak`. 177 | 178 | ```shell 179 | $ oc get routes -n keycloak-system keycloak -o jsonpath='https://{.spec.host}' 180 | ``` 181 | 182 | You will need to log in. The username will be `admin`. You can retrieve the password with: 183 | ```shell 184 | $ oc get secret/credential-keycloak -n keycloak-system -o jsonpath='{ .data.ADMIN_PASSWORD }' | base64 -d 185 | ``` 186 | 187 | #### Add the GitHub Identity Provider 188 | 189 | From the Keycloak console, select `Identity Providers` in the lefthand menu bar, then select `Add provider -> GitHub` from the drop down menu. 190 | 191 | You will need to fill in the following fields with these values to add the provider: 192 | 193 | | Field | Value | 194 | | -------------------|------------------------------------------------------------------------------------------------------------------------| 195 | | `Client ID` | the client ID from your GitHub OAuth app's page | 196 | | `Client secret` | the client secret from your GitHub OAuth app's page (note: you may need to generate a new secret to obtain this value) | 197 | | `Enabled` | `ON` | 198 | | `Trust Email` | `ON` | 199 | | `First Login Flow` | `first broker login` | 200 | 201 | #### Add IdentityProviderMapper 202 | 203 | From the Keycloak console, navigate to `Identity Providers` in the lefthand menu bar, and select the provider you have just created: `github`. Select the tab `Mappers` and click the `create` button on the right-hand side to bring up the following page: 204 | 205 |

206 | 207 |

208 | 209 | Set the field values as follows: 210 | 211 | | Field | Value | 212 | | -----------------------|-------------------------------------------------------| 213 | | `Name` | this value can be anything, as it will be overwritten | 214 | | `Sync Mode Override` | `inherit` | 215 | | `Mapper Type` | `Hardcoded Attribute` | 216 | | `User Attribute` | `emailVerified` | 217 | | `User Attribute Value` | `true` | 218 | 219 | 220 | It should look like this: 221 | 222 |

223 | 224 |

225 | 226 | Make sure to hit `save`. 227 | 228 | Note: The Sigstore Public Good Instance uses [dex](https://github.com/dexidp/dex/) for federation, which uses this same [hardcoded configuration](https://github.com/dexidp/dex/blob/80d530d9bf0e38dfb0549c847c92e3c697b0402b/connector/github/github.go#L253) for the `emailVerified` value. 229 | 230 | ### Copy the Redirect URI to your GitHub OAuth App 231 | 232 | From the Keycloak console, navigate to `Identity Providers` in the lefthand menu bar, and select the provider you have just created: `github`. From this page, copy the Redirect URI: 233 | 234 |

235 | 236 |

237 | 238 | Paste the redirect URI value into the OAuth app Authorization Callback URL field. Then paste it into the Homepage URL field, removing `broker/github/endpoint` from the end of the URL. 239 | 240 | The values should look like this, where `CLUSTERVALUE` is the unique value from the URL of your OpenShift cluster: 241 | 242 | |Field | Value| 243 | |----------------------------|------| 244 | | Homepage URL | https://keycloak-keycloak-system.apps.rosa.CLUSTERVALUE.p3.openshiftapps.com/auth/realms/sigstore/ | 245 | | Authorization Callback URL | https://keycloak-keycloak-system.apps.rosa.CLUSTERVALUE.p3.openshiftapps.com/auth/realms/sigstore/broker/github/endpoint | 246 | 247 | 248 | Add these to the appropriate fields marked below: 249 | 250 |

251 | 252 |

253 | 254 | Make sure to click `Update Application`. 255 | 256 | ### Sign the artifact 257 | 258 | Follow the commands listed in [`sign-verify.md`](/sign-verify.md) to ensure that your TAS environment variables are populated, then initialize Cosign and sign the artifact. Another way to ensure that the TAS environment variables are populated is running `source ./tas-env-variables.sh` after setting up RHTAS with `./tas-easy-install.sh`. 259 | 260 | **Troubleshooting:** If you have initialized Cosign previously, you may need to first delete `~/.sigstore` before running the commands below. 261 | 262 | ```shell 263 | $ cosign initialize --mirror=$TUF_URL --root=$TUF_URL/root.json 264 | $ cosign sign -y --fulcio-url=$FULCIO_URL --rekor-url=$REKOR_URL --oidc-issuer=$OIDC_ISSUER_URL $IMAGE 265 | ``` 266 | 267 | On the login page the pops up in the browser, make sure to select the GitHub login option at the bottom. 268 | 269 |

270 | 271 |

272 | -------------------------------------------------------------------------------- /docs/configure-self-signed-cluster.md: -------------------------------------------------------------------------------- 1 | ## Local setup when OpenShift cluster is using a self-signed ingress certificate 2 | 3 | With local development clusters, often the cluster certificate is self-signed rather than issued from a trusted CA. A few steps must be taken to get a working Sigstore stack. 4 | 5 | ### Extract the cluster ingress certificate 6 | 7 | From OpenShift, the default ingress cert is in `-n openshift-ingress` 8 | 9 | ```bash 10 | mkdir clustercert && cd clustercert 11 | oc extract secret/default-ingress-cert -n openshift-ingress 12 | cd ../ 13 | ``` 14 | 15 | Next, run the install script as usual 16 | 17 | ```bash 18 | /path/to/tas-easy-install.sh 19 | ``` 20 | 21 | Once the fulcio-system ns exists, create the ingress-cert secret in the fulcio-system namespace 22 | 23 | ```bash 24 | oc create secret generic -n fulcio-system clustercert --from-file=/path/to/clustercert/tls.crt 25 | ``` 26 | 27 | Finally, patch the fulcio-server deployment in order for 28 | fulcio to trust the ingress certificate for the keycloak OIDC endpoint. 29 | 30 | ```bash 31 | oc patch deployment/fulcio-server -n fulcio-system --patch-file /path/to/securesign/sigstore-ocp/hack/fulcio-patch-self-signed-oidc.yaml 32 | ``` 33 | 34 | Now wait for all jobs to complete, then sign as usual. Refer to [the sign and verify doc](sign-verify.md). 35 | -------------------------------------------------------------------------------- /docs/enable-grafana-monitoring.md: -------------------------------------------------------------------------------- 1 | # Enabling Grafana Monitoring for Trusted-Artifact-Signer 2 | 3 | This guide provides the commands to deploy both the Grafana operator 4 | and a Grafana instance in OpenShift. It also adds a Prometheus Datasource 5 | and configures a dashboard for monitoring Sigstore components. 6 | 7 | Prerequisites 8 | 1. Make sure you have the [oc command-line tool](https://docs.openshift.com/container-platform/4.12/cli_reference/openshift_cli/getting-started-cli.html) installed. 9 | 2. Ensure you are logged into your OpenShift cluster. 10 | 3. Ensure workload monitoring is enabled in your OpenShift cluster. If necessary, either add the line `enableUserWorkload: true` to an already existing `configmap/cluster-monitoring-config` in `-n openshift-monitoring` _or_ create the configmap as below. For more information, refer to [OpenShift documentation](https://docs.openshift.com/container-platform/4.13/monitoring/enabling-monitoring-for-user-defined-projects.html). 11 | 12 | ```yaml 13 | oc create --save-config -f - < Routes in the `trusted-artifact-signer-monitoring` namespace through the OpenShift cluster UI, the default username and password is `sigstore-rh`, please ensure to update this to something more secure. Once logged in, navigate to the dashboard by going to Dashboards -> Browse -> trusted-artifact-signer-monitoring -> Sigstore Monitoring. -------------------------------------------------------------------------------- /docs/keycloak-example.md: -------------------------------------------------------------------------------- 1 | ## Deploy RH SSO Operator and Keycloak resources in OpenShift 2 | 3 | Follow this to deploy a Keycloak instance with the following: 4 | 5 | - A dedicated `Realm` (Recommended) 6 | - A `Client` representing the Sigstore integration 7 | - Valid `Redirect URIs` 8 | - A value of `*` can be used for testing 9 | - 1 or more `Users` 10 | - Email Verified 11 | 12 | The RHSSO Operator and necessary Keycloak resources are deployed with: 13 | 14 | ```shell 15 | oc apply --kustomize keycloak/operator/base 16 | 17 | # wait for this command to succeed before going on to be sure the Keycloak CRDs are registered 18 | oc get keycloaks -A 19 | 20 | oc apply --kustomize keycloak/resources/base 21 | # wait for keycloak-system pods to be running before proceeding 22 | ``` 23 | 24 | ### Add keycloak user and/or credentials 25 | 26 | Refer to the [user custom resource](../keycloak/resources/base/user.yaml) 27 | for how to create a keycloak user. For testing, a user `jdoe@redhat.com` with password: `secure` is created. 28 | 29 | You can access the keycloak route and login as the admin user to set credentials in the keycloak admin console. 30 | To get the keycloak admin credentials, run `oc extract secret/credential-keycloak -n keycloak-system`. 31 | This will create an `ADMIN_PASSWORD` file with which to login. 32 | 33 | The example custom resource defined in [example-user.yaml](../keycloak/resources/example-user.yaml) can be modified and created: 34 | 35 | ```bash 36 | # modify to include user details 37 | oc create --save-config -f keycloak/resources/example-user.yaml -n keycloak-system 38 | ``` 39 | -------------------------------------------------------------------------------- /docs/quick-start-with-keycloak.md: -------------------------------------------------------------------------------- 1 | ## Quick Start with Keycloak OIDC 2 | 3 | No-Fail steps to get a working sigstore stack with OpenShift 4 | Note: [This script](../tas-easy-install.sh) will alternatively automate the following workflow. It will create and configure RHSSO and the Sigstore stack. It requires a connection to OpenShift with cluster-admin privileges. 5 | 6 | 1. Install RHSSO Operator and deploy Sigstore Keycloak 7 | 8 | ```shell 9 | oc apply --kustomize keycloak/operator/base 10 | # wait until the keycloak API is ready, check w/ non-erroring 'oc get keycloaks' 11 | oc apply --kustomize keycloak/resources/base 12 | # wait until keycloak-system pods are healthy/running 13 | ``` 14 | 15 | 2. Create the fulcio signing keys & root cert, and then a secret in the fulcio-system namespace. Replace in the `oc` command to match the password for decrypting the signing key. The script creates the keys in `./keys-cert` folder. 16 | 17 | ```shell 18 | oc create ns fulcio-system 19 | ./fulcio-create-root-ca-openssl.sh 20 | oc -n fulcio-system create secret generic fulcio-secret-rh --from-file=private=./keys-cert/file_ca_key.pem --from-file=public=./keys-cert/file_ca_pub.pem --from-file=cert=./keys-cert/fulcio-root.pem --from-literal=password= --dry-run=client -o yaml | oc apply -f- 21 | ``` 22 | 23 | 3. Create the rekor signing keys, and then a secret in the rekor-system namespace. The script creates the key in `./keys-cert` folder. 24 | 25 | ```shell 26 | oc create ns rekor-system 27 | ./rekor-create-signer-key.sh 28 | oc -n rekor-system create secret generic rekor-private-key --from-file=private=./keys-cert/rekor_key.pem --dry-run=client -o yaml | oc apply -f- 29 | ``` 30 | 31 | 3. Run the following: 32 | 33 | ```shell 34 | OPENSHIFT_APPS_SUBDOMAIN=apps.$(oc get dns cluster -o jsonpath='{ .spec.baseDomain }') envsubst < examples/values-sigstore-openshift.yaml | helm upgrade -i trusted-artifact-signer --debug charts/trusted-artifact-signer -n trusted-artifact-signer --create-namespace --values - 35 | ``` 36 | 37 | A good way to tell if things are progressing well is to watch `oc get jobs -A` and when the tuf-system job is complete, 38 | things should be ready. 39 | 40 | Once complete, move to the [Sign & Verify document](sign-verify.md) to test the Sigstore stack. 41 | -------------------------------------------------------------------------------- /docs/requirements-keys-certs.md: -------------------------------------------------------------------------------- 1 | ## Fulcio root key injection 2 | 3 | Utilize the following commands and configurations to inject Fulcio root secret: 4 | 5 | First, generate a root key. 6 | Open [fulcio-create-CA script](../fulcio-create-root-ca-openssl.sh) to check out the commands before running it. 7 | The `openssl` commands are interactive. 8 | 9 | ```shell 10 | ./fulcio-create-root-ca-openssl.sh 11 | ``` 12 | 13 | The command creates keys and cert in `./keys-cert` folder. 14 | Either create a secret in the fulcio-system namespace with: 15 | 16 | ```bash 17 | # Note replace with value of password to decrypt signing key created above. 18 | # if necessary, 'oc create ns fulcio-system' 19 | 20 | oc -n fulcio-system create secret generic fulcio-secret-rh --from-file=private=./keys-cert/file_ca_key.pem --from-file=public=./keys-cert/file_ca_pub.pem --from-file=cert=./keys-cert/fulcio-root.pem --from-literal=password= --dry-run=client -o yaml | oc apply -f- 21 | ``` 22 | 23 | Or, add the following to an overriding Values file injecting the public key, private key, and password used for the private key: 24 | 25 | ```yaml 26 | configs: 27 | fulcio: 28 | server: 29 | secret: 30 | name: "fulcio-secret-rh" 31 | password: "" 32 | public_key_file: "keys-cert/file_ca_pub.pem" 33 | private_key_file: "keys-cert/file_ca_key.pem" 34 | root_cert_file: "keys-cert/fulcio-root.pem" 35 | ``` 36 | 37 | ## Rekor Signer Key 38 | 39 | Open [rekor create signer script](../rekor-create-signer-key.sh) to check out the commands before running it. 40 | Generate a signer key: 41 | 42 | ```shell 43 | ./rekor-create-signer-key.sh 44 | ``` 45 | 46 | Either create a secret in the rekor-system namespace with: 47 | 48 | ```bash 49 | # if necessary, 'oc create ns rekor-system' 50 | oc -n rekor-system create secret generic rekor-private-key --from-file=private=rekor_key.pem --dry-run=client -o yaml | oc apply -f- 51 | ``` 52 | 53 | Or, add the following to override the values file injecting the signer key: 54 | 55 | ```yaml 56 | configs: 57 | rekor: 58 | signer: 59 | secret: 60 | name: rekor-private-key 61 | private_key_file: "keys-cert/rekor_key.pem" 62 | ``` 63 | 64 | NOTE: The name of the generated secret, `rekor-private-key` can be customized. 65 | Ensure the naming is consistent throughout each of the customization options 66 | -------------------------------------------------------------------------------- /docs/sign-verify.md: -------------------------------------------------------------------------------- 1 | ## Signing a Container From the Local System 2 | 3 | Utilize the following steps to sign a container that has been published to an OCI registry, with the cosign client running on your local system and the RHTAS stack running in an OpenShift cluster as documented [here](quick-start-with-keycloak.md). 4 | 5 | 1. Export the following environment variables substituting `base_hostname` with the value used as part of the provisioning 6 | 7 | The OpenShift subdomain can be obtained from 8 | 9 | ```shell 10 | OPENSHIFT_APPS_SUBDOMAIN=apps.$(oc get dns cluster -o jsonpath='{ .spec.baseDomain }') 11 | ``` 12 | 13 | The following assumes there exists a Keycloak `keycloak` in namespace `keycloak-system` 14 | 15 | ```shell 16 | export OIDC_AUTHENTICATION_REALM=trusted-artifact-signer 17 | export COSIGN_OIDC_CLIENT_ID=trusted-artifact-signer 18 | export COSIGN_FULCIO_URL=https://fulcio.$OPENSHIFT_APPS_SUBDOMAIN 19 | export COSIGN_OIDC_ISSUER=https://keycloak-keycloak-system.$OPENSHIFT_APPS_SUBDOMAIN/auth/realms/$OIDC_AUTHENTICATION_REALM 20 | export COSIGN_CERTIFICATE_OIDC_ISSUER=$COSIGN_OIDC_ISSUER 21 | export COSIGN_REKOR_URL=https://rekor.$OPENSHIFT_APPS_SUBDOMAIN 22 | export TUF_URL=https://tuf.$OPENSHIFT_APPS_SUBDOMAIN 23 | export COSIGN_MIRROR=$TUF_URL 24 | export COSIGN_ROOT=$TUF_URL/root.json 25 | export COSIGN_YES="true" 26 | ``` 27 | 28 | 2. Initialize the TUF roots 29 | 30 | If you are using a cluster with self-signed certificates, you will first need to download the `kube-root-ca.crt` from the cluster and add it to your 31 | local system's trusted certificate store. On Fedora/RHEL, this will look like: 32 | 33 | ```shell 34 | oc extract cm/kube-root-ca.crt -n openshift-ingress-operator 35 | mv ca.crt kube-root-ca.crt 36 | sudo mv kube-root-ca.crt /etc/pki/ca-trust/source/anchors/ 37 | sudo update-ca-trust extract 38 | ``` 39 | On other systems, the last two commands may differ. 40 | 41 | Then you can initialize cosign, or start here if you are not using a cluster with self-signed certificates. 42 | Note: If you have used `cosign` previously, you may need to first delete the `~/.sigstore` directory 43 | 44 | ```shell 45 | cosign initialize 46 | ``` 47 | 48 | 3. Sign the desired container 49 | 50 | ```shell 51 | cosign sign -y 52 | ``` 53 | 54 | Authenticate with the OIDC provider (Keycloak, here) using the desired credentials. 55 | 56 | 4. Verify the signed image 57 | 58 | This example that verifies an image signed with email identity `sigstore-user@email.com` and issuer `https://keycloak-keycloak.apps.com/auth/realms/trusted-artifact-signer`. 59 | 60 | ```shell 61 | cosign verify \ 62 | --certificate-identity-regexp sigstore-user \ 63 | 64 | ``` 65 | 66 | If the signature verification did not result in an error, the deployment of Sigstore was successful! 67 | 68 | ## Signing a Container Using the Cosign pod. 69 | 70 | Follow the steps below to sign an artifact using the cosign pod running in the cosign namespace. 71 | 72 | The `OPENSHIFT_APPS_SUBDOMAIN` environmental variable should be specified in the trusted-artifact-signer chart, 73 | with `global.appsSubdomain`. If it isn't, you'll need to set that variable in the cosign 74 | deployment pod specification. 75 | 76 | 1. Get the name of the pod. 77 | 78 | ``` 79 | oc get pods -n cosign 80 | ``` 81 | 82 | 2. Initialize the TUF roots. 83 | 84 | ```shell 85 | oc exec -n cosign -- /bin/sh -c 'cosign initialize' 86 | ``` 87 | 88 | 3. Login to the image repository of your choice using cosign. 89 | ``` 90 | oc exec -n cosign -- /bin/sh -c 'cosign login -u -p ' 91 | ``` 92 | 93 | 4. Retrieve `id_token` from the OIDC provider. 94 | ``` 95 | curl -X POST -H "Content-Type: application/x-www-form-urlencoded" \ 96 | -d "client_id=" \ 97 | -d "username=" \ 98 | -d "password=" \ 99 | -d "grant_type=password" \ 100 | -d "scope=openid" \ 101 | \$COSIGN_OIDC_ISSUER/protocol/openid-connect/token 102 | ``` 103 | 104 | 5. Sign the container. 105 | ``` 106 | oc exec -n cosign -- /bin/sh -c 'cosign sign -y --identity-token= ' 107 | ``` 108 | 109 | 6. Verify the signed image. Again, this example assumes `Keycloak` is the OIDC provider. 110 | 111 | ```shell 112 | oc exec -n cosign -- /bin/sh -c 'cosign verify --certificate-identity-regexp sigstore-user ' 113 | ``` 114 | 115 | If the signature verification did not result in an error, the deployment of Sigstore was successful! 116 | 117 | ## Signing an image on Windows using PowerShell 118 | 119 | Use the following steps to sign a container that has been published to an OCI registry, on Windows using `PowerShell`. 120 | 121 | 1. Define the following environment variables 122 | ``` 123 | $OPENSHIFT_APPS_SUBDOMAIN = "apps." + $(oc get dns cluster -o jsonpath='{.spec.baseDomain}') 124 | $OIDC_AUTHENTICATION_REALM = "trusted-artifact-signer" 125 | $COSIGN_OIDC_CLIENT_ID = "trusted-artifact-signer" 126 | $FULCIO_URL = "https://fulcio." + $OPENSHIFT_APPS_SUBDOMAIN 127 | $OIDC_ISSUER_URL = "https://keycloak-keycloak-system." + $OPENSHIFT_APPS_SUBDOMAIN + "/auth/realms/" + $OIDC_AUTHENTICATION_REALM 128 | $REKOR_URL = "https://rekor." + $OPENSHIFT_APPS_SUBDOMAIN 129 | $TUF_URL = "https://tuf." + $OPENSHIFT_APPS_SUBDOMAIN 130 | ``` 131 | 2. Initialize the TUF roots 132 | 133 | Note: If you have used `cosign` previously, you may need to first delete the `C:\Users\\.sigstore` directory 134 | 135 | ``` 136 | cosign initialize --mirror=$TUF_URL --root=$TUF_URL/root.json 137 | ``` 138 | 139 | 3. Sign the desired container 140 | 141 | 3.1. Signing with Upstream's Public goods instance 142 | 143 | ``` 144 | cosign sign -y --fulcio-url=$FULCIO_URL --rekor-url=$REKOR_URL 145 | ``` 146 | 147 | 3.2. Signing with keycloak 148 | 149 | Retrieve the `id_token` from the keycloak instance 150 | 151 | ``` 152 | $body = @{ 153 | client_id = "" 154 | username = "" 155 | password = "" 156 | grant_type = "password" 157 | scope = "openid" 158 | } 159 | 160 | $id_token = (Invoke-WebRequest -Uri "$OIDC_ISSUER_URL/protocol/openid-connect/token" -Method Post -Body $body -ContentType "application/x-www-form-urlencoded" -UseBasicParsing).Content | ConvertFrom-Json | Select-Object -ExpandProperty id_token 161 | ``` 162 | 163 | Sign the container 164 | 165 | ``` 166 | cosign sign -y --fulcio-url=$FULCIO_URL --rekor-url=$REKOR_URL --oidc-issuer=$OIDC_ISSUER_URL --identity-token=$id_token 167 | ``` 168 | 169 | 4. Verify the desired container 170 | 171 | ``` 172 | cosign verify --rekor-url=$REKOR_URL --certificate-identity-regexp --certificate-oidc-issuer-regexp 173 | ``` 174 | -------------------------------------------------------------------------------- /examples/values-kind-byodb.yaml: -------------------------------------------------------------------------------- 1 | # With this example, you can see how to deploy Sigstore instance that is internal and can be use only within the cluster. 2 | # To sign your containers, you can use pre-deployed container in `cosign` namespace (see https://github.com/securesign/sigstore-ocp/blob/main/sign-verify.md#signing-a-container-using-the-cosign-pod). 3 | # It is expected that there is a secret with the fulcio root & signing keys 4 | # named 'fulcio-secret-rh' in namespace 'fulcio-system' and a secret 'rekor-private-key' 5 | # with rekor signing keys in the 'rekor-system' namespace. 6 | # secret names must match secret names in scaffold.tuf, that default to 7 | # 'fulcio-secret-rh' and 'rekor-private-key' 8 | # For root & key requirements, see ../requirements-keys-certs.md 9 | configs: 10 | clientserver: 11 | consoleDownload: false 12 | route: false 13 | cosign_deploy: 14 | enabled: true 15 | fulcio: 16 | clusterMonitoring: 17 | enabled: false 18 | namespace_create: false 19 | rekor: 20 | clusterMonitoring: 21 | enabled: false 22 | namespace_create: false 23 | rekorui: 24 | route: false 25 | 26 | # github.com/sigstore/helm-charts/charts 27 | scaffold: 28 | trillian: 29 | # Trillian allows for the capabilities to bring your own database. This is 30 | # useful for production deployments where you want to use a managed database 31 | # service. 32 | mysql: 33 | enabled: false 34 | port: 3306 35 | # The hostname of the database server. This can be a hostname, IP, or Kubernetes service address. 36 | hostname: "" 37 | auth: 38 | # Existing secret must contain the username, password, and root password. This is useful when using external secrets such as vault. 39 | # values in the secret must be mysql-password, mysql-root-password, and mysql-username. The expectation is that the database will be named trillian. 40 | existingSecret: "" 41 | # If you do not have an existing secret, you can use the following to create a new secret. Do not store these in public source control as someone will be able to access your database. 42 | username: "" 43 | password: "" 44 | rootPassword: "" 45 | fulcio: 46 | server: 47 | ingress: 48 | enabled: false 49 | http: 50 | enabled: false 51 | config: 52 | contents: 53 | OIDCIssuers: 54 | # https://../auth/realms/trusted-artifact-signer 55 | ? http://keycloak-internal.keycloak-system.svc/auth/realms/trusted-artifact-signer 56 | : IssuerURL: http://keycloak-internal.keycloak-system.svc/auth/realms/trusted-artifact-signer 57 | ClientID: trusted-artifact-signer 58 | Type: email 59 | rekor: 60 | server: 61 | ingress: 62 | enabled: false 63 | http: 64 | enabled: false 65 | tuf: 66 | ingress: 67 | create: false 68 | -------------------------------------------------------------------------------- /examples/values-kind-sigstore.yaml: -------------------------------------------------------------------------------- 1 | # With this example, you can see how to deploy Sigstore instance that is internal and can be use only within the cluster. 2 | # To sign your containers, you can use pre-deployed container in `cosign` namespace (see https://github.com/securesign/sigstore-ocp/blob/main/sign-verify.md#signing-a-container-using-the-cosign-pod). 3 | # It is expected that there is a secret with the fulcio root & signing keys 4 | # named 'fulcio-secret-rh' in namespace 'fulcio-system' and a secret 'rekor-private-key' 5 | # with rekor signing keys in the 'rekor-system' namespace. 6 | # secret names must match secret names in scaffold.tuf, that default to 7 | # 'fulcio-secret-rh' and 'rekor-private-key' 8 | # For root & key requirements, see ../requirements-keys-certs.md 9 | configs: 10 | clientserver: 11 | consoleDownload: false 12 | route: false 13 | cosign_deploy: 14 | enabled: true 15 | fulcio: 16 | clusterMonitoring: 17 | enabled: false 18 | namespace_create: false 19 | rekor: 20 | clusterMonitoring: 21 | enabled: false 22 | namespace_create: false 23 | rekorui: 24 | route: false 25 | ingress: false 26 | 27 | # github.com/sigstore/helm-charts/charts 28 | scaffold: 29 | fulcio: 30 | server: 31 | ingress: 32 | enabled: false 33 | http: 34 | enabled: false 35 | config: 36 | contents: 37 | OIDCIssuers: 38 | ? http://keycloak-internal.keycloak-system.svc/auth/realms/trusted-artifact-signer 39 | : IssuerURL: http://keycloak-internal.keycloak-system.svc/auth/realms/trusted-artifact-signer 40 | ClientID: trusted-artifact-signer 41 | Type: email 42 | rekor: 43 | server: 44 | ingress: 45 | enabled: false 46 | http: 47 | enabled: false 48 | tuf: 49 | ingress: 50 | create: false 51 | -------------------------------------------------------------------------------- /examples/values-sigstore-openshift-byo-fulcio-root.yaml: -------------------------------------------------------------------------------- 1 | # With this example, the user provides the fulcio signing key and root certificate content, 2 | # either from files with path relative to this file, or by pasting contents below. 3 | # It assumes the secret 'rekor-private-key' exists in rekor-system namespace. 4 | # For fulcio cert & key requirements, see ../requirements-keys-certs.md 5 | # Note: User must substitute for $OPENSHIFT_APPS_SUBDOMAIN below. 6 | # Base domain is results of "oc get dns cluster -o jsonpath='{ .spec.baseDomain }'" 7 | --- 8 | global: 9 | appsSubdomain: $OPENSHIFT_APPS_SUBDOMAIN 10 | configs: 11 | cosign_deploy: 12 | enabled: true 13 | rekor: 14 | namespace_create: false 15 | rekorui: 16 | subdomain: rekorui.$OPENSHIFT_APPS_SUBDOMAIN 17 | fulcio: 18 | # -- whether to create the 'fulcio-system' namespace 19 | # When providing the fulcio server.secret, the ns already exists 20 | create: false 21 | server: 22 | secret: 23 | # secret name must match fulcio secret name in scaffold.tuf 24 | # that defaults to 'fulcio-secret-rh' 25 | name: fulcio-secret-rh 26 | password: "CHANGEME" 27 | # must provide 1 of each, key_file path or key contents 28 | #public_key_file: "keys-cert/file_ca_pub.pem" 29 | #private_key_file: "keys-cert/file_ca_key.pem" 30 | #root_cert_file: "keys-cert/fulcio-root.pem" 31 | public_key: | 32 | -----BEGIN PUBLIC KEY----- 33 | paste contents here 34 | -----END PUBLIC KEY----- 35 | private_key: | 36 | -----BEGIN EC PRIVATE KEY----- 37 | paste contents here 38 | -----END EC PRIVATE KEY----- 39 | root_cert: | 40 | -----BEGIN CERTIFICATE----- 41 | paste contents here 42 | -----END CERTIFICATE----- 43 | rekorui: 44 | subdomain: rekorui.$OPENSHIFT_APPS_SUBDOMAIN 45 | 46 | # github.com/sigstore/helm-charts/charts 47 | scaffold: 48 | fulcio: 49 | server: 50 | ingress: 51 | http: 52 | hosts: 53 | - host: fulcio.$OPENSHIFT_APPS_SUBDOMAIN 54 | path: / 55 | config: 56 | contents: 57 | OIDCIssuers: 58 | # https://../auth/realms/trusted-artifact-signer 59 | ? https://keycloak-keycloak-system.$OPENSHIFT_APPS_SUBDOMAIN/auth/realms/trusted-artifact-signer 60 | : IssuerURL: https://keycloak-keycloak-system.$OPENSHIFT_APPS_SUBDOMAIN/auth/realms/trusted-artifact-signer 61 | ClientID: trusted-artifact-signer 62 | Type: email 63 | rekor: 64 | server: 65 | ingress: 66 | hosts: 67 | - host: rekor.$OPENSHIFT_APPS_SUBDOMAIN 68 | path: / 69 | tuf: 70 | ingress: 71 | http: 72 | hosts: 73 | - host: tuf.$OPENSHIFT_APPS_SUBDOMAIN 74 | path: / 75 | 76 | -------------------------------------------------------------------------------- /examples/values-sigstore-openshift-byo-rekor-key.yaml: -------------------------------------------------------------------------------- 1 | # With this example, the user provides the rekor private signing key content, 2 | # either from file path relative to this file, or by pasting its contents below. 3 | # It's assumed the secret 'fulcio-secret-rh' exists already in 'fulcio-system' namespace. 4 | # For rekor key requirements, see ../requirements-keys-certs.md 5 | # Note: User must substitute for $OPENSHIFT_APPS_SUBDOMAIN below. 6 | # Base domain is results of "oc get dns cluster -o jsonpath='{ .spec.baseDomain }'" 7 | --- 8 | global: 9 | appsSubdomain: $OPENSHIFT_APPS_SUBDOMAIN 10 | configs: 11 | cosign_deploy: 12 | enabled: true 13 | fulcio: 14 | namespace_create: false 15 | rekorui: 16 | subdomain: rekorui.$OPENSHIFT_APPS_SUBDOMAIN 17 | 18 | rekor: 19 | # -- whether to create the 'rekor-system' namespace 20 | # When providing the rekor signer.secret, the ns already exists 21 | signer: 22 | secret: 23 | # must provide 1 of each, key_file path or key contents 24 | # name must match rekor signer secretName in scaffold.rekor.server 25 | name: rekor-private-key 26 | #private_key_file: "keys-cert/rekor_key.pem" 27 | private_key: | 28 | -----BEGIN EC PRIVATE KEY----- 29 | paste contents here 30 | -----END EC PRIVATE KEY----- 31 | rekorui: 32 | subdomain: rekorui.$OPENSHIFT_APPS_SUBDOMAIN 33 | 34 | # github.com/sigstore/helm-charts/charts 35 | scaffold: 36 | fulcio: 37 | server: 38 | ingress: 39 | http: 40 | hosts: 41 | - host: fulcio.$OPENSHIFT_APPS_SUBDOMAIN 42 | path: / 43 | config: 44 | contents: 45 | OIDCIssuers: 46 | # https://../auth/realms/trusted-artifact-signer 47 | ? https://keycloak-keycloak-system.$OPENSHIFT_APPS_SUBDOMAIN/auth/realms/trusted-artifact-signer 48 | : IssuerURL: https://keycloak-keycloak-system.$OPENSHIFT_APPS_SUBDOMAIN/auth/realms/trusted-artifact-signer 49 | ClientID: trusted-artifact-signer 50 | Type: email 51 | rekor: 52 | server: 53 | # when providing contents of secret with configs.rekor.signer 54 | # the signer sections must also be provided here 55 | signer: /key/private 56 | signerFileSecretOptions: 57 | secretName: rekor-private-key 58 | secretMountPath: /key 59 | secretMountSubPath: private 60 | privateKeySecretKey: private 61 | ingress: 62 | hosts: 63 | - host: rekor.$OPENSHIFT_APPS_SUBDOMAIN 64 | path: / 65 | tuf: 66 | ingress: 67 | http: 68 | hosts: 69 | - host: tuf.$OPENSHIFT_APPS_SUBDOMAIN 70 | path: / 71 | 72 | -------------------------------------------------------------------------------- /examples/values-sigstore-openshift.yaml: -------------------------------------------------------------------------------- 1 | # With this example, it is expected that there is a secret with the fulcio root & signing keys 2 | # named 'fulcio-secret-rh' in namespace 'fulcio-system' and a secret 'rekor-private-key' 3 | # with rekor signing keys in the 'rekor-system' namespace. 4 | # secret names must match secret names in scaffold.tuf, that default to 5 | # 'fulcio-secret-rh' and 'rekor-private-key' 6 | # For root & key requirements, see ../requirements-keys-certs.md 7 | # Note: User must substitute for $OPENSHIFT_APPS_SUBDOMAIN below. 8 | # Base domain is results of "oc get dns cluster -o jsonpath='{ .spec.baseDomain }'" 9 | --- 10 | global: 11 | appsSubdomain: $OPENSHIFT_APPS_SUBDOMAIN 12 | configs: 13 | cosign_deploy: 14 | enabled: true 15 | fulcio: 16 | namespace_create: false 17 | rekor: 18 | namespace_create: false 19 | rekorui: 20 | subdomain: rekorui.$OPENSHIFT_APPS_SUBDOMAIN 21 | 22 | # github.com/sigstore/helm-charts/charts 23 | scaffold: 24 | fulcio: 25 | server: 26 | ingress: 27 | http: 28 | hosts: 29 | - host: fulcio.$OPENSHIFT_APPS_SUBDOMAIN 30 | path: / 31 | config: 32 | contents: 33 | OIDCIssuers: 34 | # https://../auth/realms/trusted-artifact-signer 35 | ? https://keycloak-keycloak-system.$OPENSHIFT_APPS_SUBDOMAIN/auth/realms/trusted-artifact-signer 36 | : IssuerURL: https://keycloak-keycloak-system.$OPENSHIFT_APPS_SUBDOMAIN/auth/realms/trusted-artifact-signer 37 | ClientID: trusted-artifact-signer 38 | Type: email 39 | rekor: 40 | server: 41 | ingress: 42 | hosts: 43 | - host: rekor.$OPENSHIFT_APPS_SUBDOMAIN 44 | path: / 45 | tuf: 46 | ingress: 47 | http: 48 | hosts: 49 | - host: tuf.$OPENSHIFT_APPS_SUBDOMAIN 50 | path: / 51 | -------------------------------------------------------------------------------- /examples/values.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | global: 3 | appsSubdomain: $OPENSHIFT_APPS_SUBDOMAIN 4 | configs: 5 | cosign_deploy: 6 | enabled: true 7 | fulcio: 8 | namespace_create: false 9 | rekor: 10 | namespace_create: false 11 | # (OPTIONAL) when providing contents of secret with configs.rekor.server.signer 12 | signer: 13 | secret: 14 | # must provide 1 of each, key_file path or key contents 15 | # name must match rekor signer secretName in scaffold.rekor.server 16 | name: "" 17 | #private_key_file: "keys-cert/rekor_key.pem" 18 | private_key: "" 19 | rekorui: 20 | subdomain: rekorui.$OPENSHIFT_APPS_SUBDOMAIN 21 | 22 | # github.com/sigstore/helm-charts/charts 23 | scaffold: 24 | # Trillian allows for the capabilities to bring your own database. This is 25 | # useful for production deployments where you want to use a managed database 26 | # service. 27 | trillian: 28 | mysql: 29 | enabled: true 30 | port: 3306 31 | # The hostname of the database server. This can be a hostname, IP, or Kubernetes service address. 32 | hostname: "" 33 | auth: 34 | # Existing secret must contain the username, password, and root password. This is useful when using external secrets such as vault. 35 | # values in the secret must be mysql-password, mysql-root-password, and mysql-username. The expectation is that the database will be named trillian. 36 | existingSecret: "" 37 | # If you do not have an existing secret, you can use the following to create a new secret. Do not store these in public source control as someone will be able to access your database. 38 | username: "mysql" 39 | password: "" 40 | rootPassword: "" 41 | fulcio: 42 | server: 43 | ingress: 44 | http: 45 | hosts: 46 | - host: fulcio.$OPENSHIFT_APPS_SUBDOMAIN 47 | path: / 48 | config: 49 | contents: 50 | OIDCIssuers: 51 | # https://../auth/realms/trusted-artifact-signer 52 | ? https://keycloak-keycloak-system.$OPENSHIFT_APPS_SUBDOMAIN/auth/realms/trusted-artifact-signer 53 | : IssuerURL: https://keycloak-keycloak-system.$OPENSHIFT_APPS_SUBDOMAIN/auth/realms/trusted-artifact-signer 54 | ClientID: trusted-artifact-signer 55 | Type: email 56 | rekor: 57 | server: 58 | ingress: 59 | hosts: 60 | - host: rekor.$OPENSHIFT_APPS_SUBDOMAIN 61 | path: / 62 | tuf: 63 | ingress: 64 | http: 65 | hosts: 66 | - host: tuf.$OPENSHIFT_APPS_SUBDOMAIN 67 | path: / 68 | -------------------------------------------------------------------------------- /fulcio-create-root-ca-openssl.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | mkdir -p keys-cert 4 | 5 | pushd keys-cert > /dev/null 6 | 7 | cat << EOF > ca.cfg 8 | [req] 9 | default_bits = 2048 10 | prompt = yes 11 | x509_extensions = v3_ca 12 | distinguished_name = req_distinguished_name 13 | 14 | [ req_distinguished_name ] 15 | countryName = Country Name (2 letter code) 16 | countryName_min = 2 17 | countryName_max = 2 18 | stateOrProvinceName = State or Province Name (full name) 19 | localityName = Locality Name (eg, city) 20 | 0.organizationName = Organization Name (eg, company) 21 | organizationalUnitName = Organizational Unit Name (eg, section) 22 | commonName = Common Name (eg, fully qualified host name) 23 | commonName_max = 64 24 | emailAddress = Email Address 25 | emailAddress_max = 64 26 | 27 | [v3_ca] 28 | basicConstraints = critical, CA:TRUE 29 | keyUsage = keyCertSign 30 | subjectKeyIdentifier = hash 31 | authorityKeyIdentifier = keyid:always,issuer:always 32 | EOF 33 | 34 | 35 | openssl ecparam -genkey -name prime256v1 -noout -out unenc.key 36 | openssl ec -in unenc.key -out file_ca_key.pem -des3 37 | openssl ec -in file_ca_key.pem -pubout -out file_ca_pub.pem 38 | openssl req -new -x509 -days 365 -key file_ca_key.pem -out fulcio-root.pem -config ca.cfg 39 | 40 | rm unenc.key 41 | 42 | popd > /dev/null 43 | -------------------------------------------------------------------------------- /grafana/dashboards/datasource.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: integreatly.org/v1alpha1 2 | kind: GrafanaDataSource 3 | metadata: 4 | name: prometheus-grafana 5 | namespace: trusted-artifact-signer-monitoring 6 | spec: 7 | name: prometheus-grafana.yaml 8 | datasources: 9 | - access: proxy 10 | editable: true 11 | isDefault: true 12 | jsonData: 13 | httpHeaderName1: 'Authorization' 14 | timeInterval: 5s 15 | tlsSkipVerify: true 16 | name: prometheus 17 | secureJsonData: 18 | # Update bearer token to match your environment 19 | httpHeaderValue1: 'Bearer ${BEARER_TOKEN}' 20 | type: prometheus 21 | url: 'https://thanos-querier.openshift-monitoring.svc.cluster.local:9091' 22 | --- 23 | apiVersion: integreatly.org/v1alpha1 24 | kind: GrafanaDataSource 25 | metadata: 26 | name: trillian-grafana 27 | namespace: trusted-artifact-signer-monitoring 28 | spec: 29 | name: MySQL-datasource.yaml 30 | datasources: 31 | - name: MySQL 32 | type: mysql 33 | access: proxy 34 | url: trillian-mysql.trillian-system.svc.cluster.local:3306 35 | user: ${MYSQL_USER} 36 | secureJsonData: 37 | password: ${MYSQL_PASSWORD} 38 | database: ${MYSQL_DATABASE} 39 | jsonData: 40 | timeInterval: "5s" 41 | tlsSkipVerify: true 42 | 43 | -------------------------------------------------------------------------------- /grafana/instance/instance.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: integreatly.org/v1alpha1 2 | kind: Grafana 3 | metadata: 4 | name: trusted-artifact-signer-monitoring 5 | namespace: trusted-artifact-signer-monitoring 6 | spec: 7 | # TODO: this hard-coded image version is necessary until the currently available version 8 | # of grafana operator from OperatorHub (v4.7.1) pulls in a later version of grafana 9 | baseImage: 'docker.io/grafana/grafana:10.1.2' 10 | ingress: 11 | enabled: true 12 | config: 13 | auth: 14 | disable_signout_menu: true 15 | auth.anonymous: 16 | enabled: true 17 | log: 18 | level: warn 19 | mode: console 20 | security: 21 | admin_password: "sigstore-rh" # Make sure to update to something more secure 22 | admin_user: "sigstore-rh" # Make sure to update to something more secure 23 | dashboardLabelSelector: 24 | - matchExpressions: 25 | - key: app 26 | operator: In 27 | values: 28 | - grafana -------------------------------------------------------------------------------- /grafana/instance/kustomization.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kustomize.config.k8s.io/v1beta1 2 | kind: Kustomization 3 | 4 | resources: 5 | - instance.yaml -------------------------------------------------------------------------------- /grafana/operator/kustomization.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kustomize.config.k8s.io/v1beta1 2 | kind: Kustomization 3 | 4 | resources: 5 | - operator.yaml 6 | -------------------------------------------------------------------------------- /grafana/operator/operator.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: operators.coreos.com/v1 3 | kind: OperatorGroup 4 | metadata: 5 | name: operatorgroup 6 | namespace: trusted-artifact-signer-monitoring 7 | spec: 8 | targetNamespaces: 9 | - trusted-artifact-signer-monitoring 10 | --- 11 | apiVersion: operators.coreos.com/v1alpha1 12 | kind: Subscription 13 | metadata: 14 | name: grafana-operator 15 | namespace: trusted-artifact-signer-monitoring 16 | spec: 17 | channel: v4 18 | installPlanApproval: Automatic 19 | name: grafana-operator 20 | source: community-operators 21 | sourceNamespace: openshift-marketplace 22 | startingCSV: grafana-operator.v4.10.1 23 | -------------------------------------------------------------------------------- /grafana/resources/kustomization.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kustomize.config.k8s.io/v1beta1 2 | kind: Kustomization 3 | 4 | resources: 5 | - rolebinding.yaml 6 | - token.yaml 7 | -------------------------------------------------------------------------------- /grafana/resources/rolebinding.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRoleBinding 3 | metadata: 4 | name: grafana-cluster-monitoring-view 5 | roleRef: 6 | apiGroup: rbac.authorization.k8s.io 7 | kind: ClusterRole 8 | name: cluster-monitoring-view 9 | subjects: 10 | - kind: ServiceAccount 11 | name: grafana-serviceaccount 12 | namespace: trusted-artifact-signer-monitoring 13 | -------------------------------------------------------------------------------- /grafana/resources/token.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Secret 3 | metadata: 4 | name: grafana-sa-token 5 | namespace: trusted-artifact-signer-monitoring 6 | annotations: 7 | kubernetes.io/service-account.name: grafana-serviceaccount 8 | type: kubernetes.io/service-account-token 9 | -------------------------------------------------------------------------------- /hack/fulcio-patch-self-signed-oidc.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | annotations: 5 | name: fulcio-server 6 | namespace: fulcio-system 7 | spec: 8 | template: 9 | spec: 10 | containers: 11 | - args: 12 | - serve 13 | - --port=5555 14 | - --grpc-port=5554 15 | - --ca=fileca 16 | - --fileca-key 17 | - /var/run/fulcio-secrets/key.pem 18 | - --fileca-cert 19 | - /var/run/fulcio-secrets/cert.pem 20 | - --fileca-key-passwd 21 | - $(PASSWORD) 22 | - --ct-log-url=http://ctlog.ctlog-system.svc/sigstorescaffolding 23 | env: 24 | - name: SSL_CERT_DIR 25 | value: /var/run/clustercert 26 | - name: PASSWORD 27 | valueFrom: 28 | secretKeyRef: 29 | key: password 30 | name: fulcio-secret-rh 31 | name: fulcio-server 32 | volumeMounts: 33 | - mountPath: /etc/fulcio-config 34 | name: fulcio-config 35 | - mountPath: /var/run/fulcio 36 | name: oidc-info 37 | - mountPath: /var/run/fulcio-secrets 38 | name: fulcio-cert 39 | readOnly: true 40 | - mountPath: /var/run/clustercert 41 | name: clustercert 42 | readOnly: true 43 | volumes: 44 | - configMap: 45 | defaultMode: 420 46 | name: fulcio-server-config 47 | name: fulcio-config 48 | - name: oidc-info 49 | projected: 50 | defaultMode: 420 51 | sources: 52 | - configMap: 53 | items: 54 | - key: ca.crt 55 | mode: 438 56 | path: ca.crt 57 | name: kube-root-ca.crt 58 | - name: fulcio-cert 59 | secret: 60 | defaultMode: 420 61 | items: 62 | - key: private 63 | path: key.pem 64 | - key: cert 65 | path: cert.pem 66 | secretName: fulcio-secret-rh 67 | - name: clustercert 68 | secret: 69 | defaultMode: 420 70 | items: 71 | - key: tls.crt 72 | path: tls.crt 73 | secretName: clustercert 74 | -------------------------------------------------------------------------------- /images/add_mapper.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securesign/sigstore-ocp/49c2c70abdc7f0e789349b99622085c5fcfce682/images/add_mapper.png -------------------------------------------------------------------------------- /images/add_urls.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securesign/sigstore-ocp/49c2c70abdc7f0e789349b99622085c5fcfce682/images/add_urls.png -------------------------------------------------------------------------------- /images/create_mapper_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securesign/sigstore-ocp/49c2c70abdc7f0e789349b99622085c5fcfce682/images/create_mapper_2.png -------------------------------------------------------------------------------- /images/github_login_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securesign/sigstore-ocp/49c2c70abdc7f0e789349b99622085c5fcfce682/images/github_login_2.png -------------------------------------------------------------------------------- /images/mapper2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securesign/sigstore-ocp/49c2c70abdc7f0e789349b99622085c5fcfce682/images/mapper2.png -------------------------------------------------------------------------------- /images/redirect_uri.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securesign/sigstore-ocp/49c2c70abdc7f0e789349b99622085c5fcfce682/images/redirect_uri.png -------------------------------------------------------------------------------- /keycloak/operator/base/kustomization.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kustomize.config.k8s.io/v1beta1 2 | kind: Kustomization 3 | 4 | resources: 5 | - namespace.yaml 6 | - subscription.yaml 7 | 8 | namespace: keycloak-system 9 | -------------------------------------------------------------------------------- /keycloak/operator/base/namespace.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Namespace 3 | metadata: 4 | name: keycloak-system 5 | -------------------------------------------------------------------------------- /keycloak/operator/base/subscription.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: operators.coreos.com/v1alpha1 3 | kind: Subscription 4 | metadata: 5 | name: rhsso-operator 6 | spec: 7 | channel: stable 8 | installPlanApproval: Automatic 9 | name: rhsso-operator 10 | source: redhat-operators 11 | sourceNamespace: openshift-marketplace 12 | --- 13 | apiVersion: operators.coreos.com/v1 14 | kind: OperatorGroup 15 | metadata: 16 | name: keycloak-system-trusted-artifact-signer 17 | spec: 18 | targetNamespaces: 19 | - keycloak-system 20 | upgradeStrategy: Default 21 | -------------------------------------------------------------------------------- /keycloak/operator/overlay/kind/kustomization.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kustomize.config.k8s.io/v1beta1 2 | kind: Kustomization 3 | 4 | resources: 5 | - ../../base 6 | 7 | patches: 8 | - path: patch.yaml 9 | 10 | 11 | -------------------------------------------------------------------------------- /keycloak/operator/overlay/kind/patch.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: operators.coreos.com/v1alpha1 2 | kind: Subscription 3 | metadata: 4 | name: rhsso-operator 5 | spec: 6 | channel: alpha 7 | name: keycloak-operator 8 | source: operatorhubio-catalog 9 | sourceNamespace: olm 10 | -------------------------------------------------------------------------------- /keycloak/resources/base/keycloak.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: keycloak.org/v1alpha1 2 | kind: Keycloak 3 | metadata: 4 | labels: 5 | app: sso 6 | name: keycloak 7 | spec: 8 | externalAccess: 9 | enabled: true 10 | instances: 1 11 | keycloakDeploymentSpec: 12 | imagePullPolicy: Always 13 | postgresDeploymentSpec: 14 | imagePullPolicy: Always 15 | -------------------------------------------------------------------------------- /keycloak/resources/base/kustomization.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kustomize.config.k8s.io/v1beta1 2 | kind: Kustomization 3 | 4 | namespace: keycloak-system 5 | 6 | resources: 7 | - keycloak.yaml 8 | - realm.yaml 9 | - tas-client.yaml 10 | - user.yaml 11 | -------------------------------------------------------------------------------- /keycloak/resources/base/realm.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: keycloak.org/v1alpha1 2 | kind: KeycloakRealm 3 | metadata: 4 | labels: 5 | app: sso 6 | name: trusted-artifact-signer 7 | spec: 8 | instanceSelector: 9 | matchLabels: 10 | app: sso 11 | realm: 12 | displayName: Red-Hat-Trusted-Artifact-Signer 13 | enabled: true 14 | id: trusted-artifact-signer 15 | realm: trusted-artifact-signer 16 | sslRequired: none 17 | -------------------------------------------------------------------------------- /keycloak/resources/base/tas-client.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: keycloak.org/v1alpha1 2 | kind: KeycloakClient 3 | metadata: 4 | labels: 5 | app: sso 6 | name: trusted-artifact-signer 7 | spec: 8 | client: 9 | attributes: 10 | request.object.signature.alg: RS256 11 | user.info.response.signature.alg: RS256 12 | clientAuthenticatorType: client-secret 13 | clientId: trusted-artifact-signer 14 | defaultClientScopes: 15 | - profile 16 | - email 17 | description: Client for Red Hat Trusted Artifact Signer authentication 18 | directAccessGrantsEnabled: true 19 | implicitFlowEnabled: false 20 | name: trusted-artifact-signer 21 | protocol: openid-connect 22 | protocolMappers: 23 | - config: 24 | claim.name: email 25 | id.token.claim: "true" 26 | jsonType.label: String 27 | user.attribute: email 28 | userinfo.token.claim: "true" 29 | name: email 30 | protocol: openid-connect 31 | protocolMapper: oidc-usermodel-property-mapper 32 | - config: 33 | claim.name: email-verified 34 | id.token.claim: "true" 35 | user.attribute: emailVerified 36 | userinfo.token.claim: "true" 37 | name: email-verified 38 | protocol: openid-connect 39 | protocolMapper: oidc-usermodel-property-mapper 40 | - config: 41 | claim.name: aud 42 | claim.value: trusted-artifact-signer 43 | id.token.claim: "true" 44 | access.token.claim: "true" 45 | userinfo.token.claim: "true" 46 | name: audience 47 | protocol: openid-connect 48 | protocolMapper: oidc-hardcoded-claim-mapper 49 | publicClient: true 50 | standardFlowEnabled: true 51 | redirectUris: 52 | - "*" 53 | realmSelector: 54 | matchLabels: 55 | app: sso 56 | -------------------------------------------------------------------------------- /keycloak/resources/base/user.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: keycloak.org/v1alpha1 3 | kind: KeycloakUser 4 | metadata: 5 | labels: 6 | app: sso 7 | name: jdoe 8 | spec: 9 | realmSelector: 10 | matchLabels: 11 | app: sso 12 | user: 13 | email: jdoe@redhat.com 14 | enabled: true 15 | emailVerified: true 16 | credentials: 17 | - type: "password" 18 | value: "secure" 19 | firstName: Jane 20 | lastName: Doe 21 | username: jdoe 22 | -------------------------------------------------------------------------------- /keycloak/resources/example-user.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: keycloak.org/v1alpha1 2 | kind: KeycloakUser 3 | metadata: 4 | labels: 5 | app: sso 6 | name: UPDATE 7 | namespace: keycloak-system 8 | spec: 9 | realmSelector: 10 | matchLabels: 11 | app: sso 12 | user: 13 | credentials: 14 | - type: password 15 | value: UPDATE 16 | email: user@email.com 17 | emailVerified: true 18 | enabled: true 19 | firstName: UPDATE 20 | lastName: UPDATE 21 | username: UPDATE 22 | -------------------------------------------------------------------------------- /keycloak/resources/overlay/kind/keycloak-svc.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: keycloak-internal 5 | spec: 6 | selector: 7 | app: keycloak 8 | component: keycloak 9 | ports: 10 | - protocol: TCP 11 | port: 80 12 | targetPort: 8080 13 | -------------------------------------------------------------------------------- /keycloak/resources/overlay/kind/keycloak_patch.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: keycloak.org/v1alpha1 2 | kind: Keycloak 3 | metadata: 4 | name: keycloak 5 | spec: 6 | externalAccess: 7 | enabled: false 8 | 9 | -------------------------------------------------------------------------------- /keycloak/resources/overlay/kind/kustomization.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kustomize.config.k8s.io/v1beta1 2 | kind: Kustomization 3 | 4 | namespace: keycloak-system 5 | 6 | resources: 7 | - ../../base 8 | - keycloak-svc.yaml 9 | 10 | patches: 11 | - path: keycloak_patch.yaml 12 | - path: realm_patch.yaml 13 | -------------------------------------------------------------------------------- /keycloak/resources/overlay/kind/realm_patch.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: keycloak.org/v1alpha1 2 | kind: KeycloakRealm 3 | metadata: 4 | name: trusted-artifact-signer 5 | spec: 6 | realm: 7 | sslRequired: none 8 | -------------------------------------------------------------------------------- /kind/config.yaml: -------------------------------------------------------------------------------- 1 | kind: Cluster 2 | apiVersion: kind.x-k8s.io/v1alpha4 3 | nodes: 4 | - role: control-plane 5 | extraMounts: 6 | - containerPath: /var/lib/kubelet/config.json 7 | # this is the path in gh action where the config is saved 8 | hostPath: /tmp/config.json 9 | -------------------------------------------------------------------------------- /kind/kind-up-test.sh: -------------------------------------------------------------------------------- 1 | # run this from root of repository 2 | 3 | # spin up kind cluster 4 | cat < /tmp/config 15 | chown $USER:$USER /tmp/config 16 | if [[ -d ~/.kube ]] && [[ -f ~/.kube/config ]] 17 | then 18 | export KUBECONFIG=~/.kube/config:/tmp/config 19 | oc config view --flatten > merged-config.yaml 20 | mv merged-config.yaml ~/.kube/config 21 | else 22 | mv /tmp/config ~/.kube/config 23 | fi 24 | chmod go-r ~/.kube/config 25 | 26 | oc config use-context kind-kind 27 | 28 | oc create ns fulcio-system 29 | oc create ns rekor-system 30 | oc -n fulcio-system create secret generic fulcio-secret-rh --from-file=private=./kind/testing-only-cert-key/file_ca_key.pem --from-file=public=./kind/testing-only-cert-key/file_ca_pub.pem --from-file=cert=./kind/testing-only-cert-key/fulcio-root.pem --from-literal=password=secure --dry-run=client -o yaml | oc apply -f- 31 | 32 | oc -n rekor-system create secret generic rekor-private-key --from-file=private=./kind/testing-only-cert-key/rekor_key.pem --dry-run=client -o yaml | oc apply -f- 33 | 34 | #install OLM 35 | kubectl create -f https://github.com/operator-framework/operator-lifecycle-manager/releases/download/v0.25.0/crds.yaml 36 | # wait for a while to be sure CRDs are installed 37 | sleep 1 38 | kubectl create -f https://github.com/operator-framework/operator-lifecycle-manager/releases/download/v0.25.0/olm.yaml 39 | 40 | #install keycloak from Kind overlay 41 | kubectl create --kustomize keycloak/operator/overlay/kind 42 | until [ ! -z "$(kubectl get pod -l name=keycloak-operator -n keycloak-system 2>/dev/null)" ] 43 | do 44 | echo "Waiting for keycloak operator. Pods in keycloak-system namespace:" 45 | kubectl get pods -n keycloak-system 46 | sleep 10 47 | done 48 | kubectl create --kustomize keycloak/resources/overlay/kind 49 | until [[ $( oc get keycloak keycloak -o jsonpath='{.status.ready}' -n keycloak-system 2>/dev/null) == "true" ]] 50 | do 51 | printf "Waiting for keycloak deployment. \n Keycloak ready: %s \n" $(oc get keycloak keycloak -o jsonpath='{.status.ready}' -n keycloak-system) 52 | sleep 10 53 | done 54 | 55 | # install charts 56 | helm upgrade -i trusted-artifact-signer --debug ./charts/trusted-artifact-signer --wait --wait-for-jobs --timeout 10m -n trusted-artifact-signer --create-namespace --values ./examples/values-kind-sigstore.yaml && \ 57 | helm test trusted-artifact-signer -n trusted-artifact-signer 58 | -------------------------------------------------------------------------------- /kind/testing-only-cert-key/file_ca_key.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN EC PRIVATE KEY----- 2 | Proc-Type: 4,ENCRYPTED 3 | DEK-Info: DES-EDE3-CBC,57052BF0C94F8233 4 | 5 | iYxyAS5gRrPrdKDdEvzokWkp5z5swdqkxyuGx98gcMHnkJlW+sa53cAqqnLefNXO 6 | y/pROXH0PXhKg+5sMcwJCba8yf5obQOiqWsrH7ERb5SC+OmXvnIxTallp6fRw6W0 7 | jWRrqUp+QpQxfdKwSrLMYVPQw8e9iVewNZkZxPC0YVI= 8 | -----END EC PRIVATE KEY----- 9 | -------------------------------------------------------------------------------- /kind/testing-only-cert-key/file_ca_pub.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE+l00SWziQVPM+ubkppU3gSpdJnzd 3 | hDqojvHYY6GRTDTZcFlU24mouB/ARzT1eS6giaFbehlg5QEm6GhfWdbiww== 4 | -----END PUBLIC KEY----- 5 | -------------------------------------------------------------------------------- /kind/testing-only-cert-key/fulcio-root.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIICTjCCAfOgAwIBAgIUW9JM5WZNic2pGCTv6jYea2xBprQwCgYIKoZIzj0EAwIw 3 | fDELMAkGA1UEBhMCVVMxDjAMBgNVBAgMBU1haW5lMREwDwYDVQQHDAhQb3J0bGFu 4 | ZDEQMA4GA1UECgwHUmVkIEhhdDEUMBIGA1UEAwwLc2lnc3RvcmUuZXoxIjAgBgkq 5 | hkiG9w0BCQEWE3NvbWFsbGV5QHJlZGhhdC5jb20wHhcNMjMwOTI2MTgyNTEwWhcN 6 | MjQwOTI1MTgyNTEwWjB8MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFTWFpbmUxETAP 7 | BgNVBAcMCFBvcnRsYW5kMRAwDgYDVQQKDAdSZWQgSGF0MRQwEgYDVQQDDAtzaWdz 8 | dG9yZS5lejEiMCAGCSqGSIb3DQEJARYTc29tYWxsZXlAcmVkaGF0LmNvbTBZMBMG 9 | ByqGSM49AgEGCCqGSM49AwEHA0IABPpdNEls4kFTzPrm5KaVN4EqXSZ83YQ6qI7x 10 | 2GOhkUw02XBZVNuJqLgfwEc09XkuoImhW3oZYOUBJuhoX1nW4sOjUzBRMB0GA1Ud 11 | DgQWBBTXTK85svHwwn0vEmkp5+rvF9yL8jAfBgNVHSMEGDAWgBTXTK85svHwwn0v 12 | Emkp5+rvF9yL8jAPBgNVHRMBAf8EBTADAQH/MAoGCCqGSM49BAMCA0kAMEYCIQDO 13 | lLxcAuWYU2GqCG2XMaEEIIOX5ns5sf11MY6NdGcBngIhAMvOa1BZ7XYEGHj0G17y 14 | lAqCBO3yklG3WNHoj8Hm4YGZ 15 | -----END CERTIFICATE----- 16 | -------------------------------------------------------------------------------- /kind/testing-only-cert-key/rekor_key.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN EC PRIVATE KEY----- 2 | MHcCAQEEICnmFR7rXoJ3QujB9SzrKbVtXCikPXtEb2rs8EGgzYrSoAoGCCqGSM49 3 | AwEHoUQDQgAEnItR5lDp+1fPho5A2npEr9CygZ3lVGXB6jc0MAS/bez9PxUlPacS 4 | XrlASWbaMaLIoporoKnYhoGHd1oiiVq1lg== 5 | -----END EC PRIVATE KEY----- 6 | -------------------------------------------------------------------------------- /rekor-create-signer-key.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | mkdir -p keys-cert 4 | cd keys-cert 5 | openssl ecparam -name prime256v1 -genkey -noout -out rekor_key.pem 6 | cd ../ 7 | -------------------------------------------------------------------------------- /release-plans/gamma/ReleasePlan.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: appstudio.redhat.com/v1alpha1 2 | kind: ReleasePlan 3 | metadata: 4 | labels: 5 | release.appstudio.openshift.io/auto-release: 'false' 6 | name: rhtas-access-1-0-gamma-registry-redhat-io 7 | namespace: rhtas-tenant 8 | spec: 9 | application: access-1-0-gamma 10 | target: rhtap-releng-tenant 11 | -------------------------------------------------------------------------------- /tas-easy-install.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # Define the maximum number of attempts and the sleep interval (in seconds) 4 | max_attempts=30 5 | sleep_interval=10 6 | 7 | # Function to check pod status 8 | check_pod_status() { 9 | local namespace="$1" 10 | local pod_name_prefix="$2" 11 | local attempts=0 12 | 13 | while [[ $attempts -lt $max_attempts ]]; do 14 | pod_name=$(oc get pod -n "$namespace" | grep "$pod_name_prefix" | grep "Running" | awk '{print $1}') 15 | if [ -n "$pod_name" ]; then 16 | pod_status=$(oc get pod -n "$namespace" "$pod_name" -o jsonpath='{.status.phase}') 17 | if [ "$pod_status" == "Running" ]; then 18 | echo "$pod_name is up and running in namespace $namespace." 19 | return 0 20 | else 21 | echo "$pod_name is in state: $pod_status. Retrying in $sleep_interval seconds..." 22 | fi 23 | else 24 | echo "No pods with the prefix '$pod_name_prefix' found in namespace $namespace. Retrying in $sleep_interval seconds..." 25 | fi 26 | 27 | sleep $sleep_interval 28 | attempts=$((attempts + 1)) 29 | done 30 | 31 | echo "Timed out. No pods with the prefix '$pod_name_prefix' reached the 'Running' state within the specified time." 32 | return 1 33 | } 34 | 35 | # Install SSO Operator and Keycloak service 36 | install_sso_keycloak() { 37 | oc apply --kustomize keycloak/operator/base 38 | check_pod_status "keycloak-system" "rhsso-operator" 39 | # Check the return value from the function 40 | if [ $? -ne 0 ]; then 41 | echo "Pod status check failed. Exiting the script." 42 | exit 1 43 | fi 44 | 45 | oc apply --kustomize keycloak/resources/base 46 | check_pod_status "keycloak-system" "keycloak-postgresql" 47 | # Check the return value from the function 48 | if [ $? -ne 0 ]; then 49 | echo "Pod status check failed. Exiting the script." 50 | exit 1 51 | fi 52 | } 53 | 54 | # Install Red Hat SSO Operator and setup Keycloak service 55 | install_sso_keycloak 56 | 57 | mkdir -p keys-cert 58 | pushd keys-cert > /dev/null 59 | 60 | read -p "Should this script generate the fulcio certificates? (Y/N): " generate_certs 61 | if [ "$generate_certs" = "Y" ] || [ "$generate_certs" = "y" ]; then 62 | generate_certs=true 63 | else 64 | generate_certs=false 65 | fi 66 | 67 | common_name=apps.$(oc get dns cluster -o jsonpath='{ .spec.baseDomain }') 68 | if [ "$generate_certs" = true ]; then 69 | # Prompt for the organizationName 70 | read -p "Enter the organization name for the certificate: " organization_name 71 | # Prompt for the email address 72 | read -p "Enter the email address for the certificate: " email_address 73 | # Prompt for the password 74 | read -s -p "Enter the password for the private key: " password 75 | 76 | openssl ecparam -genkey -name prime256v1 -noout -out unenc.key 77 | openssl ec -in unenc.key -out file_ca_key.pem -des3 -passout pass:"$password" 78 | openssl ec -in file_ca_key.pem -passin pass:"$password" -pubout -out file_ca_pub.pem 79 | openssl req -new -x509 -days 365 -key file_ca_key.pem -passin pass:"$password" -out fulcio-root.pem -passout pass:"$password" -subj "/CN=$common_name/emailAddress=$email_address/O=$organization_name" 80 | rm unenc.key 81 | fi 82 | openssl ecparam -name prime256v1 -genkey -noout -out rekor_key.pem 83 | 84 | segment_backup_job=$(oc get job -n trusted-artifact-signer-monitoring --ignore-not-found=true | tail -n 1 | awk '{print $1}') 85 | if [[ -n $segment_backup_job ]]; then 86 | oc delete job $segment_backup_job -n trusted-artifact-signer-monitoring 87 | fi 88 | 89 | oc new-project trusted-artifact-signer-monitoring > /dev/null 2>&1 90 | 91 | pull_secret_exists=$(oc get secret pull-secret -n trusted-artifact-signer-monitoring --ignore-not-found=true) 92 | if [[ -n $pull_secret_exists ]]; then 93 | read -p "Secret \"pull-secret\" in namespace \"trusted-artifact-signer-monitoring\" already exists. Overwrite it (Y/N)?: " -n1 overwrite_pull_secret 94 | echo "" 95 | if [[ $overwrite_pull_secret == "Y" || $overwrite_pull_secret == 'y' ]]; then 96 | read -p "Please enter the absolute path to the pull-secret.json file: 97 | " pull_secret_path 98 | file_exists=$(ls $pull_secret_path 2>/dev/null) 99 | if [[ -n $file_exists ]]; then 100 | oc create secret generic pull-secret -n trusted-artifact-signer-monitoring --from-file=$pull_secret_path --dry-run=client -o yaml | oc replace -f - 101 | else 102 | echo "pull secret was not found based on the path provided: $pull_secret_path" 103 | exit 0 104 | fi 105 | elif [[ $overwrite_pull_secret == "N" || $overwrite_pull_secret == 'n' ]]; then 106 | echo "Skipping overwriting pull-secret..." 107 | else 108 | echo "Bad input. Skipping this step, using existing pull-secret" 109 | fi 110 | else 111 | read -p "Please enter the absolute path to the pull-secret.json file: 112 | " pull_secret_path 113 | oc create secret generic pull-secret -n trusted-artifact-signer-monitoring --from-file=$pull_secret_path 114 | fi 115 | 116 | popd > /dev/null 117 | 118 | oc create ns fulcio-system 119 | if [ "$generate_certs" = true ]; then 120 | oc -n fulcio-system create secret generic fulcio-secret-rh --from-file=private=./keys-cert/file_ca_key.pem --from-file=public=./keys-cert/file_ca_pub.pem --from-file=cert=./keys-cert/fulcio-root.pem --from-literal=password="$password" --dry-run=client -o yaml | oc apply -f- 121 | fi 122 | 123 | oc create ns rekor-system 124 | oc -n rekor-system create secret generic rekor-private-key --from-file=private=./keys-cert/rekor_key.pem --dry-run=client -o yaml | oc apply -f- 125 | 126 | # TODO: uncomment to install from helm repository, install from the local repo checkout for now 127 | #helm repo add trusted-artifact-signer https://repo-securesign-helm.apps.open-svc-sts.k1wl.p1.openshiftapps.com/helm-charts 128 | #helm repo update 129 | #OPENSHIFT_APPS_SUBDOMAIN=$common_name envsubst < examples/values-sigstore-openshift.yaml | helm install --debug trusted-artifact-signer trusted-artifact-signer/trusted-artifact-signer -n trusted-artifact-signer --create-namespace --values - 130 | 131 | if [ "$generate_certs" = true ]; then 132 | OPENSHIFT_APPS_SUBDOMAIN=$common_name envsubst < examples/values-sigstore-openshift.yaml | helm upgrade -i trusted-artifact-signer --debug charts/trusted-artifact-signer -n trusted-artifact-signer --create-namespace --values - 133 | else 134 | OPENSHIFT_APPS_SUBDOMAIN=$common_name envsubst < examples/values-sigstore-openshift.yaml | helm upgrade -i trusted-artifact-signer --debug charts/trusted-artifact-signer -n trusted-artifact-signer --create-namespace --values - --set scaffold.fulcio.createcerts.enabled=true 135 | fi 136 | 137 | echo "\nTo initialize the environment variables, run 'source ./tas-env-variables.sh' from the terminal." 138 | -------------------------------------------------------------------------------- /tas-env-variables.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # This assumes you are currently running from the context of the namespace where your securesign is created 4 | # Run `oc project ` to ensure you are working within the correct context 5 | 6 | # Initialize Variables 7 | export BASE_HOSTNAME=$(kubectl get cm -n openshift-config-managed console-public -o go-template="{{ .data.consoleURL }}" | sed 's@https://@@; s/^[^.]*\.//') 8 | export KEYCLOAK_NAMESPACE="${KEYCLOAK_NAMESPACE:=keycloak-system}" 9 | 10 | export KEYCLOAK_CLIENT_ID="${KEYCLOAK_CLIENT_ID:=trusted-artifact-signer}" 11 | export KEYCLOAK_REALM="${KEYCLOAK_REALM:=trusted-artifact-signer}" 12 | export KEYCLOAK_HOSTNAME="${KEYCLOAK_HOSTNAME:=$(kubectl get keycloak -n ${KEYCLOAK_NAMESPACE} -o jsonpath='{.items[*].status.externalURL}')}" 13 | export OIDC_ISSUER_URL="${OIDC_ISSUER_URL:=${KEYCLOAK_HOSTNAME}/auth/realms/${KEYCLOAK_REALM}}" 14 | 15 | if [[ `kubectl api-resources -o name | grep securesigns.rhtas.redhat.com` ]]; then 16 | CURRENT_NAMESPACE="${RHTAS_NAMESPACE:=$(kubectl config view --minify -o jsonpath='{..namespace}')}" 17 | 18 | # Ensure Securesign resource has been created 19 | SECURESIGN_NAME=$(kubectl get securesign -n ${CURRENT_NAMESPACE} -o name | head -1) 20 | if [[ -z "${SECURESIGN_NAME}" ]]; then 21 | echo "Error: Securesign resource not created in namespace \"${CURRENT_NAMESPACE}\"" 22 | return 23 | fi 24 | 25 | TUF_URL=$(kubectl get tuf -o jsonpath='{.items[0].status.url}' -n ${CURRENT_NAMESPACE}) 26 | REKOR_URL=$(kubectl get rekor -o jsonpath='{.items[0].status.url}' -n ${CURRENT_NAMESPACE}) 27 | FULCIO_URL=$(kubectl get fulcio -o jsonpath='{.items[0].status.url}' -n ${CURRENT_NAMESPACE}) 28 | else 29 | # Set Values for Helm Chart deployment 30 | TUF_URL="${TUF_URL:=https://tuf.${BASE_HOSTNAME}}" 31 | FULCIO_URL="${FULCIO_URL:=https://fulcio.${BASE_HOSTNAME}}" 32 | REKOR_URL="${REKOR_URL:=https://rekor.${BASE_HOSTNAME}}" 33 | fi 34 | 35 | # Common Variables 36 | export COSIGN_FULCIO_URL="${FULCIO_URL}" 37 | export COSIGN_REKOR_URL="${REKOR_URL}" 38 | export COSIGN_MIRROR="${TUF_URL}" 39 | export COSIGN_ROOT="${TUF_URL}/root.json" 40 | export COSIGN_OIDC_ISSUER="${OIDC_ISSUER_URL}" 41 | export COSIGN_OIDC_CLIENT_ID="${KEYCLOAK_CLIENT_ID}" 42 | export COSIGN_CERTIFICATE_OIDC_ISSUER="${OIDC_ISSUER_URL}" 43 | export COSIGN_YES="true" 44 | export SIGSTORE_FULCIO_URL="${FULCIO_URL}" 45 | export SIGSTORE_OIDC_CLIENT_ID="${KEYCLOAK_CLIENT_ID}" 46 | export SIGSTORE_OIDC_ISSUER="${OIDC_ISSUER_URL}" 47 | export SIGSTORE_REKOR_URL="${REKOR_URL}" 48 | export REKOR_REKOR_SERVER="${REKOR_URL}" 49 | -------------------------------------------------------------------------------- /tas-grafana-install.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | # Script for creating a Grafana dashboard for the Trusted Artifact Signer service 3 | # 4 | 5 | # Define the maximum number of attempts and the sleep interval (in seconds) 6 | max_attempts=30 7 | sleep_interval=10 8 | # Function to check pod status 9 | check_pod_status() { 10 | local namespace="$1" 11 | local pod_name_prefix="$2" 12 | local attempts=0 13 | 14 | while [[ $attempts -lt $max_attempts ]]; do 15 | pod_name=$(oc get pod -n "$namespace" | grep "$pod_name_prefix" | grep "Running" | awk '{print $1}') 16 | if [ -n "$pod_name" ]; then 17 | pod_status=$(oc get pod -n "$namespace" "$pod_name" -o jsonpath='{.status.phase}') 18 | if [ "$pod_status" == "Running" ]; then 19 | echo "$pod_name is up and running in namespace $namespace." 20 | return 0 21 | else 22 | echo "$pod_name is in state: $pod_status. Retrying in $sleep_interval seconds..." 23 | fi 24 | else 25 | echo "No pods with the prefix '$pod_name_prefix' found in namespace $namespace. Retrying in $sleep_interval seconds..." 26 | fi 27 | 28 | sleep $sleep_interval 29 | attempts=$((attempts + 1)) 30 | done 31 | 32 | echo "Timed out. No pods with the prefix '$pod_name_prefix' reached the 'Running' state within the specified time." 33 | return 1 34 | } 35 | 36 | # Ensure workload monitoring is enabled in the OpenShift cluster. 37 | enable_workload_monitoring="true" 38 | oc get configmap -n openshift-monitoring > /tmp/g1 39 | if grep -q "cluster-monitoring-config" /tmp/g1; then 40 | oc get configmap cluster-monitoring-config -n openshift-monitoring -o json| jq -r '.data."config.yaml"' > /tmp/g1 41 | if grep -q "enableUserWorkload" /tmp/g1; then 42 | extracted_text=$(grep "enableUserWorkload" /tmp/g1 | cut -f2 -d ":") 43 | trim_extracted_text=$(echo "$extracted_text" | sed -e 's/^[[:space:]]*//') 44 | if [ "$trim_extracted_text" = "true" ]; then 45 | echo "Workload monitoring is already enabled" 46 | enable_workload_monitoring="false" 47 | fi 48 | fi 49 | fi 50 | 51 | if [ "$enable_workload_monitoring" = "true" ]; then 52 | echo "setup cluster monitoring" 53 | oc create --save-config -f - <