Skip to content

Instantly share code, notes, and snippets.

@v1k0d3n
Last active October 14, 2024 15:50
Show Gist options
  • Save v1k0d3n/ffbba6fd2908ecb1b30b87780ff6d8b1 to your computer and use it in GitHub Desktop.
Save v1k0d3n/ffbba6fd2908ecb1b30b87780ff6d8b1 to your computer and use it in GitHub Desktop.
PanOS Installation for OCP Virtualization 4.16+

Overview

First off, I'm really glad you're reading through this guide. I put a lot of effort into it. Because of this, there's a lot of information packed within this Gist guide. None of it is difficult, but please read through it carefully so you have the best outcome.

There are some concepts you may already be familiar with, but some you may not be as familiar with as well (i.e. you may not be aware of Palo Alto's Bootstrapper process, even if you've been a firewall admin for a long time).

As a security-architect-turned-platform-architect for a very large service provider for much of my career, I want the most perfect experience possible (combining both security + safe GitOps). There are no shortcuts here. So if you see something you have questions about, please feel free to put your questions below! I will be happy to assist in any way that I can. The goal is to make sure your PoC is interesting and successful.

Start a VM in OpenShift Virtualization

This Gist assumes that you are coming from the original GitHub Gist located HERE. The goal for this Gist is to get a Palo Alto VM running on OpenShift Virtualization. These steps assumed you have performed the following steps first:

  • You have set up OpenShift Storage, or some other CSI-based storage option that is supported from OpenShift Virtualization.
  • You have SR-IOV supported device NICs available and configured within your OpenShift cluster (more on this below).
  • A private registry is required for PanOS/Panorama images (QCOW2 images stored in an OCI-compliant container image format). I'll provide detailed instructions on how to use a free, private registry on Red Hat's Quay.io ([down below](Build PanOS and Panorama Boot Images)), however you can use your own private registry if you'd like.

Create a New RHEL 8/9 or Fedora VM on OpenShift Virtualization

The goal of this document is to dog-food your newly created OpenShift Virtualization environment for engineering and management. Start a new RHEL or Fedora virtual machine within OpenShift Virtualization.

  • Where you see (Fedora) at the beginning of a Step number below, you will use your Fedora or RHEL virtual machine in OCPV.
  • Where you see a (Workstation) at the beginning of a Step number below, you will use your own PC or workstation. Please note that I am using a MacBook Pro for my Workstation, so some of my commands may vary just slightly from your own (although I tried to take some of this into account within my instructions below).

PanOS Touchless Self-IP, License Registration, and Panorama Management

Some of the instructions below are taking advantage of Palo Alto's Bootstrap Package method, using an older (yet still working) PanOS-Bootstrapper Utility on GitHub. This project will create a companion ISO that is attached while the VM first comes online, and it will do the following:

  • Automatically set the management IP Address
  • License the Firewall
  • Check into Panorama and pull down rules and configuration

This is all done automatically, and completely touchless from the administrator. All you have to do is follow these instructions, and begin the demonstration below.

With these things now out of the way (and potentially clarified as far as goals are concerned), let's begin!

Part I: Install Prerequisites

  1. (Fedora) Update the system and install Git and ansible
    sudo yum update -yy && sudo yum install -yy git podman tree

