Browse Source

wip

pull/1/head
Nicolas Massé 3 years ago
parent
commit
ac8a0484c3
  1. 39
      README.md
  2. 275
      infrastructure/templates/acs.yaml
  3. 37
      infrastructure/templates/fruits-dev.yaml

39
README.md

@ -1,6 +1,6 @@
# GitOps Artefacts for the MAD Roadshow France 2023 # GitOps Artefacts for the MAD Roadshow France 2023
## Pre-requisites ## Deploy OpenShift resources with OpenShift GitOps
* Install the OpenShift GitOps operator. * Install the OpenShift GitOps operator.
@ -21,25 +21,46 @@ oc get route -n openshift-gitops openshift-gitops-server -o jsonpath='https://{.
* Payload URL: *url above* * Payload URL: *url above*
* Content-Type: Application/json * Content-Type: Application/json
* Create the required namespaces. * Give cluster-admin access rights to the **OpenShift Gitops** operator.
```sh ```sh
oc new-project fruits-dev oc adm policy add-cluster-role-to-user cluster-admin system:serviceaccount:openshift-gitops:openshift-gitops-argocd-application-controller
``` ```
* Label the `fruits-dev` namespace with argocd annotations
```sh ```sh
oc label namespace fruits-dev argocd.argoproj.io/managed-by=openshift-gitops cp infrastructure.yaml.sample infrastructure.yaml
oc apply -f infrastructure.yaml -n openshift-gitops
``` ```
* Give admin access rights on the **fruits-dev** namespace to the **OpenShift Gitops** operator. ## Create the Helm repository
```sh ```sh
oc adm policy add-role-to-user admin -n fruits-dev system:serviceaccount:openshift-gitops:openshift-gitops-argocd-application-controller sudo dnf install awscli2 rclone
aws configure
aws s3api list-buckets --output text
aws s3api create-bucket --bucket mad-roadshow-france-2023-helm-charts --create-bucket-configuration LocationConstraint=eu-west-3 --region eu-west-3
aws s3api put-public-access-block --bucket "mad-roadshow-france-2023-helm-charts" --public-access-block-configuration "BlockPublicPolicy=false"
aws s3api put-bucket-policy --bucket mad-roadshow-france-2023-helm-charts --policy '{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "PublicReadGetObject",
"Effect": "Allow",
"Principal": "*",
"Action": [
"s3:GetObject"
],
"Resource": [
"arn:aws:s3:::mad-roadshow-france-2023-helm-charts/*"
]
}
]
}'
rclone config
rclone ls aws:mad-roadshow-france-2023-helm-charts
``` ```
## Deploy Postgres CrunchyDB ## Deploy Postgres CrunchyDB
1. Create a namespace ***preprod-database*** 1. Create a namespace ***preprod-database***

275
infrastructure/templates/acs.yaml

