Skip to content

Commit

Permalink
Enable the quay bridge operator by default in the opp policyset
Browse files Browse the repository at this point in the history
This sets up and configures the quay bridge operator by default
in the opp policysets.  The quay bridge operator is deployed to all
openshift managed clusters and will trust the default cert from the
hub for the image registry.

This will allow a cross product interop test for OPP since now an
application can be deployed that uses quay's image registry which is
on ODF. ACS will scan the registry.  ACM will manage the app deployment.

Signed-off-by: Gus Parvin <[email protected]>
(cherry picked from commit 0ca216a)
  • Loading branch information
gparvin authored and openshift-merge-bot[bot] committed Mar 1, 2024
1 parent 80bea90 commit 9964b25
Show file tree
Hide file tree
Showing 5 changed files with 201 additions and 64 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -33,64 +33,127 @@ spec:
- |
#!/usr/bin/env bash
# Wait for quay to be ready
attempt_counter=0
max_attempts=80
echo "Waiting for quay to be available..."
until $(curl --output /dev/null --silent --head --fail http://registry-quay-app); do
if [ ${attempt_counter} -eq ${max_attempts} ];then
echo "Max attempts reached"
exit 1
function quay_cmd() {
DATA='{}'
if [ ! -z "$4" ]; then
DATA=$4
fi
echo "[$1] $2 $3 --data $DATA" 1>&2
AUTH="Fake: dummy"
if [ $1 = "Basic" ]; then
COUNT=$(oc -n $QUAY_NAMESPACE get --ignore-not-found=true secret $QUAY_USER_SECRET | wc -l)
if [ $COUNT -gt 1 ]; then
BASIC=$(oc -n $QUAY_NAMESPACE extract secret/$QUAY_USER_SECRET --keys=basic --to=-)
fi
AUTH="Authorization: Basic $BASIC"
printf '.'
attempt_counter=$(($attempt_counter+1))
echo "Made attempt $attempt_counter, waiting..."
sleep 30
elif [ $1 = "Bearer" ]; then
AUTH="Authorization: Bearer $TOKEN"
fi
curl -X $2 $CURL_OPTS -H 'Content-Type: application/json' -H "$AUTH" https://$QUAY_HOST$3 --data "$DATA"
echo "[INFO] Success" 1>&2
}
echo -n "Waiting for the Quay Registry CR to be available ."
RC=$(oc wait QuayRegistry -n local-quay registry --for=condition=Available=true > /dev/null 2>&1;echo $?)
while [ $RC -ne 0 ]; do
sleep 2
echo -n "."
RC=$(oc wait QuayRegistry -n local-quay registry --for=condition=Available=true > /dev/null 2>&1;echo $?)
done
echo "done"
QUAYHOST=$(oc get route -n local-quay registry-quay -o jsonpath='{.spec.host}')
CURL_OPTS="-fsk"
QUAY_ADMIN=quayadmin
QUAY_USER=quaydevel
QUAY_USER_SECRET=$QUAY_USER
QUAY_NAMESPACE=local-quay
QUAY_HOST=$(oc get route -n $QUAY_NAMESPACE registry-quay -o jsonpath='{.spec.host}')
QUAY_ORG=devel
[email protected]
QUAY_REPO=example
if [ $? -ne 0 ]; then
echo "Quay route does not exist yet, please wait and try again."
exit 1
fi
RESULT=$(oc get secret -n local-quay quayadmin)
RESULT=$(oc get secret -n $QUAY_NAMESPACE $QUAY_USER_SECRET)
if [ $? -eq 0 ]; then
echo "Quay user configuration secret already exists: quayadmin in namespace local-quay"
echo "Quay user configuration secret already exists: $QUAY_USER_SECRET in namespace $QUAY_NAMESPACE"
exit 1
fi
ADMINPASS=`head -c 8 /dev/urandom | base64 | sed 's/=//'`
RESULT=$(curl -X POST -k -s https://$QUAYHOST/api/v1/user/initialize --header 'Content-Type: application/json' --data "{ \"username\": \"quayadmin\", \"password\":\"${ADMINPASS}\", \"email\": \"[email protected]\", \"access_token\": true}")
BASE64AUTH=`echo -n $QUAY_USER:$QUAY_PASSWORD | base64 -w0`
RESULT=$(curl -X POST -k -s https://$QUAY_HOST/api/v1/user/initialize --header 'Content-Type: application/json' --data "{ \"username\": \"quayadmin\", \"password\":\"${ADMINPASS}\", \"email\": \"[email protected]\", \"access_token\": true}")
echo "$RESULT" | grep -q "non-empty database"
if [ $? -eq 0 ]; then
echo "Quay user configuration failed, the database has been initialized."
exit 1
else
cat <<EOF | kubectl create -f -
apiVersion: v1
kind: Secret
metadata:
name: quayadmin
namespace: local-quay
type: Opaque
data:
password: $(echo ${ADMINPASS} | base64)
EOF
echo "Quay password successfully set for user quayadmin and stored in secret local-quay/quayadmin."
echo "[INFO] Destroy any previous secrets ..."
oc -n $QUAY_NAMESPACE delete --ignore-not-found=true secret $QUAY_USER_SECRET
echo "[INFO] Creating quay admin secret quayadmin ..."
TOKEN=$(echo "$RESULT" | tr ',' '\n' | grep access_token | awk -F: '{print $2}' | sed 's/"//g')
cat <<EOF | kubectl create -f -
apiVersion: v1
kind: Secret
metadata:
name: quay-api-token
type: Opaque
data:
token: $(echo ${TOKEN} | base64)
EOF
echo "Quay token successfully obtained and stored in secret quay-api-token."
oc -n $QUAY_NAMESPACE create secret generic quayadmin --from-literal=token=$TOKEN --from-literal=password=$ADMINPASS --from-literal=basic="$BASE64AUTH"
echo "[INFO] Creating $QUAY_USER user ..."
RESPONSE=$(quay_cmd Bearer POST /api/v1/superuser/users/ "{ \"username\": \"$QUAY_USER\", \"email\": \"$QUAY_USER_EMAIL\", \"access_token\": true}")
QUAY_PASSWORD=$(echo $RESPONSE | tr ',' '\n' | grep '"password"' | cut -d \" -f 4)
BASE64AUTH=`echo -n $QUAY_USER:$QUAY_PASSWORD | base64 -w0`
echo "[INFO] Creating $QUAY_USER_SECRET secret ..."
oc -n $QUAY_NAMESPACE create secret generic $QUAY_USER_SECRET --from-literal=password="$QUAY_PASSWORD" --from-literal=basic="$BASE64AUTH"
echo "[INFO] Creating quay-pull-secret ..."
echo -e "{ \"auths\": { \"$QUAY_HOST\": { \"auth\": \"$BASE64AUTH\" } }}" | oc -n $QUAY_NAMESPACE create secret generic quay-pull-secret --from-file=.dockerconfigjson=/dev/stdin --type=kubernetes.io/dockerconfigjson
echo "[INFO] Creating quay integration token secret ..."
oc -n $QUAY_NAMESPACE create secret generic quay-integration --from-literal=token=$TOKEN
fi
echo "[INFO] Looking for initial organization ..."
COUNT=$(quay_cmd Bearer GET /api/v1/organization/$QUAY_ORG | grep -v not_found | wc -l)
if [ $COUNT = 0 ]; then
echo "[INFO] Creating $QUAY_ORG org ..."
# Email cannot be shared with the initial user
quay_cmd Bearer POST /api/v1/organization/ "{\"name\": \"$QUAY_ORG\", \"email\": \"$QUAY_ORG_EMAIL\" }"
quay_cmd Basic GET /api/v1/organization/$QUAY_ORG
fi
echo "[INFO] Looking for org application ..."
# The only way to get another OAuth token is to go to: Organization -> Applications -> {app} -> Generate Token
# If there was a programatic way to do it here, we could avoid the problem with the bearer token expiring after 150min
APPLICATION=automation
COUNT=$(quay_cmd Bearer GET /api/v1/organization/$QUAY_ORG/applications | grep $APPLICATION | wc -l)
if [ $COUNT = 0 ]; then
echo "[INFO] Creating $APPLICATION application..."
quay_cmd Bearer POST /api/v1/organization/$QUAY_ORG/applications "{\"name\": \"$QUAY_ORG-automation\", \"description\": \"automation app\" }"
fi
echo "[INFO] Looking for initial repo ..."
COUNT=$(quay_cmd Bearer GET /api/v1/repository/$QUAY_ORG/$QUAY_REPO | grep -v not_found | wc -l)
if [ $COUNT = 0 ]; then
echo "[INFO] Creating $QUAY_REPO repo..."
quay_cmd Bearer POST /api/v1/repository "{\"namespace\":\"$QUAY_ORG\", \"repository\":\"$QUAY_REPO\", \"visibility\":\"public\", \"description\":\"Development Repo\", \"repo_kind\":\"image\"}"
fi
echo "[INFO] Looking for $QUAY_ORG members ..."
COUNT=$(quay_cmd Bearer GET /api/v1/organization/$QUAY_ORG/team/owners/members | grep "name\": \"$QUAY_USER\"" | wc -l)
if [ $COUNT = 0 ]; then
echo "[INFO] Associating $QUAY_USER with $QUAY_ORG ..."
quay_cmd Bearer PUT /api/v1/organization/$QUAY_ORG/team/owners/members/$QUAY_USER '{}'
fi
echo "[INFO] Looking for $QUAY_REPO admins ..."
COUNT=$(quay_cmd Bearer GET /api/v1/repository/$QUAY_ORG/$QUAY_REPO/permissions/user/$QUAY_USER | grep '"role": "admin"' | wc -l)
if [ $COUNT = 0 ]; then
echo "[INFO] Give $QUAY_USER admin rights to the repo ..."
quay_cmd Bearer PUT /api/v1/repository/$QUAY_ORG/$QUAY_REPO/permissions/user/$QUAY_USER '{ "role": "admin"}'
fi
echo "[INFO] Job finished"
image: image-registry.openshift-image-registry.svc:5000/openshift/cli:latest
imagePullPolicy: Always
name: create-admin-user
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,24 @@ spec:
source: redhat-operators
sourceNamespace: openshift-marketplace
---
kind: Secret
type: Opaque
metadata:
name: quay-integration
namespace: openshift-operators
apiVersion: v1
data:
token: '{{ fromSecret "local-quay" "quay-integration" "token" }}'
---
kind: Secret
type: Opaque
metadata:
name: quay-integration
namespace: policies
apiVersion: v1
data:
token: '{{ fromSecret "local-quay" "quay-integration" "token" }}'
---
apiVersion: quay.redhat.com/v1
kind: QuayIntegration
metadata:
Expand All @@ -25,11 +43,29 @@ spec:
insecureRegistry: false
quayHostname: https://{{ fromConfigMap "policies" "quay-config" "host" }}
---
kind: Secret
type: Opaque
apiVersion: v1
data:
'{{ (lookup "route.openshift.io/v1" "Route" "local-quay" "registry-quay" ).spec.host }}': |
{{ ( fromSecret "openshift-ingress-operator" "router-ca" "tls.crt" ) | base64dec | autoindent }}
kind: ConfigMap
metadata:
name: quay-integration
namespace: policies
name: opp-ingres-ca
namespace: openshift-config
---
apiVersion: config.openshift.io/v1
kind: Image
metadata:
name: cluster
spec:
additionalTrustedCA:
name: opp-ingres-ca
---
apiVersion: v1
data:
token: '{{ fromSecret "openshift-operators" "quay-integration" "token" }}'
registry-quay-local-quay: |
{{ ( fromSecret "openshift-ingress-operator" "router-ca" "tls.crt" ) }}
kind: Secret
metadata:
name: opp-ingres-ca
namespace: policies
type: Opaque
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,22 @@ rules:
- create
- patch
- update
- delete
- apiGroups:
- route.openshift.io
resources:
- routes
verbs:
- get
- list
- apiGroups:
- quay.redhat.com
resources:
- quayregistries
verbs:
- get
- list
- watch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
Expand Down Expand Up @@ -73,7 +82,7 @@ spec:
---
apiVersion: v1
data:
config.yaml: RkVBVFVSRV9VU0VSX0lOSVRJQUxJWkU6IHRydWUKQlJPV1NFUl9BUElfQ0FMTFNfWEhSX09OTFk6IGZhbHNlClNVUEVSX1VTRVJTOgotIHF1YXlhZG1pbgpGRUFUVVJFX1VTRVJfQ1JFQVRJT046IHRydWUK
config.yaml: RkVBVFVSRV9VU0VSX0lOSVRJQUxJWkU6IHRydWUKQlJPV1NFUl9BUElfQ0FMTFNfWEhSX09OTFk6IGZhbHNlClNVUEVSX1VTRVJTOgotIHF1YXlhZG1pbgpGRUFUVVJFX1VTRVJfQ1JFQVRJT046IHRydWUKRkVBVFVSRV9TVVBFUlVTRVJTX0ZVTExfQUNDRVNTOiB0cnVlCg==
kind: Secret
metadata:
name: init-config-bundle-secret
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,29 @@ metadata:
apiVersion: v1
data:
token: '{{hub fromSecret "" "quay-integration" "token" hub}}'
---
apiVersion: v1
data:
quay-integration: '{{hub fromSecret "policies" "opp-ingres-ca" "registry-quay-local-quay" hub}}'
kind: Secret
metadata:
name: opp-ingres-ca
namespace: openshift-config
type: Opaque
---
apiVersion: v1
data:
'{{hub fromConfigMap "" "quay-config" "host" hub}}': |
{{ ( fromSecret "openshift-config" "opp-ingres-ca" "quay-integration" ) | base64dec | autoindent }}
kind: ConfigMap
metadata:
name: opp-ingres-ca
namespace: openshift-config
---
apiVersion: config.openshift.io/v1
kind: Image
metadata:
name: cluster
spec:
additionalTrustedCA:
name: opp-ingres-ca
Original file line number Diff line number Diff line change
Expand Up @@ -172,27 +172,30 @@ policies:
manifests:
- path: input-quay/policy-quay-status.yaml
remediationAction: inform
# Quay Bridge requires a token that needs to be populated in a secret. Uncomment the following
# 2 policies if you need to use the quay bridge. After quay is running, see the instructions:
# Quay Bridge is configured with a temporary token that will expire quickly after
# deployment. After quay is running, see the instructions:
# https://hybrid-cloud-patterns.io/devsecops/getting-started/#completing-the-quay-bridge-with-a-bearer-token
# The command below is needed to place the secret where the policies expect to find it.
# oc create secret -n openshift-operators generic quay-integration --from-literal=token=<access_token>
#- name: policy-hub-quay-bridge
# categories:
# - SI System and Information Integrity
# controls:
# - SI-7 Software Firmware and Information Integrity
# manifests:
# - path: input-quay/policy-hub-quay-bridge.yaml
#- name: policy-quay-bridge
# categories:
# - SI System and Information Integrity
# controls:
# - SI-7 Software Firmware and Information Integrity
# manifests:
# - path: input-quay/policy-quay-bridge.yaml
# policySets:
# - openshift-plus-clusters
# Update the token in the quayadmin secret in the local-quay namespace with your
# bearer token. It will be propagated to the managed clusters automatically.
- name: policy-hub-quay-bridge
categories:
- SI System and Information Integrity
controls:
- SI-7 Software Firmware and Information Integrity
dependencies:
- name: policy-quay-status
manifests:
- path: input-quay/policy-hub-quay-bridge.yaml
- name: policy-quay-bridge
categories:
- SI System and Information Integrity
controls:
- SI-7 Software Firmware and Information Integrity
manifests:
- path: input-quay/policy-quay-bridge.yaml
orderManifests: true
policySets:
- openshift-plus-clusters
# Quay Policies - end
# Compliance Operator Policies - start
- name: policy-compliance-operator-install
Expand Down

0 comments on commit 9964b25

Please sign in to comment.