Part II: Configuration Prerequisites

  1. (Fedora) Set the global user/email for Git

    git config --global user.name "Brandon B. Jozsa"
    git config --global user.email "[email protected]"
  2. (Fedora) Create the following directories that we will use throughout this project

    mkdir -p {~/development/dockerfiles/panorama/,~/development/dockerfiles/panos/,~/development/panos-images/,~/Downloads/,~/.kube/}
  3. (Fedora) Download the follow Dockerfiles for Panorama and PanOS:

    curl -L https://gist.githubusercontent.com/v1k0d3n/ffbba6fd2908ecb1b30b87780ff6d8b1/raw/9938d64e682bb9e84948d906c7d6704e21a63dc7/Dockerfile-panos -o ~/development/dockerfiles/panos/Dockerfile
    
    curl -L https://gist.githubusercontent.com/v1k0d3n/ffbba6fd2908ecb1b30b87780ff6d8b1/raw/9938d64e682bb9e84948d906c7d6704e21a63dc7/Dockerfile-panorama -o ~/development/dockerfiles/panorama/Dockerfile
  4. (Fedora) Make sure that the Fedora host has the oc and virtctl Linux binaries. First make sure that your Fedora environment has a ~/.kube/ directory and then copy the kubeconfig into that directory, but as named config. If this is confusing, please review this documentation.

    • Details: Copy the downloaded kubeconfig from your cluster and name it ~/.kube/config on the Fedora host.
  5. (Fedora) Get the latest oc Linux binary for OpenShift:

    curl -L https://mirror.openshift.com/pub/openshift-v4/clients/ocp/stable-4.16/openshift-client-linux-4.16.10.tar.gz -o ~/Downloads/openshift-client-linux-4.16.10.tar.gz
  6. (Workstation) Download the virtctl binary for Linux by going to the OpenShift console and clicking on the top right-hand corner on the ? (question mark), and clicking on Command Line Tools. Download the one that says Download virtctl for Linux for x86_64.

  7. (Workstation) Set a variable on your workstation that will make life easier later when we copy files from your workstation to your Fedora VM. You want to put YOUR FEDORA IP ADDRESS as the variable below:

    primary_ip="PUT_YOUR_IP_HERE_AND_KEEP_QUOTES"
  8. (Workstation > Fedora) Use scp or some other utility to the virtctl.tar.gz tarball to the Fedora virtual machine.

    STOP: Change the information below to match your own environment. This includes the $USER and the variable you set earlier ($primary_ip), because these will be different for each environment.

    scp ~/Downloads/virtctl.tar.gz  fedora@$primary_ip:/home/fedora/Downloads/virtctl.tar.gz
  9. (Fedora) Back on the Fedora virtual machine, unpack both of these packages and copy the executables to /usr/local/bin/

    # Go to the ~/Downloads folder, and untar the binaries for oc, kubectl, and virtctl:
    cd ~/Downloads/
    tar zxvf openshift-client-linux-4.16.10.tar.gz
    tar zxvf virtctl.tar.gz
    
    # Copy the binaries to /usr/local/bin/:
    sudo cp virtctl /usr/local/bin/
    sudo cp oc /usr/local/bin/
    sudo cp kubectl /usr/local/bin/
  10. (Fedora) Check that you can communicate with OpenShift:

    [fedora@fedora-panos-devel-3 Downloads]$ oc get nodes
    NAME       STATUS   ROLES                         AGE     VERSION
    roderika   Ready    control-plane,master,worker   5d23h   v1.29.7+4510e9c

