You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
529 lines
14 KiB
529 lines
14 KiB
apiVersion: project.openshift.io/v1
|
|
kind: Project
|
|
metadata:
|
|
annotations:
|
|
argocd.argoproj.io/sync-wave: "0"
|
|
openshift.io/description: ""
|
|
openshift.io/display-name: ""
|
|
labels:
|
|
kubernetes.io/metadata.name: rhacs-operator
|
|
name: rhacs-operator
|
|
spec:
|
|
finalizers:
|
|
- kubernetes
|
|
---
|
|
apiVersion: operators.coreos.com/v1
|
|
kind: OperatorGroup
|
|
metadata:
|
|
annotations:
|
|
argocd.argoproj.io/sync-wave: "5"
|
|
name: rhacs-operator
|
|
namespace: rhacs-operator
|
|
spec:
|
|
upgradeStrategy: Default
|
|
---
|
|
apiVersion: operators.coreos.com/v1alpha1
|
|
kind: Subscription
|
|
metadata:
|
|
annotations:
|
|
argocd.argoproj.io/sync-wave: "10"
|
|
name: rhacs-operator
|
|
namespace: rhacs-operator
|
|
spec:
|
|
channel: rhacs-4.0
|
|
installPlanApproval: Automatic
|
|
name: rhacs-operator
|
|
source: redhat-operators
|
|
sourceNamespace: openshift-marketplace
|
|
startingCSV: rhacs-operator.v4.0.1
|
|
---
|
|
apiVersion: project.openshift.io/v1
|
|
kind: Project
|
|
metadata:
|
|
annotations:
|
|
argocd.argoproj.io/sync-wave: "15"
|
|
openshift.io/description: ""
|
|
openshift.io/display-name: ""
|
|
labels:
|
|
kubernetes.io/metadata.name: stackrox
|
|
name: stackrox
|
|
spec:
|
|
finalizers:
|
|
- kubernetes
|
|
---
|
|
apiVersion: v1
|
|
kind: Secret
|
|
metadata:
|
|
annotations:
|
|
argocd.argoproj.io/sync-wave: "15"
|
|
name: central-admin
|
|
namespace: stackrox
|
|
type: Opaque
|
|
data:
|
|
password: {{ include "acs-admin-password" . | b64enc | quote }}
|
|
---
|
|
apiVersion: platform.stackrox.io/v1alpha1
|
|
kind: Central
|
|
metadata:
|
|
annotations:
|
|
argocd.argoproj.io/sync-wave: "15"
|
|
argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true
|
|
name: stackrox-central-services
|
|
namespace: stackrox
|
|
spec:
|
|
central:
|
|
exposure:
|
|
loadBalancer:
|
|
enabled: false
|
|
port: 443
|
|
nodePort:
|
|
enabled: false
|
|
route:
|
|
enabled: true
|
|
adminPasswordSecret:
|
|
name: central-admin
|
|
db:
|
|
isEnabled: Default
|
|
persistence:
|
|
persistentVolumeClaim:
|
|
claimName: central-db
|
|
persistence:
|
|
persistentVolumeClaim:
|
|
claimName: stackrox-db
|
|
egress:
|
|
connectivityPolicy: Online
|
|
scanner:
|
|
analyzer:
|
|
scaling:
|
|
autoScaling: Enabled
|
|
maxReplicas: 5
|
|
minReplicas: 2
|
|
replicas: 3
|
|
scannerComponent: Enabled
|
|
---
|
|
apiVersion: v1
|
|
kind: ServiceAccount
|
|
metadata:
|
|
annotations:
|
|
argocd.argoproj.io/sync-wave: "20"
|
|
name: stackrox-hook
|
|
namespace: stackrox
|
|
---
|
|
apiVersion: rbac.authorization.k8s.io/v1
|
|
kind: RoleBinding
|
|
metadata:
|
|
annotations:
|
|
argocd.argoproj.io/sync-wave: "20"
|
|
name: stackrox-hook
|
|
namespace: stackrox
|
|
roleRef:
|
|
apiGroup: rbac.authorization.k8s.io
|
|
kind: ClusterRole
|
|
name: edit
|
|
subjects:
|
|
- kind: ServiceAccount
|
|
name: stackrox-hook
|
|
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
|
|
kind: ConfigMap
|
|
metadata:
|
|
annotations:
|
|
argocd.argoproj.io/sync-wave: "20"
|
|
name: stackrox-init-hook
|
|
namespace: stackrox
|
|
data:
|
|
configure-acs.sh: |
|
|
#!/bin/bash
|
|
|
|
set -Eeuo pipefail
|
|
|
|
mkdir -p /tmp/bin
|
|
curl -sfLo /tmp/bin/roxctl https://mirror.openshift.com/pub/rhacs/assets/4.0.0/bin/Linux/roxctl
|
|
chmod 755 /tmp/bin/roxctl
|
|
curl -sLo /tmp/bin/jq https://github.com/stedolan/jq/releases/download/jq-1.6/jq-linux64
|
|
chmod 755 /tmp/bin/jq
|
|
export PATH="/tmp/bin:$PATH"
|
|
|
|
echo "========================================================================"
|
|
echo " Connecting to Red Hat ACS"
|
|
echo "========================================================================"
|
|
echo
|
|
|
|
export ROX_CENTRAL_ADDRESS="$(oc get route central -n stackrox -o go-template='{{ "{{" }}.spec.host}}'):443"
|
|
export ROX_CENTRAL_HOSTNAME="$ROX_CENTRAL_ADDRESS"
|
|
while ! curl -sfko /dev/null "https://$ROX_CENTRAL_ADDRESS/"; do
|
|
echo "Red Hat ACS not ready..."
|
|
sleep 5
|
|
done
|
|
|
|
echo "========================================================================"
|
|
echo " Retrieving an API Token for Red Hat ACS"
|
|
echo "========================================================================"
|
|
echo
|
|
if ! oc get secret stackrox-api-token -n stackrox &>/dev/null; then
|
|
POLICY_JSON='{ "name": "init-token", "role":"Admin"}'
|
|
APIURL="https://$ROX_CENTRAL_ADDRESS/v1/apitokens/generate"
|
|
export ROX_API_TOKEN=$(curl -s -k -u admin:$ROX_ADMIN_PASSWORD -H 'Content-Type: application/json' -X POST -d "$POLICY_JSON" "$APIURL" | jq -r '.token')
|
|
oc create secret generic stackrox-api-token -n stackrox --from-literal=token="$ROX_API_TOKEN"
|
|
else
|
|
export ROX_API_TOKEN="$(oc get secret stackrox-api-token -n stackrox -o go-template --template='{{ "{{" }}.data.token|base64decode}}')"
|
|
fi
|
|
|
|
echo "========================================================================"
|
|
echo " Generating the Cluster Init Bundle"
|
|
echo "========================================================================"
|
|
echo
|
|
|
|
if ! oc get secret admission-control-tls -n stackrox &>/dev/null; then
|
|
roxctl -e "$ROX_CENTRAL_ADDRESS" central init-bundles generate local-cluster --output-secrets /tmp/cluster_init_bundle.yaml
|
|
oc apply -f /tmp/cluster_init_bundle.yaml -n stackrox
|
|
fi
|
|
|
|
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
|
|
kind: Job
|
|
metadata:
|
|
annotations:
|
|
argocd.argoproj.io/sync-wave: "20"
|
|
name: stackrox-init-hook
|
|
namespace: stackrox
|
|
spec:
|
|
backoffLimit: 30
|
|
template:
|
|
spec:
|
|
containers:
|
|
- name: hook
|
|
command:
|
|
- /entrypoint/configure-acs.sh
|
|
args: []
|
|
image: registry.redhat.io/openshift4/ose-cli:v4.13
|
|
imagePullPolicy: IfNotPresent
|
|
env:
|
|
- name: ROX_ADMIN_PASSWORD
|
|
valueFrom:
|
|
secretKeyRef:
|
|
name: central-admin
|
|
key: password
|
|
- name: USER
|
|
value: openshift
|
|
- name: HOME
|
|
value: /tmp
|
|
volumeMounts:
|
|
- mountPath: /entrypoint
|
|
name: stackrox-hook
|
|
readOnly: true
|
|
serviceAccountName: stackrox-hook
|
|
serviceAccount: stackrox-hook
|
|
restartPolicy: OnFailure
|
|
terminationGracePeriodSeconds: 30
|
|
volumes:
|
|
- name: stackrox-hook
|
|
configMap:
|
|
name: stackrox-init-hook
|
|
defaultMode: 0755
|
|
---
|
|
apiVersion: platform.stackrox.io/v1alpha1
|
|
kind: SecuredCluster
|
|
metadata:
|
|
annotations:
|
|
argocd.argoproj.io/sync-wave: "30"
|
|
argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true
|
|
name: stackrox-secured-cluster-services
|
|
namespace: stackrox
|
|
spec:
|
|
auditLogs:
|
|
collection: Auto
|
|
admissionControl:
|
|
listenOnUpdates: true
|
|
bypass: BreakGlassAnnotation
|
|
contactImageScanners: ScanIfMissing
|
|
listenOnCreates: true
|
|
timeoutSeconds: 20
|
|
listenOnEvents: true
|
|
scanner:
|
|
analyzer:
|
|
scaling:
|
|
autoScaling: Enabled
|
|
maxReplicas: 5
|
|
minReplicas: 2
|
|
replicas: 3
|
|
scannerComponent: AutoSense
|
|
perNode:
|
|
collector:
|
|
collection: EBPF
|
|
imageFlavor: Regular
|
|
taintToleration: TolerateTaints
|
|
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
|
|
|