Skip to content

Commit d7b1121

Browse files
authored
RHTAP: Add jenkins as CI builder (redhat-cop#8901)
* update * update * update * update * update * update * update * update * update * update
1 parent b555c10 commit d7b1121

15 files changed

+338
-20
lines changed

ansible/roles_ocp_workloads/ocp4_workload_jenkins/tasks/workload.yml

+2
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
- ./templates/service.yaml.j2
1717
- ./templates/service_jnlp.yaml.j2
1818
- ./templates/role_binding.yaml.j2
19+
- ./role_binding_privileged.yaml.j2
20+
- ./role_binding_webhook_unauthenticated.yaml.j2
1921
- ./templates/route.yaml.j2
2022
- ./templates/deployment.yaml.j2
2123

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
kind: RoleBinding
2+
apiVersion: rbac.authorization.k8s.io/v1
3+
metadata:
4+
name: 'system:openshift:scc:anyuid'
5+
namespace: {{ ocp4_workload_jenkins_project }}
6+
subjects:
7+
- kind: ServiceAccount
8+
name: default
9+
namespace: {{ ocp4_workload_jenkins_project }}
10+
roleRef:
11+
apiGroup: rbac.authorization.k8s.io
12+
kind: ClusterRole
13+
name: 'system:openshift:scc:privileged'
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
kind: RoleBinding
2+
apiVersion: rbac.authorization.k8s.io/v1
3+
metadata:
4+
name: webhook-access-unauthenticated
5+
namespace: {{ ocp4_workload_jenkins_project }}
6+
subjects:
7+
- kind: Group
8+
apiGroup: rbac.authorization.k8s.io
9+
name: 'system:unauthenticated'
10+
roleRef:
11+
apiGroup: rbac.authorization.k8s.io
12+
kind: ClusterRole
13+
name: 'system:webhook'

ansible/roles_ocp_workloads/ocp4_workload_trusted_application_pipeline/defaults/main.yml

+3
Original file line numberDiff line numberDiff line change
@@ -119,3 +119,6 @@ ocp4_workload_trusted_application_pipeline_env_type: ocp4-cluster
119119
ocp4_workload_trusted_application_pipeline_cloud_provider: "{{ cloud_provider | default('ec2') }}"
120120

121121
ocp4_workload_trusted_application_pipeline_orchestrator_enabled: "{{ orchestrator_enabled | default('true') | bool }}"
122+
123+
ocp4_workload_trusted_application_pipeline_jenkins_namespace: jenkins
124+
ocp4_workload_trusted_application_pipeline_jenkins_admin_password: password
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
apiVersion: external-secrets.io/v1beta1
2+
kind: ExternalSecret
3+
metadata:
4+
name: common-password-secret
5+
spec:
6+
secretStoreRef:
7+
name: vault-secret-store
8+
kind: ClusterSecretStore
9+
target:
10+
name: common-password-secret
11+
data:
12+
- secretKey: password
13+
remoteRef:
14+
key: secrets/janusidp/common_password
15+
property: password
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
apiVersion: external-secrets.io/v1beta1
2+
kind: ExternalSecret
3+
metadata:
4+
name: gitlab-webhook-secret
5+
spec:
6+
secretStoreRef:
7+
name: vault-secret-store
8+
kind: ClusterSecretStore
9+
target:
10+
name: gitlab-webhook-secret
11+
data:
12+
- secretKey: WebHookSecretKey
13+
remoteRef:
14+
key: secrets/janusidp/gitlab_webhook
15+
property: secret
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
apiVersion: external-secrets.io/v1beta1
2+
kind: ExternalSecret
3+
metadata:
4+
name: stackrox-token
5+
spec:
6+
secretStoreRef:
7+
name: vault-secret-store
8+
kind: ClusterSecretStore
9+
target:
10+
name: stackrox-token
11+
data:
12+
- secretKey: rox_api_token
13+
remoteRef:
14+
key: secrets/janusidp/stackrox
15+
property: token
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
apiVersion: external-secrets.io/v1beta1
2+
kind: ExternalSecret
3+
metadata:
4+
name: trustification-secret
5+
spec:
6+
secretStoreRef:
7+
name: vault-secret-store
8+
kind: ClusterSecretStore
9+
target:
10+
name: trustification-secret
11+
data:
12+
- secretKey: bombastic_api_url
13+
remoteRef:
14+
key: secrets/janusidp/tpa/bombastic_api_url
15+
property: value
16+
- secretKey: oidc_issuer_url
17+
remoteRef:
18+
key: secrets/janusidp/tpa/oidc_issuer_url
19+
property: value
20+
- secretKey: oidc_client_id
21+
remoteRef:
22+
key: secrets/janusidp/tpa/oidc_client_id
23+
property: value
24+
- secretKey: oidc_client_secret
25+
remoteRef:
26+
key: secrets/janusidp/tpa/oidc_client_secret
27+
property: value
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
<?xml version='1.1' encoding='UTF-8'?>
2+
<org.jenkinsci.plugins.configfiles.GlobalConfigFiles plugin="[email protected]_4518b_">
3+
<configs class="sorted-set">
4+
<comparator class="org.jenkinsci.plugins.configfiles.ConfigByIdComparator"/>
5+
<org.jenkinsci.plugins.configfiles.custom.CustomConfig>
6+
<id>create.att.predicate.sh</id>
7+
<name>create.att.predicate.sh</name>
8+
<comment></comment>
9+
<content>#
10+
# Create attestation predicate for RHTAP Jenkins builds
11+
#
12+
# Useful references:
13+
# - https://slsa.dev/spec/v1.0/provenance
14+
# - https://www.jenkins.io/doc/book/pipeline/jenkinsfile/#using-environment-variables
15+
# - http://localhost:8080/env-vars.html/
16+
# (Replace localhost with your Jenkins instance)
17+
#
18+
yq -o=json -I=0 &lt;&lt; EOT
19+
---
20+
buildDefinition:
21+
buildType: &quot;https://redhat.com/rhtap/slsa-build-types/${CI_TYPE}-build/v1&quot;
22+
externalParameters: {}
23+
internalParameters: {}
24+
resolvedDependencies:
25+
- uri: &quot;git+${GIT_URL}&quot;
26+
digest:
27+
gitCommit: &quot;${GIT_COMMIT}&quot;
28+
29+
runDetails:
30+
builder:
31+
id: &quot;${NODE_NAME}&quot;
32+
builderDependencies: []
33+
version:
34+
# Not sure if this is the right place for these...
35+
buildNumber: &quot;${BUILD_NUMBER}&quot;
36+
jobName: &quot;${JOB_NAME}&quot;
37+
executorNumber: &quot;${EXECUTOR_NUMBER}&quot;
38+
jenkinsHome: &quot;${JENKINS_HOME}&quot;
39+
buildUrl: &quot;${BUILD_URL}&quot;
40+
jobUrl: &quot;${JOB_URL}&quot;
41+
42+
metadata:
43+
invocationID: &quot;${BUILD_TAG}&quot;
44+
startedOn: &quot;$(cat $RESULTS/init/START_TIME)&quot;
45+
# Inaccurate, but maybe close enough
46+
finishedOn: &quot;$(date +%Y-%m-%dT%H:%M:%SZ)&quot;
47+
48+
byproducts:
49+
- name: SBOM_BLOB
50+
uri: &quot;$(cat &quot;$BASE_RESULTS&quot;/buildah-rhtap/SBOM_BLOB_URL)&quot;
51+
52+
EOT</content>
53+
<providerId>org.jenkinsci.plugins.configfiles.custom.CustomConfig</providerId>
54+
<customizedCredentialMappings/>
55+
</org.jenkinsci.plugins.configfiles.custom.CustomConfig>
56+
<org.jenkinsci.plugins.configfiles.custom.CustomConfig>
57+
<id>merge.sboms.py</id>
58+
<name>merge.sboms.py</name>
59+
<comment></comment>
60+
<content>#!/bin/python3
61+
import hashlib
62+
import json
63+
import os
64+
import re
65+
66+
### load SBOMs ###
67+
68+
with open(os.getenv(&quot;TEMP_DIR&quot;) + &quot;/files/sbom-image.json&quot;) as f:
69+
image_sbom = json.load(f)
70+
71+
with open(os.getenv(&quot;TEMP_DIR&quot;) + &quot;/files/sbom-source.json&quot;) as f:
72+
source_sbom = json.load(f)
73+
74+
75+
### attempt to deduplicate components ###
76+
77+
component_list = image_sbom.get(&quot;components&quot;, [])
78+
existing_purls = [c[&quot;purl&quot;] for c in component_list if &quot;purl&quot; in c]
79+
80+
for component in source_sbom.get(&quot;components&quot;, []):
81+
if &quot;purl&quot; in component:
82+
if component[&quot;purl&quot;] not in existing_purls:
83+
component_list.append(component)
84+
existing_purls.append(component[&quot;purl&quot;])
85+
else:
86+
# We won&apos;t try to deduplicate components that lack a purl.
87+
# This should only happen with operating-system type components,
88+
# which are only reported in the image SBOM.
89+
component_list.append(component)
90+
91+
component_list.sort(key=lambda c: c[&quot;type&quot;] + c[&quot;name&quot;])
92+
image_sbom[&quot;components&quot;] = component_list
93+
94+
95+
### write the CycloneDX unified SBOM ###
96+
97+
with open(os.getenv(&quot;TEMP_DIR&quot;) + &quot;/files/sbom-cyclonedx.json&quot;, &quot;w&quot;) as f:
98+
json.dump(image_sbom, f, indent=4)
99+
100+
101+
### write the SBOM blob URL result ###
102+
103+
with open(os.getenv(&quot;TEMP_DIR&quot;) + &quot;/files/sbom-cyclonedx.json&quot;, &quot;rb&quot;) as f:
104+
sbom_digest = hashlib.file_digest(f, &quot;sha256&quot;).hexdigest()
105+
106+
# https://github.com/opencontainers/distribution-spec/blob/main/spec.md?plain=1#L160
107+
tag_regex = &quot;[a-zA-Z0-9_][a-zA-Z0-9._-]{0,127}&quot;
108+
109+
# the tag must be after a colon, but always at the end of the string
110+
# this avoids conflict with port numbers
111+
image_without_tag = re.sub(f&quot;:{tag_regex}\$&quot;, &quot;&quot;, os.getenv(&quot;IMAGE&quot;))
112+
113+
sbom_blob_url = f&quot;{image_without_tag}@sha256:{sbom_digest}&quot;
114+
115+
with open(os.getenv(&quot;RESULT_PATH&quot;), &quot;w&quot;) as f:
116+
f.write(sbom_blob_url)</content>
117+
<providerId>org.jenkinsci.plugins.configfiles.custom.CustomConfig</providerId>
118+
<customizedCredentialMappings/>
119+
</org.jenkinsci.plugins.configfiles.custom.CustomConfig>
120+
</configs>
121+
</org.jenkinsci.plugins.configfiles.GlobalConfigFiles>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
---
2+
- name: Copy global config files to host
3+
ansible.builtin.copy:
4+
src: files/jenkins-global-config.xml
5+
dest: /tmp/jenkins-global-config.xml
6+
7+
- name: Transfer pipeline files to container
8+
shell: |
9+
JENKINS_POD=$(oc get pod -l deployment=jenkins -n jenkins --no-headers | awk '{ print $1 }')
10+
oc cp /tmp/jenkins-global-config.xml {{ ocp4_workload_trusted_application_pipeline_jenkins_namespace
11+
}}/$JENKINS_POD:/var/lib/jenkins/org.jenkinsci.plugins.configfiles.GlobalConfigFiles.xml -c jenkins
12+
oc delete pod $JENKINS_POD -n {{ ocp4_workload_trusted_application_pipeline_jenkins_namespace
13+
}}
14+
15+
- name: Create Jenkins Secrets
16+
kubernetes.core.k8s:
17+
state: present
18+
definition: "{{ lookup('file', item) | from_yaml }}"
19+
namespace: "{{ ocp4_workload_trusted_application_pipeline_jenkins_namespace }}"
20+
loop:
21+
- external-secret-trustification.yml
22+
- external-secret-gitlab-webhook.yml
23+
- external-secret-common-password.yml
24+
- external-secret-stackrox-token.yml
25+
26+
- name: Create Jenkins Job Runner Resources
27+
kubernetes.core.k8s:
28+
state: present
29+
definition: "{{ lookup('template', item) | from_yaml }}"
30+
loop:
31+
- cluster-role-binding-job-runner-sa-cluster-edit.yml.j2
32+
- sa-jenkins-job-runner.yml.j2
33+
34+
- name: Retrieve cosign signing secret
35+
kubernetes.core.k8s_info:
36+
api_version: v1
37+
kind: Secret
38+
name: signing-secrets
39+
namespace: "{{ ocp4_workload_trusted_application_pipeline_pipelines_namespace }}"
40+
register: r_signing_secrets
41+
retries: 120
42+
delay: 10
43+
until:
44+
- r_signing_secrets is defined
45+
- r_signing_secrets.resources is defined
46+
- r_signing_secrets.resources | length > 0
47+
48+
- name: Creating Cosign Signing Secret
49+
shell: |
50+
oc create secret generic signing-secrets -n {{
51+
ocp4_workload_trusted_application_pipeline_jenkins_namespace }} \
52+
--from-literal=cosign.key={{ r_signing_secrets.resources[0].data['cosign.key'] }} \
53+
--from-literal=cosign.pub={{ r_signing_secrets.resources[0].data['cosign.pub'] }} \
54+
--from-literal=cosign.password={{ r_signing_secrets.resources[0].data['cosign.password'] | b64decode }}
55+
56+
- name: Wait until Jenkins is fully up and running
57+
k8s_info:
58+
api_version: v1
59+
kind: Deployment
60+
name: jenkins
61+
namespace: "{{ ocp4_workload_trusted_application_pipeline_jenkins_namespace }}"
62+
register: r_jenkins
63+
retries: 60
64+
delay: 10
65+
until:
66+
- r_jenkins.resources[0].status is defined
67+
- r_jenkins.resources[0].status.readyReplicas is defined
68+
- r_jenkins.resources[0].status.readyReplicas == r_jenkins.resources[0].spec.replicas
69+
70+
- name: Generate Jenkins API Token
71+
uri:
72+
url: "{{ ocp4_workload_trusted_application_pipeline_jenkins_host }}/me/descriptorByName/jenkins.security.ApiTokenProperty/generateNewToken"
73+
user: admin
74+
password: "{{ ocp4_workload_trusted_application_pipeline_jenkins_admin_password }}"
75+
method: POST
76+
force_basic_auth: true
77+
validate_certs: false
78+
body_format: form-urlencoded
79+
body:
80+
newTokenName: backstage
81+
register: r_jenkins_token
82+
83+
- name: Set Jenkins Token Fact
84+
set_fact:
85+
ocp4_workload_trusted_application_pipeline_jenkins_token: "{{ r_jenkins_token.json.data.tokenValue }}"

ansible/roles_ocp_workloads/ocp4_workload_trusted_application_pipeline/tasks/workload.yml

+12-8
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,9 @@
6868
ocp4_workload_trusted_application_pipeline_tpa_issuer_url: "https://sso-{{
6969
ocp4_workload_trusted_application_pipeline_tpa_namespace }}.{{
7070
r_ingress_config.resources[0].spec.domain }}/realms/chicken"
71+
ocp4_workload_trusted_application_pipeline_jenkins_host: "https://jenkins-{{
72+
ocp4_workload_trusted_application_pipeline_jenkins_namespace }}.{{
73+
r_ingress_config.resources[0].spec.domain }}"
7174