@ -125,12 +125,45 @@ subjects:
name: stackrox-hook name: stackrox-hook
namespace: stackrox namespace: stackrox
--- ---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
annotations:
argocd.argoproj.io/sync-wave: "20"
name: stackrox-hook-scc
namespace: stackrox
rules:
- apiGroups:
- security.openshift.io
resourceNames:
- anyuid
resources:
- securitycontextconstraints
verbs:
- use
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
annotations:
argocd.argoproj.io/sync-wave: "20"
name: stackrox-hook-scc
namespace: stackrox
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: stackrox-hook-scc
subjects:
- kind: ServiceAccount
name: stackrox-hook
namespace: stackrox
---
apiVersion: v1 apiVersion: v1
kind: ConfigMap kind: ConfigMap
metadata: metadata:
annotations: annotations:
argocd.argoproj.io/sync-wave: "20" argocd.argoproj.io/sync-wave: "20"
name: stackrox-hook name: stackrox-init-hook
namespace: stackrox namespace: stackrox
data: data:
configure-acs.sh: | configure-acs.sh: |
@ -182,6 +215,211 @@ data:
exit 0 exit 0
--- ---
apiVersion: v1
kind: ConfigMap
metadata:
annotations:
argocd.argoproj.io/sync-wave: "20"
name: stackrox-configure-hook
namespace: stackrox
data:
entrypoint.sh: |
#!/bin/bash
set -Eeuo pipefail
ansible-galaxy collection install community.general
ansible-playbook configure.yaml
exit 0
configure.yaml: |
- name: Configure RHACS
hosts: localhost
gather_facts: no
vars:
ansible_connection: local
acs_api: https://{{ central_hostname }}/v1
validate_certs: no
tasks:
- name: Get Stackrox central's Route
kubernetes.core.k8s_info:
api_version: route.openshift.io/v1
kind: Route
name: central
namespace: stackrox
register: central_route
failed_when: central_route.resources|length == 0
until: central_route is succeeded
retries: 60
delay: 5
- set_fact:
central_hostname: '{{ central_route.resources[0].spec.host }}:443'
- name: Get Stackrox central's admin password
kubernetes.core.k8s_info:
api_version: v1
kind: Secret
name: central-admin
namespace: stackrox
register: admin_secret
failed_when: admin_secret.resources|length == 0
until: admin_secret is succeeded
retries: 60
delay: 5
- set_fact:
central_admin_password: '{{ admin_secret.resources[0].data.password | b64decode }}'
- name: Get Cosign public key
kubernetes.core.k8s_info:
api_version: v1
kind: Secret
name: code-signature
namespace: fruits-dev
register: cosign_secret
failed_when: cosign_secret.resources|length == 0
until: cosign_secret is succeeded
retries: 60
delay: 5
- set_fact:
cosign_public_key: '{{ cosign_secret.resources[0].data["cosign.pub"] | b64decode }}'
- name: Check if jmespath is available locally
debug: msg={{ dummy|json_query('@') }}
register: check_jmespath
ignore_errors: yes
vars:
dummy: Hello World
- name: Ensure JMESPath is installed
assert:
that:
- 'check_jmespath is success'
msg: >
The JMESPath library is required by this playbook.
Please install the JMESPath library with 'pip install jmespath'.
- name: Find signature integrations
uri:
url: '{{ acs_api }}/signatureintegrations'
validate_certs: '{{ validate_certs }}'
url_username: admin
url_password: '{{ central_admin_password }}'
force_basic_auth: yes
register: find_signature_integrations_response
changed_when: false
- set_fact:
signature_integration_id: '{{ (find_signature_integrations_response.json | json_query(query) | first).id }}'
when: find_signature_integrations_response.json | json_query(query) | count > 0
vars:
query: integrations[?name == `Sigstore`]
- name: Create the Cosign signature integration
uri:
url: '{{ acs_api }}/signatureintegrations'
method: POST
status_code: "200"
validate_certs: '{{ validate_certs }}'
url_username: admin
url_password: '{{ central_admin_password }}'
body: '{{ integration }}'
body_format: json
force_basic_auth: yes
register: create_signature_integration_response
changed_when: create_signature_integration_response.status == 200
when: signature_integration_id is not defined
vars:
integration:
name: Sigstore
cosign:
publicKeys:
- name: cosign.pub
publicKeyPemEnc: '{{ cosign_public_key }}'
- set_fact:
signature_integration_id: '{{ create_signature_integration_response.json.id }}'
when: signature_integration_id is not defined
- debug:
var: signature_integration_id
- name: Find policies
uri:
url: '{{ acs_api }}/policies?query=Policy%3AImage%20is%20not%20signed'
validate_certs: '{{ validate_certs }}'
url_username: admin
url_password: '{{ central_admin_password }}'
force_basic_auth: yes
register: find_policies_response
changed_when: false
- set_fact:
policy_id: '{{ (find_policies_response.json.policies | first).id }}'
when: find_policies_response.json.policies | count > 0
- name: Create the policy
uri:
url: '{{ acs_api }}/policies'
method: POST
status_code: "200"
validate_certs: '{{ validate_certs }}'
url_username: admin
url_password: '{{ central_admin_password }}'
body: '{{ policy }}'
body_format: json
force_basic_auth: yes
register: create_policy_response
changed_when: create_policy_response.status == 200
when: policy_id is not defined
vars:
policy:
SORTEnforcement: no
SORTLifecycleStage: ''
SORTName: ''
categories:
- Security Best Practices
criteriaLocked: no
description: The container image has not been digitally signed.
disabled: no
enforcementActions:
- SCALE_TO_ZERO_ENFORCEMENT
- UNSATISFIABLE_NODE_CONSTRAINT_ENFORCEMENT
eventSource: NOT_APPLICABLE
exclusions: []
isDefault: no
lifecycleStages:
- DEPLOY
mitreAttackVectors: []
mitreVectorsLocked: no
name: Image is not signed
notifiers: []
policySections:
- policyGroups:
- booleanOperator: OR
fieldName: Image Signature Verified By
negate: no
values:
- value: "{{ signature_integration_id }}"
sectionName: Policy Section 1
policyVersion: '1.1'
rationale: The container image MUST be digitally signed in order to prevent tampering.
remediation: Use cosign to sign this image. See https://docs.sigstore.dev/cosign/signing_with_containers/
scope:
- cluster:
label:
namespace: dev
severity: CRITICAL_SEVERITY
- set_fact:
policy_id: '{{ create_policy_response.json.id }}'
when: policy_id is not defined
- debug:
var: policy_id
---
apiVersion: batch/v1 apiVersion: batch/v1
kind: Job kind: Job
metadata: metadata:
@ -221,7 +459,7 @@ spec:
volumes: volumes:
- name: stackrox-hook - name: stackrox-hook
configMap: configMap:
name: stackrox-hook name: stackrox-init-hook
defaultMode: 0755 defaultMode: 0755
--- ---
apiVersion: platform.stackrox.io/v1alpha1 apiVersion: platform.stackrox.io/v1alpha1
@ -256,3 +494,36 @@ spec:
imageFlavor: Regular imageFlavor: Regular
taintToleration: TolerateTaints taintToleration: TolerateTaints
clusterName: local-cluster clusterName: local-cluster
---
apiVersion: batch/v1
kind: Job
metadata:
annotations:
argocd.argoproj.io/sync-wave: "20"
name: stackrox-configure-hook
namespace: stackrox
spec:
backoffLimit: 30
template:
spec:
containers:
- name: hook
command:
- /playbooks/entrypoint.sh
args: []
image: registry.redhat.io/ansible-automation-platform-21/ee-supported-rhel8:1.0
imagePullPolicy: IfNotPresent
volumeMounts:
- mountPath: /playbooks
name: stackrox-hook
readOnly: true
workingDir: /playbooks
serviceAccountName: stackrox-hook
serviceAccount: stackrox-hook
restartPolicy: OnFailure
terminationGracePeriodSeconds: 30
volumes:
- name: stackrox-hook
configMap:
name: stackrox-configure-hook
defaultMode: 0755