Part III: Run the PanOS-Bootstrapper Utility

  1. (Fedora) Run the following podman command:

    sudo podman run -d --network=host paloaltonetworks/panos-bootstrapper:latest
  2. (Fedora) Get the IP address of your server, and then create following variable with that IP where the PUT_YOUR_IP_HERE_AND_KEEP_QUOTES notation is below:

    IMPORTANT: Get the IP address of your Fedora VM first with the following command:

    ip addr

    When you find the IP address you need, enter it as a variable (primary_ip).

    primary_ip="PUT_YOUR_IP_HERE_AND_KEEP_QUOTES"
  3. (Fedora) Change into the following directory called panos-images:

    cd ~/development/panos-images/
  4. (Fedora) Look at the following sample. Configure your firewall variables to match your own deployment/environment:

    IMPORTANT: The auth_code will be the authorization code for your Palo Alto VM-series firewall license. You may need to check your email for this code.

    # Set variables to be used in the curl command below:
    hostname="panos-01"
    management_ip="192.168.3.105/24"
    management_gateway="192.168.3.1"
    dns_servers='["192.168.3.5", "192.168.3.5"]'
    auth_code="REMOVED"
    panorama_ip="192.168.3.95"
    panorama_port="3978"
    timezone="UTC"
    
    # Use the following code to generate an ISO that will be used to configure your firewall (ZTP):
    curl -X POST http://$primary_ip:5000/bootstrap_kvm \
        -H "Content-Type: application/json" \
        -d '{
            "hostname": "'"$hostname"'",
            "archive_type": "iso",
            "management_ip": "'"$management_ip"'",
            "management_gateway": "'"$management_gateway"'",
            "dns_servers": '"$dns_servers"',
            "auth_code": "'"$auth_code"'",
            "panorama_ip": "'"$panorama_ip"'",
            "panorama_port": "'"$panorama_port"'",
            "timezone": "'"$timezone"'"
        }' --output /home/fedora/development/panos-images/panos-bootstrap-$hostname.iso
  5. (Fedora) Now go back to your CLI that is communicating with OpenShift Virtualization, and type the following commands. BE SURE to change with your own variables for namespace:

    hostname="panos-01"
    namespace="jinkit-vms"
    
    # Be sure to use virtctl to create the ISO/pvc first:
    virtctl image-upload pvc panos-bootstrap-$hostname-config-iso \
      --size 1Gi \
      --image-path=/home/fedora/development/panos-images/panos-bootstrap-$hostname.iso \
      --namespace=$namespace \
      --force-bind \
      --volume-mode=block \
      --insecure

Part IV: Stage PanOS Prerequisites

  1. (Workstation) Download the PanOS and Panorama update from the Palo Alto website (11.2.0)

    For this you will need to go to the following navigation path:

    • PAN-OS: Updates > Software Updates > PAN-OS for VM-Series KVM Base Images and select PA-VM-KVM-11.2.0.qcow2.
    • Panorama: Updates > Software Updates > Panorama Base Images and select Panorama-KVM-11.2.0.qcow2.
  2. (Workstation > Fedora) SCP The files from your local machine to the Fedora Development VM (these are example directories, so be sure to change for your environment):

    Important: Be sure to use your own Workstation PATH and $USER. The syntax is for example only, and will not match your environment exactly as shown below:

    scp ~/Downloads/PA-VM-KVM-11.2.0.qcow2 [email protected]:/home/fedora/development/dockerfiles/panos/PA-VM-KVM-11.2.0.qcow2
    
    scp ~/Downloads/Panorama-KVM-11.2.0.qcow2 [email protected]:/home/fedora/development/dockerfiles/panorama/Panorama-KVM-11.2.0.qcow2
    