7275
- name: Setup Gitlab dependencies
7376
ansible.builtin.include_tasks:
@@ -84,6 +87,15 @@
8487
loop_control:
8588
loop_var: location
8689

90+
- name: Run RHTAP specific tasks
91+
ansible.builtin.include_tasks: "{{ item }}"
92+
loop:
93+
- setup_cyclonedx_repo_server.yml
94+
- setup_tekton_chains.yml
95+
- setup_stackrox.yml
96+
- setup_tpa_secrets.yml
97+
- setup_jenkins.yml
98+
8799
- name: Setup Backstage dependencies
88100
ansible.builtin.include_tasks:
89101
file: ./setup_backstage.yml
@@ -96,14 +108,6 @@
96108
ansible.builtin.include_tasks:
97109
file: ./setup_devspaces.yml
98110

99-
- name: Run RHTAP specific tasks
100-
ansible.builtin.include_tasks: "{{ item }}"
101-
loop:
102-
- setup_cyclonedx_repo_server.yml
103-
- setup_tekton_chains.yml
104-
- setup_stackrox.yml
105-
- setup_tpa_secrets.yml
106-
107111
- name: Build user output
108112
block:
109113
- name: Set user_list
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
kind: ClusterRoleBinding
2+
apiVersion: rbac.authorization.k8s.io/v1
3+
metadata:
4+
name: jenkins-jobrunner-edit
5+
subjects:
6+
- kind: ServiceAccount
7+
name: job-runner
8+
namespace: {{ ocp4_workload_trusted_application_pipeline_jenkins_namespace }}
9+
roleRef:
10+
apiGroup: rbac.authorization.k8s.io
11+
kind: ClusterRole
12+
name: edit

0 commit comments

Comments
 (0)