37
infrastructure/templates/fruits-dev.yaml

@ -36,6 +36,35 @@ subjects:
name: cosign-hook name: cosign-hook
namespace: fruits-dev namespace: fruits-dev
--- ---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
annotations:
argocd.argoproj.io/sync-wave: "20"
name: secret-reader
namespace: fruits-dev
rules:
- apiGroups: [""]
resources: ["secrets"]
verbs: ["get", "list", "watch"]
---
# The stackrox hook needs to be able to read the cosign public key in order to create the sigstore policy
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
annotations:
argocd.argoproj.io/sync-wave: "20"
name: stackrox-hook
namespace: fruits-dev
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: secret-reader
subjects:
- kind: ServiceAccount
name: stackrox-hook
namespace: stackrox
---
apiVersion: v1 apiVersion: v1
kind: ConfigMap kind: ConfigMap
metadata: metadata:
@ -59,7 +88,13 @@ data:
echo " Generating a keypair" echo " Generating a keypair"
echo "========================================================================" echo "========================================================================"
echo echo
cosign generate-key-pair --kms k8s://fruits-dev/code-signature
## Move to /tmp before creating the keypair because of:
# Error: open cosign.pub: permission denied
# main.go:74: error during command execution: open cosign.pub: permission denied
cd /tmp
COSIGN_PASSWORD=dummy cosign generate-key-pair k8s://fruits-dev/code-signature
fi fi
exit 0 exit 0

Loading…
Cancel
Save