Part V: Build PanOS and Panorama Boot Images

  1. Go to your registry and get your user credentials. I will show you how to do this for Quay.

    • If you don't already have an account, create one.
    • Then when you are logged in, go to the very top right-hand corner and click on your username.
    • Click on Account Settings and on the left-hand menu click on the Gear Icon.
    • This pulls up a section called *Docker CLI Password.
    • For the CLI Password section click on Generate Encrypted Password.
    • It will ask you to verify your credentials. Enter them now.
    • This will now have an open window that says Credentials for USER.
    • On the left-hand side of this window, click on the Podman Login option.
    • Copy the podman login -u='USER' -p= string.
    • Paste this string into your Fedora CLI to authenticate Podman to your custom personal registry.
  2. (Fedora) Run the following podman commands to build the correct containers. MAKE SURE to replace USERNAME with your actual username for Quay.

    Important: Set the following variable for your QUAY USERNAME.

    quay_username=bjozsa-redhat

    Important: Be sure to use your own Workstation PATH and $quay_username are set correctly. The syntax is for example only, and will likely not match your environment exactly as shown below:

    cd /home/fedora/development/dockerfiles/panos/
    podman build -t quay.io/$quay_username/pa-vm:11.2.0 .
    
    cd /home/fedora/development/dockerfiles/panorama/
    podman build -t quay.io/$quay_username/panorama:11.2.0 .
  3. (Fedora) Now push these images to your Quay registry. Like the previous command, MAKE SURE to replace USERNAME with your actual username for Quay.

    Important: Be sure to use your own Workstation PATH and $USER. The syntax is for example only, and will not match your environment exactly as shown below:

    podman push quay.io/$quay_username/pa-vm:11.2.0
    podman push quay.io/$quay_username/panorama:11.2.0
  4. (Fedora) Now create a secret for your private registry (where you pushed the images). By default, Quay will make your container images private. DO NOT EXPOSE PALO ALTO IMAGES WITHOUT AUTHORIZATION! In order to keep these images private but allow the VM to download what it needs, we need to create a secret for your registry.

    # Change the namespace to your own namespace:
    secret_name="quay-creds-registry-panos"
    namespace="jinkit-vms"
    
    # Do not change below this point:
    read -p "Enter Username: " username
    read -sp "Enter Password or Token: " password
    echo  # This ensures a newline after password input
    
    encoded_username=$(printf "%s" "$username" | base64 -w 0)
    encoded_password=$(printf "%s" "$password" | base64 -w 0)
    
    oc apply -f - <<EOF
    apiVersion: v1
    kind: Secret
    metadata:
      labels:
        app: containerized-data-importer
      name: $secret_name
      namespace: $namespace  
    type: Opaque
    data:
      accessKeyId: "$encoded_username"
      secretKey: "$encoded_password"
    EOF

Part VI: Configure SR-IOV

  1. (Fedora) Make sure that you have the SR-IOV operator installed, and that you have configured two SRIOVNetworks. Think of one network as the "trusted" network, and one network as the "untrusted" network. I will show you a couple of examples down below.

    Trusted:

    oc apply -f - <<EOF
    apiVersion: sriovnetwork.openshift.io/v1
    kind: SriovNetworkNodePolicy
    metadata:
    name: policy-sriov-ens6f1np1-0031
    namespace: openshift-sriov-network-operator
    spec:
    deviceType: vfio-pci
    isRdma: false
    nicSelector:
        deviceID: 101d
        pfNames:
        - ens6f1np1#0-31
        vendor: 15b3
    nodeSelector:
        feature.node.kubernetes.io/network-sriov.capable: "true"
    numVfs: 64
    priority: 99
    resourceName: ens6f1np1_0031
    
    ---
    apiVersion: sriovnetwork.openshift.io/v1
    kind: SriovNetwork
    metadata:
    annotations:
        operator.sriovnetwork.openshift.io/last-network-namespace: jinkit-vms
    name: ens6f1np1-vlan3-d
    namespace: openshift-sriov-network-operator
    spec:
    ipam: |-
        {
        "ipam": {
            "type": "dhcp"
        }
        }
    logLevel: info
    networkNamespace: jinkit-vms
    resourceName: ens6f1np1_0031
    vlan: 3
    EOF

    Untrusted:

    oc apply -f - <<EOF
    apiVersion: sriovnetwork.openshift.io/v1
    kind: SriovNetworkNodePolicy
    metadata:
    name: policy-sriov-ens6f1np1-3263
    namespace: openshift-sriov-network-operator
    spec:
    deviceType: vfio-pci
    isRdma: false
    nicSelector:
        deviceID: 101d
        pfNames:
        - ens6f1np1#32-63
        vendor: 15b3
    nodeSelector:
        feature.node.kubernetes.io/network-sriov.capable: "true"
    numVfs: 64
    priority: 99
    resourceName: ens6f1np1_3263
    
    ---
    apiVersion: sriovnetwork.openshift.io/v1
    kind: SriovNetwork
    metadata:
    annotations:
        operator.sriovnetwork.openshift.io/last-network-namespace: jinkit-vms
    name: ens6f1np1-vlan90-d
    namespace: openshift-sriov-network-operator
    spec:
    ipam: |-
        {
        "ipam": {
            "type": "dhcp"
        }
        }
    logLevel: info
    networkNamespace: jinkit-vms
    resourceName: ens6f1np1_3263
    vlan: 90
    EOF

