Skip to content
This repository has been archived by the owner on Aug 19, 2024. It is now read-only.

Add script and docs for air-gapped/restricted env setup #183

Merged
merged 16 commits into from
Feb 8, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
154 changes: 154 additions & 0 deletions scripts/deploy-mirror-registry.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
#!/bin/bash

# Fail on error
set -e

# example usage:
# ./deploy-mirror-registry.sh \
# --namespace "airgap-registry" \
# --image "registry:2" \
# --storage_class "" \
# --storage_capacity "100Gi" \
# --expose "true" \
# --username "$USER" \
# --password "$PASS"

while [ $# -gt 0 ]; do
if [[ $1 == *"--"* ]]; then
param="${1/--/}"
declare "$param"="$2"
fi
shift
done

declare namespace="${namespace:-"airgap-helper-ns"}"
declare image="${image:-"registry:2"}"
declare storage_capacity=${storage_capacity:-"100Gi"}
declare username="${username:?Must set --username}"
declare password="${password:?Must set --username}"

if ! oc get namespace "${namespace}" > /dev/null 2>&1; then
oc create namespace "${namespace}"
fi

registry_htpasswd=$(htpasswd -Bbn "${username}" "${password}")
cat <<EOF | oc apply -f -
apiVersion: v1
kind: Secret
type: Opaque
metadata:
name: airgap-registry-auth
namespace: "${namespace}"
labels:
app: airgap-registry
stringData:
htpasswd: "${registry_htpasswd}"
EOF

if [ -z "$storage_class" ]; then
# use default storage class
storage_class=$(oc get storageclasses -o=jsonpath='{.items[?(@.metadata.annotations.storageclass\.kubernetes\.io/is-default-class=="true")].metadata.name}')
fi
cat <<EOF | oc apply -f -
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: airgap-registry-storage
namespace: "${namespace}"
spec:
resources:
requests:
storage: "${storage_capacity}"
storageClassName: ${storage_class}
accessModes:
- ReadWriteOnce
EOF

cat <<EOF | oc apply -f -
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: airgap-registry
namespace: "${namespace}"
labels:
app: airgap-registry
spec:
replicas: 1
selector:
matchLabels:
app: airgap-registry
template:
metadata:
labels:
app: airgap-registry
spec:
# -----------------------------------------------------------------------
containers:
- image: "${image}"
name: airgap-registry
imagePullPolicy: IfNotPresent
env:
- name: REGISTRY_AUTH
value: "htpasswd"
- name: REGISTRY_AUTH_HTPASSWD_REALM
value: "RHDH Private Registry"
- name: REGISTRY_AUTH_HTPASSWD_PATH
value: "/auth/htpasswd"
- name: REGISTRY_STORAGE_DELETE_ENABLED
value: "true"
# - name: REGISTRY_HTTP_TLS_CERTIFICATE
# value: "/certs/tls.crt"
# - name: REGISTRY_HTTP_TLS_KEY
# value: "/certs/tls.key"
ports:
- containerPort: 5000
volumeMounts:
- name: registry-vol
mountPath: /var/lib/registry
# - name: tls-vol
# mountPath: /certs
# readOnly: true
- name: auth-vol
mountPath: "/auth"
readOnly: true
# -----------------------------------------------------------------------
volumes:
- name: registry-vol
persistentVolumeClaim:
claimName: airgap-registry-storage
# - name: tls-vol
# secret:
# secretName: airgap-registry-certificate
- name: auth-vol
secret:
secretName: airgap-registry-auth
EOF

cat <<EOF | oc apply -f -
apiVersion: v1
kind: Service
metadata:
name: airgap-registry
namespace: "${namespace}"
labels:
app: airgap-registry
spec:
type: ClusterIP
ports:
- port: 5000
protocol: TCP
targetPort: 5000
selector:
app: airgap-registry
EOF

oc -n "${namespace}" create route edge --service=airgap-registry --insecure-policy=Redirect --dry-run=client -o yaml | oc -n "${namespace}" apply -f -

echo "Registry exposed at: $(oc get route airgap-registry -n "${namespace}" --template='{{ .spec.host }}')"

# TODO
#echo oc edit image.config.openshift.io/cluster and add this registry as insecure if needed
#echo oc get secret/pull-secret -n openshift-config --template='{{index .data ".dockerconfigjson" | base64decode}}' > /tmp/my-global-pull-secret.yaml
#echo oc registry login --registry="<REG>" --auth-basic="<USER>:<PASS>" --to=/tmp/my-global-pull-secret.yaml
#echo oc set data secret/pull-secret -n openshift-config --from-file=.dockerconfigjson=/tmp/my-global-pull-secret.yaml
22 changes: 13 additions & 9 deletions scripts/prepare-restricted-environment.sh
Original file line number Diff line number Diff line change
Expand Up @@ -50,20 +50,20 @@ declare my_operator_index="${my_registry}/${prod_operator_package_name}/${my_ope
declare my_catalog=${prod_operator_package_name}-disconnected-install
declare k8s_resource_name=${my_catalog}

# from https://docs.openshift.com/container-platform/4.14/registry/securing-exposing-registry.html
echo "[INFO] Expose the default registry and log in ..."
oc patch configs.imageregistry.operator.openshift.io/cluster --patch '{"spec":{"defaultRoute":true}}' --type=merge
HOST=$(oc get route default-route -n openshift-image-registry --template='{{ .spec.host }}')
echo "[INFO] Default registry is $HOST"
my_registry="$HOST"
## from https://docs.openshift.com/container-platform/4.14/registry/securing-exposing-registry.html
#echo "[INFO] Expose the default registry and log in ..."
#oc patch configs.imageregistry.operator.openshift.io/cluster --patch '{"spec":{"defaultRoute":true}}' --type=merge
#HOST=$(oc get route default-route -n openshift-image-registry --template='{{ .spec.host }}')
#echo "[INFO] Default registry is $HOST"
#my_registry="$HOST"

# if able to run sudo and update your ca trust store
# oc get secret -n openshift-ingress router-certs-default -o go-template='{{index .data "tls.crt"}}' | base64 -d | sudo tee /etc/pki/ca-trust/source/anchors/${HOST}.crt > /dev/null
# sudo update-ca-trust enable
# sudo podman login -u kubeadmin -p "$(oc whoami -t)" "$HOST"

# else just login with tls disabled
podman login -u kubeadmin -p "$(oc whoami -t)" --tls-verify=false "$HOST"
## else just login with tls disabled
#podman login -u kubeadmin -p "$(oc whoami -t)" --tls-verify=false "$HOST"

# Create local directory
mkdir -p "${my_catalog}/${prod_operator_package_name}"
Expand Down Expand Up @@ -105,7 +105,7 @@ echo "[INFO] Deploying your catalog image to the $my_operator_index registry."
### TODO fix this step or switch to oc adm catalog mirror?
# https://docs.openshift.com/container-platform/4.14/installing/disconnected_install/installing-mirroring-installation-images.html#installation-images-samples-disconnected-mirroring-assist_installing-mirroring-installation-images ?
# FATA[0010] writing manifest: uploading manifest v1.1.0 to default-route-openshift-image-registry.apps.ci-ln-x0yk982-72292.origin-ci-int-gce.dev.rhcloud.com/rhdh/rhdh-index: denied
# skopeo copy --src-tls-verify=false --dest-tls-verify=false --all "containers-storage:$my_operator_index" "docker://$my_operator_index"
skopeo copy --src-tls-verify=false --dest-tls-verify=false --all "containers-storage:$my_operator_index" "docker://$my_operator_index"

echo "[INFO] Removing index image from mappings.txt to prepare mirroring."
oc adm catalog mirror "$my_operator_index" "$my_registry" --insecure --manifests-only | tee catalog_mirror.log
Expand All @@ -118,6 +118,10 @@ echo "[INFO] Mirroring related images to the $my_registry registry."
while IFS= read -r line
do
public_image=$(echo "${line}" | cut -d '=' -f1)
if [[ "$public_image" == registry.redhat.io/rhdh/* ]]; then
rm3l marked this conversation as resolved.
Show resolved Hide resolved
# CI Builds not public yet
public_image=${public_image/registry.redhat.io/quay.io}
nickboldt marked this conversation as resolved.
Show resolved Hide resolved
fi
private_image=$(echo "${line}" | cut -d '=' -f2)
echo "[INFO] Mirroring ${public_image}"
skopeo copy --dest-tls-verify=false --preserve-digests --all "docker://$public_image" "docker://$private_image"
Expand Down