Part VII: Creating the Panorama VM

  1. (Fedora) Before creating the PanOS VM-Series Firewall, first create the Panorama management instance (named panorama-01). Use the following deployment below simply as an example. Complete the variables according to your own environment, and the deployment should "just work" as-is:

    # Variables
    namespace=jinkit-vms
    instance_name=panorama-01
    secret_name="quay-creds-registry-panos"
    nad_mgmt01=ens6f1np1-vlan3-d
    nad_mgmt02=ens6f1np1-vlan3-d
    mac_mgmt01="02:9b:48:00:18:51"
    mac_mgmt02="02:9b:48:00:18:52"
    registry_image="docker://quay.io/bjozsa-redhat/panorama:11.2.0"
    disk_size="150Gi"
    core_count="16"
    memory_count="36G"
    
    # Virtual Machine Deployment
    oc apply -f - <<EOF
    ---
    apiVersion: kubevirt.io/v1
    kind: VirtualMachine
    metadata:
      name: $instance_name
      namespace: $namespace
    spec:
      dataVolumeTemplates:
        - apiVersion: cdi.kubevirt.io/v1beta1
          kind: DataVolume
          metadata:
            creationTimestamp: null
            name: $instance_name
          spec:
            source:
              registry:
                secretRef: $secret_name
                url: "$registry_image"
            storage:
              resources:
                requests:
                  storage: $disk_size
      running: false
      template:
        metadata:
          labels:
            kubevirt.io/size: small
            kubevirt.io/domain: $instance_name
        spec:
          domain:
            cpu:
              cores: $core_count
            devices:
              disks:
                - name: rootdisk
                  disk:
                    bus: virtio
              interfaces:
              - name: $instance_name-port1
                macAddress: $mac_mgmt01
                model: virtio
                sriov: {}
              - name: $instance_name-port2
                macAddress: $mac_mgmt02
                model: virtio
                sriov: {}
            resources:
              requests:
                memory: $memory_count
          networks:
          - name: $instance_name-port1
            multus:
              networkName: $nad_mgmt01
          - name: $instance_name-port2
            multus:
              networkName: $nad_mgmt02
          volumes:
            - name: rootdisk
              dataVolume:
                name: $instance_name
    EOF
  2. (OpenShift Console) In the OpenShift console, navigate to the VM you've just created (check the variables above, but if left default the name of the vm should be called panorama-01.

    • Click on the Configuration tab.
    • Next, click on the Storage tab.
    • Click on the blue box that says Add disk
    • In the new window (Add disk), use the Name storage-disk-01
    • Source should be Empty disk (blank)
    • PersistentVolumeClaim size should be 75 GiB or higher
    • Type should be set to Disk
    • Interface should be set to VirtIO
    • StorageClass should be set to lvms-vg1-immediate
    • Make sure the option Apply optimized StorageProfile settings is checked
    • Click the blue Save button when completed
  3. Start the VM (you will notice that the VM was created earlier, but not started per the running: false option).

  4. Complete the setup of Panorama as you would normally.

Part VIII: Creating the PanOS VM

  1. (Fedora) Now you can deploy the first PanOS VM-Series Firewall (named panos-01). Use the following deployment below simply as an example. Complete the variables according to your own environment, and the deployment should "just work" as-is - just like the Panorama instance above:

    # Variables
    namespace=jinkit-vms
    instance_name=panos-01
    secret_name="quay-creds-registry-panos"
    nad_mgmt01=ens6f1np1-vlan3-d
    nad_mgmt02=ens6f1np1-vlan3-d
    nad_trusted=ens6f1np1-vlan60-d
    nad_untrusted=ens6f1np1-vlan90-d
    mac_mgmt01="02:9b:48:00:18:11"
    mac_mgmt02="02:9b:48:00:18:12"
    mac_trusted="02:9b:48:00:18:13"
    mac_untrusted="02:9b:48:00:18:14"
    registry_image="docker://quay.io/bjozsa-redhat/pa-vm:11.2.0"
    disk_size="80Gi"
    core_count="8"
    memory_count="16384M"
    
    # Virtual Machine Deployment
    oc apply -f - <<EOF
    ---
    apiVersion: kubevirt.io/v1
    kind: VirtualMachine
    metadata:
      name: $instance_name
      namespace: $namespace
    spec:
      dataVolumeTemplates:
        - apiVersion: cdi.kubevirt.io/v1beta1
          kind: DataVolume
          metadata:
            creationTimestamp: null
            name: $instance_name
          spec:
            source:
              registry:
                secretRef: $secret_name
                url: "$registry_image"
            storage:
              resources:
                requests:
                  storage: $disk_size
      running: true
      template:
        metadata:
          labels:
            kubevirt.io/size: small
            kubevirt.io/domain: $instance_name
        spec:
          domain:
            cpu:
              cores: $core_count
            devices:
              disks:
                - name: rootdisk
                  disk:
                    bus: virtio
                - name: $instance_name-config-iso
                  cdrom:
                    bus: sata
              interfaces:
              - name: $instance_name-port1
                macAddress: $mac_mgmt01
                model: virtio
                sriov: {}
              - name: $instance_name-port2
                macAddress: $mac_mgmt02
                model: virtio
                sriov: {}
              - name: $instance_name-port3
                macAddress: $mac_trusted
                model: virtio
                sriov: {}
              - name: $instance_name-port4
                macAddress: $mac_untrusted
                model: virtio
                sriov: {}
            resources:
              requests:
                memory: $memory_count
          networks:
          - name: $instance_name-port1
            multus:
              networkName: $nad_mgmt01
          - name: $instance_name-port2
            multus:
              networkName: $nad_mgmt02
          - name: $instance_name-port3
            multus:
              networkName: $nad_trusted
          - name: $instance_name-port4
            multus:
              networkName: $nad_untrusted
          volumes:
            - name: rootdisk
              dataVolume:
                name: $instance_name
            - name: $instance_name-config-iso
              persistentVolumeClaim:
                claimName: panos-bootstrap-$instance_name-config-iso
    EOF
# This is a demo for Palo Alto engineering team:
INTERFACE=enp129s0f0
VF_RANGE=0-31
VF_TOTAL=64
VENDOR=8086
DEVICE_ID=158b
DEVICE_TYPE=vfio-pci
RDMA=false
PRIORITY=99
NAME=policy-sriov-$INTERFACE-0031
NAMESPACE=panos-vms
RESOURCE=${INTERFACE}_0031
oc apply -f - <<EOF | tee /dev/tty
---
apiVersion: sriovnetwork.openshift.io/v1
kind: SriovNetwork
metadata:
name: $INTERFACE-panos-lan
namespace: openshift-sriov-network-operator
spec:
ipam: |-
{
"ipam": {
"type": "dhcp"
}
}
networkNamespace: $NAMESPACE
resourceName: $RESOURCE
vlan: 249
EOF
oc apply -f - <<EOF | tee /dev/tty
---
apiVersion: sriovnetwork.openshift.io/v1
kind: SriovNetwork
metadata:
name: $INTERFACE-panos-wan
namespace: openshift-sriov-network-operator
spec:
ipam: |-
{
"ipam": {
"type": "dhcp"
}
}
networkNamespace: $NAMESPACE
resourceName: $RESOURCE
vlan: 8
EOF
FROM scratch
ADD --chown=107:107 Panorama-KVM-11.2.0.qcow2 /disk/
FROM scratch
ADD --chown=107:107 PA-VM-KVM-11.2.0.qcow2 /disk/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment