From c01b537fe7061e8ecb3fe8d5534baa30c2263a6f Mon Sep 17 00:00:00 2001 From: Steven Fairchild Date: Wed, 10 Apr 2024 11:24:40 -0400 Subject: [PATCH 01/38] Move systemd service configurations into functions --- pkg/deploy/generator/scripts/rpVMSS.sh | 693 ++++++++++++++++--------- 1 file changed, 447 insertions(+), 246 deletions(-) diff --git a/pkg/deploy/generator/scripts/rpVMSS.sh b/pkg/deploy/generator/scripts/rpVMSS.sh index 290b534c1c9..eb567b06443 100644 --- a/pkg/deploy/generator/scripts/rpVMSS.sh +++ b/pkg/deploy/generator/scripts/rpVMSS.sh @@ -1,46 +1,125 @@ #!/bin/bash -echo "setting ssh password authentication" -# We need to manually set PasswordAuthentication to true in order for the VMSS Access JIT to work -sed -i 's/PasswordAuthentication no/PasswordAuthentication yes/g' /etc/ssh/sshd_config -systemctl reload sshd.service - -#Adding retry logic to yum commands in order to avoid stalling out on resource locks -echo "running RHUI fix" -for attempt in {1..5}; do - yum update -y --disablerepo='*' --enablerepo='rhui-microsoft-azure*' && break - if [[ ${attempt} -lt 5 ]]; then sleep 10; else exit 1; fi -done +set -o errexit \ + -o nounset \ + +# trap 'catch' ERR + +main() { + configure_sshd + configure_rhui_repo + dnf_update_pkgs + configure_disk_partitions + configure_logrotate + create_azure_rpm_repos + configure_selinux + mkdir -p /var/log/journal + mkdir -p /var/lib/waagent/Microsoft.Azure.KeyVault.Store + configure_firewalld_rules + pull_container_images +} -echo "running yum update" -for attempt in {1..5}; do - yum -y -x WALinuxAgent -x WALinuxAgent-udev update --allowerasing && break - if [[ ${attempt} -lt 5 ]]; then sleep 10; else exit 1; fi -done +# We need to configure PasswordAuthentication to yes in order for the VMSS Access JIT to work +configure_sshd() { + log "setting ssh password authentication" + sed -i 's/PasswordAuthentication no/PasswordAuthentication yes/g' /etc/ssh/sshd_config -echo "extending partition table" -# Linux block devices are inconsistently named -# it's difficult to tie the lvm pv to the physical disk using /dev/disk files, which is why lvs is used here -physicalDisk="$(lvs -o devices -a | head -n2 | tail -n1 | cut -d ' ' -f 3 | cut -d \( -f 1 | tr -d '[:digit:]')" -growpart "$physicalDisk" 2 + systemctl reload sshd.service + systemctl is-active --quiet sshd || abort "sshd failed to reload" +} -echo "extending filesystems" -lvextend -l +20%FREE /dev/rootvg/rootlv -xfs_growfs / +configure_rhui_repo() { + log "running RHUI package updates" + #Adding retry logic to yum commands in order to avoid stalling out on resource locks + for attempt in {1..5}; do + dnf update \ + -y \ + --disablerepo='*' \ + --enablerepo='rhui-microsoft-azure*' \ + && break + if [[ ${attempt} -lt 5 ]]; then + sleep 10 + else + abort "failed to run dnf update" + fi + done +} -lvextend -l +100%FREE /dev/rootvg/varlv -xfs_growfs /var +dnf_update_pkgs() { + log "running dnf update" + for attempt in {1..5}; do + dnf -y \ + -x WALinuxAgent \ + -x WALinuxAgent-udev \ + update --allowerasing \ + && break + if [[ ${attempt} -lt 5 ]]; then + sleep 10 + else + return 1 + fi + done +} -echo "importing rpm repositories" -rpm --import https://dl.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-8 -rpm --import https://packages.microsoft.com/keys/microsoft.asc +dnf_install_pkgs() { + log "importing rpm repositories" + rpm --import https://dl.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-8 + rpm --import https://packages.microsoft.com/keys/microsoft.asc + + for attempt in {1..5}; do + yum -y install https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm && break + if [[ ${attempt} -lt 5 ]]; then + sleep 10 + else + return 1 + fi + done + + for attempt in {1..5}; do + yum -y \ + install \ + clamav \ + azsec-clamav \ + azsec-monitor \ + azure-cli \ + azure-mdsd \ + azure-security \ + podman \ + podman-docker \ + openssl-perl \ + python3 \ + && break + # hack - we are installing python3 on hosts due to an issue with Azure Linux Extensions https://github.com/Azure/azure-linux-extensions/pull/1505 + if [[ ${attempt} -lt 5 ]]; then + sleep 10 + else + abort "failed to install required packages" + fi + done +} -for attempt in {1..5}; do - yum -y install https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm && break - if [[ ${attempt} -lt 5 ]]; then sleep 10; else exit 1; fi -done +configure_disk_partitions() { + log "extending partition table" + # Linux block devices are inconsistently named + # it's difficult to tie the lvm pv to the physical disk using /dev/disk files, which is why lvs is used here + physicalDisk="$(lvs -o devices -a | head -n2 | tail -n1 | cut -d ' ' -f 3 | cut -d \( -f 1 | tr -d '[:digit:]')" + growpart "$physicalDisk" 2 + + log "extending filesystems" + log "extending root lvm" + lvextend -l +20%FREE /dev/rootvg/rootlv + log "growing root filesystem" + xfs_growfs / + + log "extending var lvm" + lvextend -l +100%FREE /dev/rootvg/varlv + log "growing var filesystem" + xfs_growfs /var +} -echo "configuring logrotate" +# configure_logrotate clobbers /etc/logrotate.conf +configure_logrotate() { + log "configuring logrotate" cat >/etc/logrotate.conf <<'EOF' # see "man logrotate" for details # rotate log files weekly @@ -76,8 +155,11 @@ include /etc/logrotate.d rotate 1 } EOF +} -echo "configuring yum repository and running yum update" +# create_azure_rpm_repos creates /etc/yum.repos.d/azure.repo repository file +create_azure_rpm_repos() { + log "configuring yum repository and running yum update" cat >/etc/yum.repos.d/azure.repo <<'EOF' [azure-cli] name=azure-cli @@ -91,18 +173,16 @@ baseurl=https://packages.microsoft.com/yumrepos/azurecore enabled=yes gpgcheck=no EOF +} -semanage fcontext -a -t var_log_t "/var/log/journal(/.*)?" -mkdir -p /var/log/journal - -for attempt in {1..5}; do -yum -y install clamav azsec-clamav azsec-monitor azure-cli azure-mdsd azure-security podman podman-docker openssl-perl python3 && break - # hack - we are installing python3 on hosts due to an issue with Azure Linux Extensions https://github.com/Azure/azure-linux-extensions/pull/1505 - if [[ ${attempt} -lt 5 ]]; then sleep 10; else exit 1; fi -done +configure_selinux() { + semanage fcontext -a -t var_log_t "/var/log/journal(/.*)?" + chcon -R system_u:object_r:var_log_t:s0 /var/opt/microsoft/linuxmonagent +} -# https://access.redhat.com/security/cve/cve-2020-13401 -echo "applying firewall rules" +configure_firewalld_rules() { + # https://access.redhat.com/security/cve/cve-2020-13401 + log "applying firewall rules" cat >/etc/sysctl.d/02-disable-accept-ra.conf <<'EOF' net.ipv6.conf.all.accept_ra=0 EOF @@ -110,35 +190,95 @@ EOF cat >/etc/sysctl.d/01-disable-core.conf <<'EOF' kernel.core_pattern = |/bin/true EOF -sysctl --system + sysctl --system + + log "adding firewalld ports to default zone" + firewall-cmd \ + --add-port=443/tcp \ + --permanent + firewall-cmd \ + --add-port=444/tcp \ + --permanent + firewall-cmd \ + --add-port=445/tcp \ + --permanent + firewall-cmd \ + --add-port=2222/tcp \ + --permanent + + log "reloading firewalld" + firewall-cmd reload +} -firewall-cmd --add-port=443/tcp --permanent -firewall-cmd --add-port=444/tcp --permanent -firewall-cmd --add-port=445/tcp --permanent -firewall-cmd --add-port=2222/tcp --permanent +export AZURE_CLOUD_NAME="${AZURECLOUDNAME:?"Failed to carry over variables"}" -export AZURE_CLOUD_NAME=$AZURECLOUDNAME +pull_container_images() { + echo "logging into prod acr" + az login -i --allow-no-subscriptions -echo "logging into prod acr" -az login -i --allow-no-subscriptions + # Suppress emulation output for podman instead of docker for az acr compatability + mkdir -p /etc/containers/ + touch /etc/containers/nodocker -# Suppress emulation output for podman instead of docker for az acr compatability -mkdir -p /etc/containers/ -touch /etc/containers/nodocker + mkdir -p /root/.docker + REGISTRY_AUTH_FILE=/root/.docker/config.json az acr login --name "$(sed -e 's|.*/||' <<<"$ACRRESOURCEID")" -mkdir -p /root/.docker -REGISTRY_AUTH_FILE=/root/.docker/config.json az acr login --name "$(sed -e 's|.*/||' <<<"$ACRRESOURCEID")" + MDMIMAGE="${RPIMAGE%%/*}/${MDMIMAGE##*/}" + docker pull "$MDMIMAGE" + docker pull "$RPIMAGE" + docker pull "$FLUENTBITIMAGE" -MDMIMAGE="${RPIMAGE%%/*}/${MDMIMAGE##*/}" -docker pull "$MDMIMAGE" -docker pull "$RPIMAGE" -docker pull "$FLUENTBITIMAGE" + az logout +} -az logout +# configure_system_services creates, configures, and enables the following systemd services and timers +# services +# fluentbit +# mdm +# mdsd +# arp-rp +# aro-dbtoken +# aro-monitor +# aro-portal +configure_system_services() { + configure_service_fluentbit + configure_service_mdm + configure_timers_mdm_mdsd + configure_service_aro_rp + configure_service_aro_dbtoken + configure_service_aro_monitor + configure_service_aro_portal + configure_service_mdsd +} + +# enable_aro_services enables all services required for aro rp +enable_aro_services() { + local -a aro_services=( + "aro-dbtoken" + "aro-monitor" + "aro-portal" + "aro-rp" + "auoms" + "azsecd" + "azsecmond" + "mdsd" + "mdm" + "chronyd" + "fluentbit" + ) + log "enabling aro services ${aro_services[*]}" + # shellcheck disable=SC2068 + for service in ${aro_services[@]}; do + log "Enabling $service now" + systemctl enable "$service.service" + done +} -echo "configuring fluentbit service" -mkdir -p /etc/fluentbit/ -mkdir -p /var/lib/fluent +# configure_service_fluentbit +configure_service_fluentbit() { + log "configuring fluentbit service" + mkdir -p /etc/fluentbit/ + mkdir -p /var/lib/fluent cat >/etc/fluentbit/fluentbit.conf <<'EOF' [INPUT] @@ -176,7 +316,7 @@ cat >/etc/fluentbit/fluentbit.conf <<'EOF' Port 29230 EOF -echo "FLUENTBITIMAGE=$FLUENTBITIMAGE" >/etc/sysconfig/fluentbit + log "FLUENTBITIMAGE=$FLUENTBITIMAGE" >/etc/sysconfig/fluentbit cat >/etc/systemd/system/fluentbit.service <<'EOF' [Unit] @@ -211,15 +351,42 @@ StartLimitInterval=0 [Install] WantedBy=multi-user.target EOF +} -mkdir /etc/aro-rp -base64 -d <<<"$ADMINAPICABUNDLE" >/etc/aro-rp/admin-ca-bundle.pem -if [[ -n "$ARMAPICABUNDLE" ]]; then - base64 -d <<<"$ARMAPICABUNDLE" >/etc/aro-rp/arm-ca-bundle.pem -fi -chown -R 1000:1000 /etc/aro-rp +# configure_certs +configure_certs() { + mkdir /etc/aro-rp + base64 -d <<<"$ADMINAPICABUNDLE" >/etc/aro-rp/admin-ca-bundle.pem + if [[ -n "$ARMAPICABUNDLE" ]]; then + base64 -d <<<"$ARMAPICABUNDLE" >/etc/aro-rp/arm-ca-bundle.pem + fi + chown -R 1000:1000 /etc/aro-rp + + # setting MONITORING_GCS_AUTH_ID_TYPE=AuthKeyVault seems to have caused mdsd not + # to honour SSL_CERT_FILE any more, heaven only knows why. + mkdir -p /usr/lib/ssl/certs + csplit -f /usr/lib/ssl/certs/cert- -b %03d.pem /etc/pki/tls/certs/ca-bundle.crt /^$/1 {*} >/dev/null + c_rehash /usr/lib/ssl/certs + +# we leave clientId blank as long as only 1 managed identity assigned to vmss +# if we have more than 1, we will need to populate with clientId used for off-node scanning +cat >/etc/default/vsa-nodescan-agent.config </etc/sysconfig/mdm </etc/systemd/system/mdm.service <<'EOF' [Unit] After=network-online.target @@ -263,9 +430,142 @@ StartLimitInterval=0 [Install] WantedBy=multi-user.target EOF +} + +# configure_timers_mdm_mdsd +configure_timers_mdm_mdsd() { + for var in "mdsd" "mdm"; do +cat >/etc/systemd/system/download-$var-credentials.service </etc/systemd/system/download-$var-credentials.timer </usr/local/bin/download-credentials.sh </etc/sysconfig/aro-rp </etc/systemd/system/watch-mdm-credentials.service </etc/systemd/system/watch-mdm-credentials.path <"$arp_rp_config_file"</etc/systemd/system/aro-rp.service <<'EOF' + local aro_rp_service_file="/etc/systemd/system/aro-rp.service" + log "Writing $aro_rp_service_file" +cat >"$aro_rp_service_file" <<'EOF' [Unit] After=network-online.target Wants=network-online.target @@ -347,9 +649,13 @@ StartLimitInterval=0 [Install] WantedBy=multi-user.target EOF +} -echo "configuring aro-dbtoken service" -cat >/etc/sysconfig/aro-dbtoken <"$aro_dbtoken_service_file" </etc/systemd/system/aro-dbtoken.service <<'EOF' + local aro_dbtoken_service_file="/etc/systemd/system/aro-dbtoken.service" + log "Writing $aro_dbtoken_service_file" +cat >"$aro_dbtoken_service_config_file" <<'EOF' [Unit] After=network-online.target Wants=network-online.target @@ -393,11 +701,15 @@ StartLimitInterval=0 [Install] WantedBy=multi-user.target EOF +} +# configure_service_aro_monitor +configure_service_aro_monitor() { + local aro_monitor_service_config="/etc/sysconfig/aro-monitor" + log "configuring aro-monitor service" # DOMAIN_NAME, CLUSTER_MDSD_ACCOUNT, CLUSTER_MDSD_CONFIG_VERSION, GATEWAY_DOMAINS, GATEWAY_RESOURCEGROUP, MDSD_ENVIRONMENT CLUSTER_MDSD_NAMESPACE # are not used, but can't easily be refactored out. Should be revisited in the future. -echo "configuring aro-monitor service" -cat >/etc/sysconfig/aro-monitor <"$aro_monitor_service_config" </etc/systemd/system/aro-monitor.service <<'EOF' + local aro_monitor_service_file="/etc/systemd/system/aro-monitor.service" + log "Writing $aro_monitor_service_file" +cat >"$aro_monitor_service_file" <<'EOF' [Unit] After=network-online.target Wants=network-online.target @@ -454,9 +768,13 @@ StartLimitInterval=0 [Install] WantedBy=multi-user.target EOF +} -echo "configuring aro-portal service" -cat >/etc/sysconfig/aro-portal <"$aro_portal_service_config" </etc/systemd/system/aro-portal.service <<'EOF' + local aro_portal_service_file="/etc/systemd/system/aro-portal.service" + log "Writing $aro_portal_service_config" +cat >"$aro_portal_service_file" <<'EOF' [Unit] After=network-online.target Wants=network-online.target @@ -503,138 +823,16 @@ RestartSec=1 [Install] WantedBy=multi-user.target EOF - -echo "configuring mdsd and mdm services" -chcon -R system_u:object_r:var_log_t:s0 /var/opt/microsoft/linuxmonagent - -mkdir -p /var/lib/waagent/Microsoft.Azure.KeyVault.Store - -for var in "mdsd" "mdm"; do -cat >/etc/systemd/system/download-$var-credentials.service </etc/systemd/system/download-$var-credentials.timer </usr/local/bin/download-credentials.sh </etc/systemd/system/watch-mdm-credentials.service </etc/systemd/system/watch-mdm-credentials.path </etc/systemd/system/mdsd.service.d/override.conf <<'EOF' +# configure_service_mdsd +configure_service_mdsd() { + local mdsd_service_dir="/etc/systemd/system/mdsd.service.d" + log "Creating $mdsd_service_dir" + mkdir "$mdsd_service_dir" + local mdsd_override_conf="$mdsd_service_dir/override.conf" + log "Writing $mdsd_override_conf" +cat >"$mdsd_override_conf" <<'EOF' [Unit] After=network-online.target EOF @@ -658,36 +856,39 @@ export MONITORING_ROLE_INSTANCE='$(hostname)' export MDSD_MSGPACK_SORT_COLUMNS=1 EOF +} -# setting MONITORING_GCS_AUTH_ID_TYPE=AuthKeyVault seems to have caused mdsd not -# to honour SSL_CERT_FILE any more, heaven only knows why. -mkdir -p /usr/lib/ssl/certs -csplit -f /usr/lib/ssl/certs/cert- -b %03d.pem /etc/pki/tls/certs/ca-bundle.crt /^$/1 {*} >/dev/null -c_rehash /usr/lib/ssl/certs - -# we leave clientId blank as long as only 1 managed identity assigned to vmss -# if we have more than 1, we will need to populate with clientId used for off-node scanning -cat >/etc/default/vsa-nodescan-agent.config < Date: Wed, 10 Apr 2024 11:51:10 -0400 Subject: [PATCH 02/38] Move dnf package and repo operations into function, move all service configuration into a function --- pkg/deploy/generator/scripts/rpVMSS.sh | 130 +++++++++++++++++-------- 1 file changed, 91 insertions(+), 39 deletions(-) diff --git a/pkg/deploy/generator/scripts/rpVMSS.sh b/pkg/deploy/generator/scripts/rpVMSS.sh index eb567b06443..c3eea7e0827 100644 --- a/pkg/deploy/generator/scripts/rpVMSS.sh +++ b/pkg/deploy/generator/scripts/rpVMSS.sh @@ -7,16 +7,15 @@ set -o errexit \ main() { configure_sshd - configure_rhui_repo - dnf_update_pkgs + configure_and_install_dnf_pkgs_repos configure_disk_partitions configure_logrotate - create_azure_rpm_repos configure_selinux mkdir -p /var/log/journal mkdir -p /var/lib/waagent/Microsoft.Azure.KeyVault.Store configure_firewalld_rules pull_container_images + configure_system_services } # We need to configure PasswordAuthentication to yes in order for the VMSS Access JIT to work @@ -28,6 +27,15 @@ configure_sshd() { systemctl is-active --quiet sshd || abort "sshd failed to reload" } +# configure_and_install_dnf_pkgs_repos +configure_and_install_dnf_pkgs_repos() { + configure_rhui_repo + dnf_update_pkgs + dnf_install_pkgs + create_azure_rpm_repos +} + +# configure_rhui_repo configure_rhui_repo() { log "running RHUI package updates" #Adding retry logic to yum commands in order to avoid stalling out on resource locks @@ -45,6 +53,7 @@ configure_rhui_repo() { done } +# dnf_update_pkgs dnf_update_pkgs() { log "running dnf update" for attempt in {1..5}; do @@ -61,13 +70,16 @@ dnf_update_pkgs() { done } +# dnf_install_pkgs dnf_install_pkgs() { log "importing rpm repositories" rpm --import https://dl.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-8 rpm --import https://packages.microsoft.com/keys/microsoft.asc for attempt in {1..5}; do - yum -y install https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm && break + dnf -y \ + install https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm \ + && break if [[ ${attempt} -lt 5 ]]; then sleep 10 else @@ -76,7 +88,7 @@ dnf_install_pkgs() { done for attempt in {1..5}; do - yum -y \ + dnf -y \ install \ clamav \ azsec-clamav \ @@ -98,6 +110,7 @@ dnf_install_pkgs() { done } +# configure_disk_partitions configure_disk_partitions() { log "extending partition table" # Linux block devices are inconsistently named @@ -119,8 +132,9 @@ configure_disk_partitions() { # configure_logrotate clobbers /etc/logrotate.conf configure_logrotate() { - log "configuring logrotate" -cat >/etc/logrotate.conf <<'EOF' + local logrotate_conf_file="/etc/logrotate.conf" + log "Writing over $logrotate_conf_file" +cat >"$logrotate_conf_file" <<'EOF' # see "man logrotate" for details # rotate log files weekly weekly @@ -159,8 +173,9 @@ EOF # create_azure_rpm_repos creates /etc/yum.repos.d/azure.repo repository file create_azure_rpm_repos() { - log "configuring yum repository and running yum update" -cat >/etc/yum.repos.d/azure.repo <<'EOF' + local azure_repo_file="/etc/yum.repos.d/azure.repo" + log "Writing $azure_repo_file" +cat >"$azure_repo_file" <<'EOF' [azure-cli] name=azure-cli baseurl=https://packages.microsoft.com/yumrepos/azure-cli @@ -175,43 +190,54 @@ gpgcheck=no EOF } +# configure_selinux configure_selinux() { + local relabel="${1:-false}" semanage fcontext -a -t var_log_t "/var/log/journal(/.*)?" chcon -R system_u:object_r:var_log_t:s0 /var/opt/microsoft/linuxmonagent + + if relabel; then + restorecon -RF /var/log/* + fi } +# configure_firewalld_rules configure_firewalld_rules() { # https://access.redhat.com/security/cve/cve-2020-13401 - log "applying firewall rules" -cat >/etc/sysctl.d/02-disable-accept-ra.conf <<'EOF' + local prefix="/etc/sysctl.d" + local diable_accept_ra_conf="$prefix/02-disable-accept-ra.conf" + log "Writing $diable_accept_ra_conf" +cat >"$diable_accept_ra_conf" <<'EOF' net.ipv6.conf.all.accept_ra=0 EOF -cat >/etc/sysctl.d/01-disable-core.conf <<'EOF' + local disable_core="$prefix/01-disable-core.conf" + log "Writing $disable_core" +cat >"$disable_core" <<'EOF' kernel.core_pattern = |/bin/true EOF sysctl --system - log "adding firewalld ports to default zone" - firewall-cmd \ - --add-port=443/tcp \ - --permanent - firewall-cmd \ - --add-port=444/tcp \ - --permanent - firewall-cmd \ - --add-port=445/tcp \ - --permanent - firewall-cmd \ - --add-port=2222/tcp \ - --permanent + enable_ports=( + "443/tcp" + "444/tcp" + "445/tcp" + "2222/tcp" + ) + log "Enabling ports ${enable_ports[*]} on default firewalld zone" + # shellcheck disable=SC2068 + for port in ${enable_ports[@]}; do + log "Enabling port $port now" + firewall-cmd "--add-port=$port" + done log "reloading firewalld" firewall-cmd reload -} -export AZURE_CLOUD_NAME="${AZURECLOUDNAME:?"Failed to carry over variables"}" + firewall-cmd --runtime-to-permanent +} +# pull_container_images pull_container_images() { echo "logging into prod acr" az login -i --allow-no-subscriptions @@ -316,9 +342,13 @@ cat >/etc/fluentbit/fluentbit.conf <<'EOF' Port 29230 EOF - log "FLUENTBITIMAGE=$FLUENTBITIMAGE" >/etc/sysconfig/fluentbit + local sysconfig_fluentbit="/etc/sysconfig/fluentbit" + log "Writing value FLUENTBITIMAGE=$FLUENTBITIMAGE to $sysconfig_fluentbit" + echo "FLUENTBITIMAGE=$FLUENTBITIMAGE" >"$sysconfig_fluentbit" -cat >/etc/systemd/system/fluentbit.service <<'EOF' + fluentbit_service_file="/etc/systemd/system/fluentbit.service" + log "Writing $fluentbit_service_file now" +cat >"$fluentbit_service_file" <<'EOF' [Unit] After=network-online.target Wants=network-online.target @@ -370,7 +400,9 @@ configure_certs() { # we leave clientId blank as long as only 1 managed identity assigned to vmss # if we have more than 1, we will need to populate with clientId used for off-node scanning -cat >/etc/default/vsa-nodescan-agent.config <"$nodescan_agent_file" </etc/sysconfig/mdm <"$sysconfig_mdm_file" </etc/systemd/system/mdm.service <<'EOF' + mdm_service_file="/etc/systemd/system/mdm.service" + log "Writing $mdm_service_file" +cat >"$mdm_service_file"<<'EOF' [Unit] After=network-online.target Wants=network-online.target @@ -435,7 +471,9 @@ EOF # configure_timers_mdm_mdsd configure_timers_mdm_mdsd() { for var in "mdsd" "mdm"; do -cat >/etc/systemd/system/download-$var-credentials.service <"$download_creds_service_file" </etc/systemd/system/download-$var-credentials.timer <"$download_creds_timer_file"</usr/local/bin/download-credentials.sh <"$download_creds_script_file" </etc/systemd/system/watch-mdm-credentials.service <"$watch_mdm_creds_service_file" </etc/systemd/system/watch-mdm-credentials.path <"$watch_mdm_creds_path_file" <"$mdsd_override_conf" <<'EOF' After=network-online.target EOF -cat >/etc/default/mdsd <"$default_mdsd_file" < Date: Wed, 10 Apr 2024 13:23:20 -0400 Subject: [PATCH 03/38] Move repository configuration higher in sequence of events, make unchanging variables readonly --- pkg/deploy/generator/scripts/rpVMSS.sh | 70 +++++++++++++------------- 1 file changed, 36 insertions(+), 34 deletions(-) diff --git a/pkg/deploy/generator/scripts/rpVMSS.sh b/pkg/deploy/generator/scripts/rpVMSS.sh index c3eea7e0827..0677589931f 100644 --- a/pkg/deploy/generator/scripts/rpVMSS.sh +++ b/pkg/deploy/generator/scripts/rpVMSS.sh @@ -3,7 +3,7 @@ set -o errexit \ -o nounset \ -# trap 'catch' ERR +trap 'catch' ERR main() { configure_sshd @@ -11,11 +11,13 @@ main() { configure_disk_partitions configure_logrotate configure_selinux - mkdir -p /var/log/journal + journal_dir="/var/log/journal" + mkdir -p "$journal_dir" mkdir -p /var/lib/waagent/Microsoft.Azure.KeyVault.Store configure_firewalld_rules pull_container_images configure_system_services + reboot_vm } # We need to configure PasswordAuthentication to yes in order for the VMSS Access JIT to work @@ -30,9 +32,9 @@ configure_sshd() { # configure_and_install_dnf_pkgs_repos configure_and_install_dnf_pkgs_repos() { configure_rhui_repo + create_azure_rpm_repos dnf_update_pkgs dnf_install_pkgs - create_azure_rpm_repos } # configure_rhui_repo @@ -192,26 +194,28 @@ EOF # configure_selinux configure_selinux() { - local relabel="${1:-false}" - semanage fcontext -a -t var_log_t "/var/log/journal(/.*)?" + local -r relabel="${1:-false}" + + already_defined_ignore_error="File context for /var/log/journal(/.*)? already defined" + semanage fcontext -a -t var_log_t "/var/log/journal(/.*)?" || log "$already_defined_ignore_error" chcon -R system_u:object_r:var_log_t:s0 /var/opt/microsoft/linuxmonagent - if relabel; then - restorecon -RF /var/log/* + if "$relabel"; then + restorecon -RF /var/log/* || log "$already_defined_ignore_error" fi } # configure_firewalld_rules configure_firewalld_rules() { # https://access.redhat.com/security/cve/cve-2020-13401 - local prefix="/etc/sysctl.d" - local diable_accept_ra_conf="$prefix/02-disable-accept-ra.conf" + local -r prefix="/etc/sysctl.d" + local -r diable_accept_ra_conf="$prefix/02-disable-accept-ra.conf" log "Writing $diable_accept_ra_conf" cat >"$diable_accept_ra_conf" <<'EOF' net.ipv6.conf.all.accept_ra=0 EOF - local disable_core="$prefix/01-disable-core.conf" + local -r disable_core="$prefix/01-disable-core.conf" log "Writing $disable_core" cat >"$disable_core" <<'EOF' kernel.core_pattern = |/bin/true @@ -230,9 +234,6 @@ EOF log "Enabling port $port now" firewall-cmd "--add-port=$port" done - - log "reloading firewalld" - firewall-cmd reload firewall-cmd --runtime-to-permanent } @@ -279,7 +280,7 @@ configure_system_services() { # enable_aro_services enables all services required for aro rp enable_aro_services() { - local -a aro_services=( + local -ra aro_services=( "aro-dbtoken" "aro-monitor" "aro-portal" @@ -342,7 +343,7 @@ cat >/etc/fluentbit/fluentbit.conf <<'EOF' Port 29230 EOF - local sysconfig_fluentbit="/etc/sysconfig/fluentbit" + local -r sysconfig_fluentbit="/etc/sysconfig/fluentbit" log "Writing value FLUENTBITIMAGE=$FLUENTBITIMAGE to $sysconfig_fluentbit" echo "FLUENTBITIMAGE=$FLUENTBITIMAGE" >"$sysconfig_fluentbit" @@ -429,7 +430,7 @@ MDMSOURCEROLE=rp MDMSOURCEROLEINSTANCE='$(hostname)' EOF - mkdir /var/etw + mkdir -p /var/etw mdm_service_file="/etc/systemd/system/mdm.service" log "Writing $mdm_service_file" cat >"$mdm_service_file"<<'EOF' @@ -482,7 +483,7 @@ Type=oneshot ExecStart=/usr/local/bin/download-credentials.sh $var EOF - download_creds_timer_file="/etc/systemd/system/download-$var-credentials.timer" + local -r download_creds_timer_file="/etc/systemd/system/download-$var-credentials.timer" log "Writing $download_creds_timer_file" cat >"$download_creds_timer_file"<"$download_creds_script_file" <"$watch_mdm_creds_service_file" <"$arp_rp_config_file"<"$aro_rp_service_file" <<'EOF' [Unit] @@ -699,7 +700,7 @@ EOF # configure_service_aro_dbtoken configure_service_aro_dbtoken() { - local aro_dbtoken_service_config_file="/etc/sysconfig/aro-dbtoken" + local -r aro_dbtoken_service_config_file="/etc/sysconfig/aro-dbtoken" log "Writing $aro_dbtoken_service_file" cat >"$aro_dbtoken_service_file" <"$aro_dbtoken_service_config_file" <<'EOF' [Unit] @@ -751,7 +752,7 @@ EOF # configure_service_aro_monitor configure_service_aro_monitor() { - local aro_monitor_service_config="/etc/sysconfig/aro-monitor" + local -r aro_monitor_service_config="/etc/sysconfig/aro-monitor" log "configuring aro-monitor service" # DOMAIN_NAME, CLUSTER_MDSD_ACCOUNT, CLUSTER_MDSD_CONFIG_VERSION, GATEWAY_DOMAINS, GATEWAY_RESOURCEGROUP, MDSD_ENVIRONMENT CLUSTER_MDSD_NAMESPACE # are not used, but can't easily be refactored out. Should be revisited in the future. @@ -773,7 +774,7 @@ MDM_NAMESPACE=BBM RPIMAGE='$RPIMAGE' EOF - local aro_monitor_service_file="/etc/systemd/system/aro-monitor.service" + local -r aro_monitor_service_file="/etc/systemd/system/aro-monitor.service" log "Writing $aro_monitor_service_file" cat >"$aro_monitor_service_file" <<'EOF' [Unit] @@ -818,7 +819,7 @@ EOF # configure_service_aro_portal configure_service_aro_portal() { - local aro_portal_service_config="/etc/sysconfig/aro-portal" + local -r aro_portal_service_config="/etc/sysconfig/aro-portal" log "Writing $aro_portal_service_config" cat >"$aro_portal_service_config" <"$aro_portal_service_file" <<'EOF' [Unit] @@ -873,10 +874,10 @@ EOF # configure_service_mdsd configure_service_mdsd() { - local mdsd_service_dir="/etc/systemd/system/mdsd.service.d" + local -r mdsd_service_dir="/etc/systemd/system/mdsd.service.d" log "Creating $mdsd_service_dir" mkdir "$mdsd_service_dir" - local mdsd_override_conf="$mdsd_service_dir/override.conf" + local -r mdsd_override_conf="$mdsd_service_dir/override.conf" log "Writing $mdsd_override_conf" cat >"$mdsd_override_conf" <<'EOF' [Unit] @@ -908,7 +909,7 @@ EOF # run_azsecd_config_scan run_azsecd_config_scan() { - local -a configs=( + local -ar configs=( "baseline" "clamav" "software" @@ -930,14 +931,15 @@ reboot_vm() { # log is a wrapper for echo that includes the function name log() { - local msg="${1:-"log message is empty"}" - local stack_level="${2:-1}" + local -r msg="${1:-"log message is empty"}" + local -r stack_level="${2:-1}" echo "${FUNCNAME[${stack_level}]}: ${msg}" } # abort is a wrapper for log that exits with an error code abort() { - log "${1}" "2" + local -ri origin_stacklevel=2 + log "${1}" "$origin_stacklevel" exit 1 } From 91bcccd9847edea6571fe3bee121922e870ac41a Mon Sep 17 00:00:00 2001 From: Steven Fairchild Date: Wed, 10 Apr 2024 16:28:10 -0400 Subject: [PATCH 04/38] Add write_file function to cleanup creation of new files, appending to existing files --- pkg/deploy/assets/gateway-production.json | 2 +- pkg/deploy/assets/rp-production.json | 2 +- pkg/deploy/generator/scripts/gatewayVMSS.sh | 3 +- pkg/deploy/generator/scripts/rpVMSS.sh | 378 ++++++++++---------- 4 files changed, 198 insertions(+), 187 deletions(-) diff --git a/pkg/deploy/assets/gateway-production.json b/pkg/deploy/assets/gateway-production.json index 1a3296cd889..e539ddfd02a 100644 --- a/pkg/deploy/assets/gateway-production.json +++ b/pkg/deploy/assets/gateway-production.json @@ -309,7 +309,7 @@ "autoUpgradeMinorVersion": true, "settings": {}, "protectedSettings": { - "script": "[base64(concat(base64ToString('c2V0IC1leAoK'),'ACRRESOURCEID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('acrResourceId')),''')\n','AZURECLOUDNAME=$(base64 -d \u003c\u003c\u003c''',base64(parameters('azureCloudName')),''')\n','AZURESECPACKQUALYSURL=$(base64 -d \u003c\u003c\u003c''',base64(parameters('azureSecPackQualysUrl')),''')\n','AZURESECPACKVSATENANTID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('azureSecPackVSATenantId')),''')\n','DATABASEACCOUNTNAME=$(base64 -d \u003c\u003c\u003c''',base64(parameters('databaseAccountName')),''')\n','DBTOKENCLIENTID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('dbtokenClientId')),''')\n','DBTOKENURL=$(base64 -d \u003c\u003c\u003c''',base64(parameters('dbtokenUrl')),''')\n','MDMFRONTENDURL=$(base64 -d \u003c\u003c\u003c''',base64(parameters('mdmFrontendUrl')),''')\n','MDSDENVIRONMENT=$(base64 -d \u003c\u003c\u003c''',base64(parameters('mdsdEnvironment')),''')\n','FLUENTBITIMAGE=$(base64 -d \u003c\u003c\u003c''',base64(parameters('fluentbitImage')),''')\n','GATEWAYMDSDCONFIGVERSION=$(base64 -d \u003c\u003c\u003c''',base64(parameters('gatewayMdsdConfigVersion')),''')\n','GATEWAYDOMAINS=$(base64 -d \u003c\u003c\u003c''',base64(parameters('gatewayDomains')),''')\n','GATEWAYFEATURES=$(base64 -d \u003c\u003c\u003c''',base64(parameters('gatewayFeatures')),''')\n','KEYVAULTDNSSUFFIX=$(base64 -d \u003c\u003c\u003c''',base64(parameters('keyvaultDNSSuffix')),''')\n','KEYVAULTPREFIX=$(base64 -d \u003c\u003c\u003c''',base64(parameters('keyvaultPrefix')),''')\n','RPIMAGE=$(base64 -d \u003c\u003c\u003c''',base64(parameters('rpImage')),''')\n','RPMDMACCOUNT=$(base64 -d \u003c\u003c\u003c''',base64(parameters('rpMdmAccount')),''')\n','RPMDSDACCOUNT=$(base64 -d \u003c\u003c\u003c''',base64(parameters('rpMdsdAccount')),''')\n','RPMDSDNAMESPACE=$(base64 -d \u003c\u003c\u003c''',base64(parameters('rpMdsdNamespace')),''')\n','MDMIMAGE=''/genevamdm:2.2024.328.1744-c5fb79-20240328t1935''\n','LOCATION=$(base64 -d \u003c\u003c\u003c''',base64(resourceGroup().location),''')\n','SUBSCRIPTIONID=$(base64 -d \u003c\u003c\u003c''',base64(subscription().subscriptionId),''')\n','RESOURCEGROUPNAME=$(base64 -d \u003c\u003c\u003c''',base64(resourceGroup().name),''')\n','\n',base64ToString('IyEvYmluL2Jhc2gKCmVjaG8gInNldHRpbmcgc3NoIHBhc3N3b3JkIGF1dGhlbnRpY2F0aW9uIgojIFdlIG5lZWQgdG8gbWFudWFsbHkgc2V0IFBhc3N3b3JkQXV0aGVudGljYXRpb24gdG8gdHJ1ZSBpbiBvcmRlciBmb3IgdGhlIFZNU1MgQWNjZXNzIEpJVCB0byB3b3JrCnNlZCAtaSAncy9QYXNzd29yZEF1dGhlbnRpY2F0aW9uIG5vL1Bhc3N3b3JkQXV0aGVudGljYXRpb24geWVzL2cnIC9ldGMvc3NoL3NzaGRfY29uZmlnCnN5c3RlbWN0bCByZWxvYWQgc3NoZC5zZXJ2aWNlCgojQWRkaW5nIHJldHJ5IGxvZ2ljIHRvIHl1bSBjb21tYW5kcyBpbiBvcmRlciB0byBhdm9pZCBzdGFsbGluZyBvdXQgb24gcmVzb3VyY2UgbG9ja3MKZWNobyAicnVubmluZyBSSFVJIGZpeCIKZm9yIGF0dGVtcHQgaW4gezEuLjV9OyBkbwogIHl1bSB1cGRhdGUgLXkgLS1kaXNhYmxlcmVwbz0nKicgLS1lbmFibGVyZXBvPSdyaHVpLW1pY3Jvc29mdC1henVyZSonICYmIGJyZWFrCiAgaWYgW1sgJHthdHRlbXB0fSAtbHQgNSBdXTsgdGhlbiBzbGVlcCAxMDsgZWxzZSBleGl0IDE7IGZpCmRvbmUKCmVjaG8gInJ1bm5pbmcgeXVtIHVwZGF0ZSIKZm9yIGF0dGVtcHQgaW4gezEuLjV9OyBkbwogIHl1bSAteSAteCBXQUxpbnV4QWdlbnQgLXggV0FMaW51eEFnZW50LXVkZXYgdXBkYXRlIC0tYWxsb3dlcmFzaW5nICYmIGJyZWFrCiAgaWYgW1sgJHthdHRlbXB0fSAtbHQgNSBdXTsgdGhlbiBzbGVlcCAxMDsgZWxzZSBleGl0IDE7IGZpCmRvbmUKCmVjaG8gImV4dGVuZGluZyBwYXJ0aXRpb24gdGFibGUiCiMgTGludXggYmxvY2sgZGV2aWNlcyBhcmUgaW5jb25zaXN0ZW50bHkgbmFtZWQKIyBpdCdzIGRpZmZpY3VsdCB0byB0aWUgdGhlIGx2bSBwdiB0byB0aGUgcGh5c2ljYWwgZGlzayB1c2luZyAvZGV2L2Rpc2sgZmlsZXMsIHdoaWNoIGlzIHdoeSBsdnMgaXMgdXNlZCBoZXJlCnBoeXNpY2FsX2Rpc2s9IiQobHZzIC1vIGRldmljZXMgLWEgfCBoZWFkIC1uMiB8IHRhaWwgLW4xIHwgY3V0IC1kICcgJyAtZiAzIHwgY3V0IC1kIFwoIC1mIDEgfCB0ciAtZCAnWzpkaWdpdDpdJykiCmdyb3dwYXJ0ICIkcGh5c2ljYWxfZGlzayIgMgoKZWNobyAiZXh0ZW5kaW5nIGZpbGVzeXN0ZW1zIgpsdmV4dGVuZCAtbCArMjAlRlJFRSAvZGV2L3Jvb3R2Zy9yb290bHYKeGZzX2dyb3dmcyAvCgpsdmV4dGVuZCAtbCArMTAwJUZSRUUgL2Rldi9yb290dmcvdmFybHYKeGZzX2dyb3dmcyAvdmFyCgpycG0gLS1pbXBvcnQgaHR0cHM6Ly9kbC5mZWRvcmFwcm9qZWN0Lm9yZy9wdWIvZXBlbC9SUE0tR1BHLUtFWS1FUEVMLTgKcnBtIC0taW1wb3J0IGh0dHBzOi8vcGFja2FnZXMubWljcm9zb2Z0LmNvbS9rZXlzL21pY3Jvc29mdC5hc2MKCmZvciBhdHRlbXB0IGluIHsxLi41fTsgZG8KICB5dW0gLXkgaW5zdGFsbCBodHRwczovL2RsLmZlZG9yYXByb2plY3Qub3JnL3B1Yi9lcGVsL2VwZWwtcmVsZWFzZS1sYXRlc3QtOC5ub2FyY2gucnBtICYmIGJyZWFrCiAgaWYgW1sgJHthdHRlbXB0fSAtbHQgNSBdXTsgdGhlbiBzbGVlcCAxMDsgZWxzZSBleGl0IDE7IGZpCmRvbmUKCmVjaG8gImNvbmZpZ3VyaW5nIGxvZ3JvdGF0ZSIKCiMgZ2F0ZXdheV9sb2dkaXIgaXMgYSByZWFkb25seSB2YXJpYWJsZSB0aGF0IHNwZWNpZmllcyB0aGUgaG9zdCBwYXRoIG1vdW50IHBvaW50IGZvciB0aGUgZ2F0ZXdheSBjb250YWluZXIgbG9nIGZpbGUKIyBmb3IgdGhlIHB1cnBvc2Ugb2Ygcm90YXRpbmcgdGhlIGdhdGV3YXkgbG9ncwpkZWNsYXJlIC1yIGdhdGV3YXlfbG9nZGlyPScvdmFyL2xvZy9hcm8tZ2F0ZXdheScKCmNhdCA+L2V0Yy9sb2dyb3RhdGUuY29uZiA8PEVPRgojIHNlZSAibWFuIGxvZ3JvdGF0ZSIgZm9yIGRldGFpbHMKIyByb3RhdGUgbG9nIGZpbGVzIHdlZWtseQp3ZWVrbHkKCiMga2VlcCAyIHdlZWtzIHdvcnRoIG9mIGJhY2tsb2dzCnJvdGF0ZSAyCgojIGNyZWF0ZSBuZXcgKGVtcHR5KSBsb2cgZmlsZXMgYWZ0ZXIgcm90YXRpbmcgb2xkIG9uZXMKY3JlYXRlCgojIHVzZSBkYXRlIGFzIGEgc3VmZml4IG9mIHRoZSByb3RhdGVkIGZpbGUKZGF0ZWV4dAoKIyB1bmNvbW1lbnQgdGhpcyBpZiB5b3Ugd2FudCB5b3VyIGxvZyBmaWxlcyBjb21wcmVzc2VkCmNvbXByZXNzCgojIFJQTSBwYWNrYWdlcyBkcm9wIGxvZyByb3RhdGlvbiBpbmZvcm1hdGlvbiBpbnRvIHRoaXMgZGlyZWN0b3J5CmluY2x1ZGUgL2V0Yy9sb2dyb3RhdGUuZAoKIyBubyBwYWNrYWdlcyBvd24gd3RtcCBhbmQgYnRtcCAtLSB3ZSdsbCByb3RhdGUgdGhlbSBoZXJlCi92YXIvbG9nL3d0bXAgewogICAgbW9udGhseQogICAgY3JlYXRlIDA2NjQgcm9vdCB1dG1wCiAgICAgICAgbWluc2l6ZSAxTQogICAgcm90YXRlIDEKfQoKL3Zhci9sb2cvYnRtcCB7CiAgICBtaXNzaW5nb2sKICAgIG1vbnRobHkKICAgIGNyZWF0ZSAwNjAwIHJvb3QgdXRtcAogICAgcm90YXRlIDEKfQoKIyBNYXhpbXVtIGxvZyBkaXJlY3Rvcnkgc2l6ZSBpcyAxMDBHIHdpdGggdGhpcyBjb25maWd1cmF0aW9uCiMgU2V0dGluZyBsaW1pdCB0byAxMDBHIHRvIGFsbG93IHNwYWNlIGZvciBvdGhlciBsb2dnaW5nIHNlcnZpY2VzCiMgY29weXRydW5jYXRlIGlzIGEgY3JpdGljYWwgb3B0aW9uIHVzZWQgdG8gcHJldmVudCBsb2dzIGZyb20gYmVpbmcgc2hpcHBlZCB0d2ljZQoke2dhdGV3YXlfbG9nZGlyfSB7CiAgICBzaXplIDIwRwogICAgcm90YXRlIDUKICAgIGNyZWF0ZSAwNjAwIHJvb3Qgcm9vdAogICAgY29weXRydW5jYXRlCiAgICBub29sZGRpcgogICAgY29tcHJlc3MKfQpFT0YKCmVjaG8gImNvbmZpZ3VyaW5nIHl1bSByZXBvc2l0b3J5IGFuZCBydW5uaW5nIHl1bSB1cGRhdGUiCmNhdCA+L2V0Yy95dW0ucmVwb3MuZC9henVyZS5yZXBvIDw8J0VPRicKW2F6dXJlLWNsaV0KbmFtZT1henVyZS1jbGkKYmFzZXVybD1odHRwczovL3BhY2thZ2VzLm1pY3Jvc29mdC5jb20veXVtcmVwb3MvYXp1cmUtY2xpCmVuYWJsZWQ9eWVzCmdwZ2NoZWNrPXllcwoKW2F6dXJlY29yZV0KbmFtZT1henVyZWNvcmUKYmFzZXVybD1odHRwczovL3BhY2thZ2VzLm1pY3Jvc29mdC5jb20veXVtcmVwb3MvYXp1cmVjb3JlCmVuYWJsZWQ9eWVzCmdwZ2NoZWNrPW5vCkVPRgoKc2VtYW5hZ2UgZmNvbnRleHQgLWEgLXQgdmFyX2xvZ190ICIvdmFyL2xvZy9qb3VybmFsKC8uKik/Igpta2RpciAtcCAvdmFyL2xvZy9qb3VybmFsCgpmb3IgYXR0ZW1wdCBpbiB7MS4uNX07IGRvCiAgeXVtIC15IGluc3RhbGwgY2xhbWF2IGF6c2VjLWNsYW1hdiBhenNlYy1tb25pdG9yIGF6dXJlLWNsaSBhenVyZS1tZHNkIGF6dXJlLXNlY3VyaXR5IHBvZG1hbi1kb2NrZXIgb3BlbnNzbC1wZXJsIHB5dGhvbjMgJiYgYnJlYWsKICAjIGhhY2sgLSB3ZSBhcmUgaW5zdGFsbGluZyBweXRob24zIG9uIGhvc3RzIGR1ZSB0byBhbiBpc3N1ZSB3aXRoIEF6dXJlIExpbnV4IEV4dGVuc2lvbnMgaHR0cHM6Ly9naXRodWIuY29tL0F6dXJlL2F6dXJlLWxpbnV4LWV4dGVuc2lvbnMvcHVsbC8xNTA1CiAgaWYgW1sgJHthdHRlbXB0fSAtbHQgNSBdXTsgdGhlbiBzbGVlcCAxMDsgZWxzZSBleGl0IDE7IGZpCmRvbmUKCmVjaG8gImFwcGx5aW5nIGZpcmV3YWxsIHJ1bGVzIgojIGh0dHBzOi8vYWNjZXNzLnJlZGhhdC5jb20vc2VjdXJpdHkvY3ZlL2N2ZS0yMDIwLTEzNDAxCmNhdCA+L2V0Yy9zeXNjdGwuZC8wMi1kaXNhYmxlLWFjY2VwdC1yYS5jb25mIDw8J0VPRicKbmV0LmlwdjYuY29uZi5hbGwuYWNjZXB0X3JhPTAKRU9GCgpjYXQgPi9ldGMvc3lzY3RsLmQvMDEtZGlzYWJsZS1jb3JlLmNvbmYgPDwnRU9GJwprZXJuZWwuY29yZV9wYXR0ZXJuID0gfC9iaW4vdHJ1ZQpFT0YKc3lzY3RsIC0tc3lzdGVtCgpmaXJld2FsbC1jbWQgLS1hZGQtcG9ydD04MC90Y3AgLS1wZXJtYW5lbnQKZmlyZXdhbGwtY21kIC0tYWRkLXBvcnQ9ODA4MS90Y3AgLS1wZXJtYW5lbnQKZmlyZXdhbGwtY21kIC0tYWRkLXBvcnQ9NDQzL3RjcCAtLXBlcm1hbmVudAoKZWNobyAibG9nZ2luZyBpbnRvIHByb2QgYWNyIgpleHBvcnQgQVpVUkVfQ0xPVURfTkFNRT0kQVpVUkVDTE9VRE5BTUUKYXogbG9naW4gLWkgLS1hbGxvdy1uby1zdWJzY3JpcHRpb25zCgojIFRoZSBtYW5hZ2VkIGlkZW50aXR5IHRoYXQgdGhlIFZNIHJ1bnMgYXMgb25seSBoYXMgYSBzaW5nbGUgcm9sZWFzc2lnbm1lbnQuCiMgVGhpcyByb2xlIGFzc2lnbm1lbnQgaXMgQUNSUHVsbCB3aGljaCBpcyBub3QgbmVjZXNzYXJpbHkgcHJlc2VudCBpbiB0aGUKIyBzdWJzY3JpcHRpb24gd2UncmUgZGVwbG95aW5nIGludG8uICBJZiB0aGUgaWRlbnRpdHkgZG9lcyBub3QgaGF2ZSBhbnkKIyByb2xlIGFzc2lnbm1lbnRzIHNjb3BlZCBvbiB0aGUgc3Vic2NyaXB0aW9uIHdlJ3JlIGRlcGxveWluZyBpbnRvLCBpdCB3aWxsCiMgbm90IHNob3cgb24gYXogbG9naW4gLWksIHdoaWNoIGlzIHdoeSB0aGUgYmVsb3cgbGluZSBpcyBjb21tZW50ZWQuCiMgYXogYWNjb3VudCBzZXQgLXMgIiRTVUJTQ1JJUFRJT05JRCIKCiMgU3VwcHJlc3MgZW11bGF0aW9uIG91dHB1dCBmb3IgcG9kbWFuIGluc3RlYWQgb2YgZG9ja2VyIGZvciBheiBhY3IgY29tcGF0YWJpbGl0eQpta2RpciAtcCAvZXRjL2NvbnRhaW5lcnMvCnRvdWNoIC9ldGMvY29udGFpbmVycy9ub2RvY2tlcgoKbWtkaXIgLXAgL3Jvb3QvLmRvY2tlcgpSRUdJU1RSWV9BVVRIX0ZJTEU9L3Jvb3QvLmRvY2tlci9jb25maWcuanNvbiBheiBhY3IgbG9naW4gLS1uYW1lICIkKHNlZCAtZSAnc3wuKi98fCcgPDw8IiRBQ1JSRVNPVVJDRUlEIikiCgpNRE1JTUFHRT0iJHtSUElNQUdFJSUvKn0vJHtNRE1JTUFHRSMjKi99Igpkb2NrZXIgcHVsbCAiJE1ETUlNQUdFIgpkb2NrZXIgcHVsbCAiJFJQSU1BR0UiCmRvY2tlciBwdWxsICIkRkxVRU5UQklUSU1BR0UiCgpheiBsb2dvdXQKCmVjaG8gImNvbmZpZ3VyaW5nIGZsdWVudGJpdCBzZXJ2aWNlIgpta2RpciAtcCAvZXRjL2ZsdWVudGJpdC8KbWtkaXIgLXAgL3Zhci9saWIvZmx1ZW50CgpjYXQgPi9ldGMvZmx1ZW50Yml0L2ZsdWVudGJpdC5jb25mIDw8J0VPRicKW0lOUFVUXQoJTmFtZSBzeXN0ZW1kCglUYWcgam91cm5hbGQKCVN5c3RlbWRfRmlsdGVyIF9DT01NPWFybwoJREIgL3Zhci9saWIvZmx1ZW50L2pvdXJuYWxkYgoKW0ZJTFRFUl0KCU5hbWUgbW9kaWZ5CglNYXRjaCBqb3VybmFsZAoJUmVtb3ZlX3dpbGRjYXJkIF8KCVJlbW92ZSBUSU1FU1RBTVAKCltPVVRQVVRdCglOYW1lIGZvcndhcmQKCU1hdGNoICoKCVBvcnQgMjkyMzAKRU9GCgplY2hvICJGTFVFTlRCSVRJTUFHRT0kRkxVRU5UQklUSU1BR0UiID4vZXRjL3N5c2NvbmZpZy9mbHVlbnRiaXQKCmNhdCA+L2V0Yy9zeXN0ZW1kL3N5c3RlbS9mbHVlbnRiaXQuc2VydmljZSA8PCdFT0YnCltVbml0XQpBZnRlcj1uZXR3b3JrLW9ubGluZS50YXJnZXQKV2FudHM9bmV0d29yay1vbmxpbmUudGFyZ2V0ClN0YXJ0TGltaXRJbnRlcnZhbFNlYz0wCgpbU2VydmljZV0KUmVzdGFydFNlYz0xcwpFbnZpcm9ubWVudEZpbGU9L2V0Yy9zeXNjb25maWcvZmx1ZW50Yml0CkV4ZWNTdGFydFByZT0tL3Vzci9iaW4vZG9ja2VyIHJtIC1mICVOCkV4ZWNTdGFydD0vdXNyL2Jpbi9kb2NrZXIgcnVuIFwKICAtLXNlY3VyaXR5LW9wdCBsYWJlbD1kaXNhYmxlIFwKICAtLWVudHJ5cG9pbnQgL29wdC90ZC1hZ2VudC1iaXQvYmluL3RkLWFnZW50LWJpdCBcCiAgLS1uZXQ9aG9zdCBcCiAgLS1ob3N0bmFtZSAlSCBcCiAgLS1uYW1lICVOIFwKICAtLXJtIFwKICAtLWNhcC1kcm9wIG5ldF9yYXcgXAogIC12IC9ldGMvZmx1ZW50Yml0L2ZsdWVudGJpdC5jb25mOi9ldGMvZmx1ZW50Yml0L2ZsdWVudGJpdC5jb25mIFwKICAtdiAvdmFyL2xpYi9mbHVlbnQ6L3Zhci9saWIvZmx1ZW50OnogXAogIC12IC92YXIvbG9nL2pvdXJuYWw6L3Zhci9sb2cvam91cm5hbDpybyBcCiAgLXYgL2V0Yy9tYWNoaW5lLWlkOi9ldGMvbWFjaGluZS1pZDpybyBcCiAgJEZMVUVOVEJJVElNQUdFIFwKICAtYyAvZXRjL2ZsdWVudGJpdC9mbHVlbnRiaXQuY29uZgoKRXhlY1N0b3A9L3Vzci9iaW4vZG9ja2VyIHN0b3AgJU4KUmVzdGFydD1hbHdheXMKUmVzdGFydFNlYz01ClN0YXJ0TGltaXRJbnRlcnZhbD0wCgpbSW5zdGFsbF0KV2FudGVkQnk9bXVsdGktdXNlci50YXJnZXQKRU9GCgplY2hvICJjb25maWd1cmluZyBtZG0gc2VydmljZSIKY2F0ID4vZXRjL3N5c2NvbmZpZy9tZG0gPDxFT0YKTURNRlJPTlRFTkRVUkw9JyRNRE1GUk9OVEVORFVSTCcKTURNSU1BR0U9JyRNRE1JTUFHRScKTURNU09VUkNFRU5WSVJPTk1FTlQ9JyRMT0NBVElPTicKTURNU09VUkNFUk9MRT1nYXRld2F5Ck1ETVNPVVJDRVJPTEVJTlNUQU5DRT0nJChob3N0bmFtZSknCkVPRgoKbWtkaXIgL3Zhci9ldHcKY2F0ID4vZXRjL3N5c3RlbWQvc3lzdGVtL21kbS5zZXJ2aWNlIDw8J0VPRicKW1VuaXRdCkFmdGVyPW5ldHdvcmstb25saW5lLnRhcmdldApXYW50cz1uZXR3b3JrLW9ubGluZS50YXJnZXQKCltTZXJ2aWNlXQpFbnZpcm9ubWVudEZpbGU9L2V0Yy9zeXNjb25maWcvbWRtCkV4ZWNTdGFydFByZT0tL3Vzci9iaW4vZG9ja2VyIHJtIC1mICVOCkV4ZWNTdGFydD0vdXNyL2Jpbi9kb2NrZXIgcnVuIFwKICAtLWVudHJ5cG9pbnQgL3Vzci9zYmluL01ldHJpY3NFeHRlbnNpb24gXAogIC0taG9zdG5hbWUgJUggXAogIC0tbmFtZSAlTiBcCiAgLS1ybSBcCiAgLS1jYXAtZHJvcCBuZXRfcmF3IFwKICAtbSAyZyBcCiAgLXYgL2V0Yy9tZG0ucGVtOi9ldGMvbWRtLnBlbSBcCiAgLXYgL3Zhci9ldHc6L3Zhci9ldHc6eiBcCiAgJE1ETUlNQUdFIFwKICAtQ2VydEZpbGUgL2V0Yy9tZG0ucGVtIFwKICAtRnJvbnRFbmRVcmwgJE1ETUZST05URU5EVVJMIFwKICAtTG9nZ2VyIENvbnNvbGUgXAogIC1Mb2dMZXZlbCBXYXJuaW5nIFwKICAtUHJpdmF0ZUtleUZpbGUgL2V0Yy9tZG0ucGVtIFwKICAtU291cmNlRW52aXJvbm1lbnQgJE1ETVNPVVJDRUVOVklST05NRU5UIFwKICAtU291cmNlUm9sZSAkTURNU09VUkNFUk9MRSBcCiAgLVNvdXJjZVJvbGVJbnN0YW5jZSAkTURNU09VUkNFUk9MRUlOU1RBTkNFCkV4ZWNTdG9wPS91c3IvYmluL2RvY2tlciBzdG9wICVOClJlc3RhcnQ9YWx3YXlzClJlc3RhcnRTZWM9MQpTdGFydExpbWl0SW50ZXJ2YWw9MAoKW0luc3RhbGxdCldhbnRlZEJ5PW11bHRpLXVzZXIudGFyZ2V0CkVPRgoKZWNobyAiY29uZmlndXJpbmcgYXJvLWdhdGV3YXkgc2VydmljZSIKY2F0ID4vZXRjL3N5c2NvbmZpZy9hcm8tZ2F0ZXdheSA8PEVPRgpBQ1JfUkVTT1VSQ0VfSUQ9JyRBQ1JSRVNPVVJDRUlEJwpEQVRBQkFTRV9BQ0NPVU5UX05BTUU9JyREQVRBQkFTRUFDQ09VTlROQU1FJwpBWlVSRV9EQlRPS0VOX0NMSUVOVF9JRD0nJERCVE9LRU5DTElFTlRJRCcKREJUT0tFTl9VUkw9JyREQlRPS0VOVVJMJwpNRE1fQUNDT1VOVD0iJFJQTURNQUNDT1VOVCIKTURNX05BTUVTUEFDRT1HYXRld2F5CkdBVEVXQVlfRE9NQUlOUz0nJEdBVEVXQVlET01BSU5TJwpHQVRFV0FZX0ZFQVRVUkVTPSckR0FURVdBWUZFQVRVUkVTJwpSUElNQUdFPSckUlBJTUFHRScKRU9GCgpjYXQgPi9ldGMvc3lzdGVtZC9zeXN0ZW0vYXJvLWdhdGV3YXkuc2VydmljZSA8PEVPRgpbVW5pdF0KQWZ0ZXI9bmV0d29yay1vbmxpbmUudGFyZ2V0CldhbnRzPW5ldHdvcmstb25saW5lLnRhcmdldAoKW1NlcnZpY2VdCkVudmlyb25tZW50RmlsZT0vZXRjL3N5c2NvbmZpZy9hcm8tZ2F0ZXdheQpFeGVjU3RhcnRQcmU9LS91c3IvYmluL2RvY2tlciBybSAtZiAlTgpFeGVjU3RhcnRQcmU9L3Vzci9iaW4vbWtkaXIgLXAgJHtnYXRld2F5X2xvZ2Rpcn0KRXhlY1N0YXJ0PS91c3IvYmluL2RvY2tlciBydW4gXAogIC0taG9zdG5hbWUgJUggXAogIC0tbmFtZSAlTiBcCiAgLS1ybSBcCiAgLS1jYXAtZHJvcCBuZXRfcmF3IFwKICAtZSBBQ1JfUkVTT1VSQ0VfSUQgXAogIC1lIERBVEFCQVNFX0FDQ09VTlRfTkFNRSBcCiAgLWUgQVpVUkVfREJUT0tFTl9DTElFTlRfSUQgXAogIC1lIERCVE9LRU5fVVJMIFwKICAtZSBHQVRFV0FZX0RPTUFJTlMgXAogIC1lIEdBVEVXQVlfRkVBVFVSRVMgXAogIC1lIE1ETV9BQ0NPVU5UIFwKICAtZSBNRE1fTkFNRVNQQUNFIFwKICAtbSAyZyBcCiAgLXAgODA6ODA4MCBcCiAgLXAgODA4MTo4MDgxIFwKICAtcCA0NDM6ODQ0MyBcCiAgLXYgL3J1bi9zeXN0ZW1kL2pvdXJuYWw6L3J1bi9zeXN0ZW1kL2pvdXJuYWwgXAogIC12IC92YXIvZXR3Oi92YXIvZXR3OnogXAogIC12ICR7Z2F0ZXdheV9sb2dkaXJ9Oi9jdHIubG9nOnogXAogIFwkUlBJTUFHRSBcCiAgZ2F0ZXdheQpFeGVjU3RvcD0vdXNyL2Jpbi9kb2NrZXIgc3RvcCAtdCAzNjAwICVOClRpbWVvdXRTdG9wU2VjPTM2MDAKUmVzdGFydD1hbHdheXMKUmVzdGFydFNlYz0xClN0YXJ0TGltaXRJbnRlcnZhbD0wCgpbSW5zdGFsbF0KV2FudGVkQnk9bXVsdGktdXNlci50YXJnZXQKRU9GCgpjaGNvbiAtUiBzeXN0ZW1fdTpvYmplY3Rfcjp2YXJfbG9nX3Q6czAgL3Zhci9vcHQvbWljcm9zb2Z0L2xpbnV4bW9uYWdlbnQKCm1rZGlyIC1wIC92YXIvbGliL3dhYWdlbnQvTWljcm9zb2Z0LkF6dXJlLktleVZhdWx0LlN0b3JlCgplY2hvICJjb25maWd1cmluZyBtZHNkIGFuZCBtZG0gc2VydmljZXMiCmZvciB2YXIgaW4gIm1kc2QiICJtZG0iOyBkbwpjYXQgPi9ldGMvc3lzdGVtZC9zeXN0ZW0vZG93bmxvYWQtJHZhci1jcmVkZW50aWFscy5zZXJ2aWNlIDw8RU9GCltVbml0XQpEZXNjcmlwdGlvbj1QZXJpb2RpYyAkdmFyIGNyZWRlbnRpYWxzIHJlZnJlc2gKCltTZXJ2aWNlXQpUeXBlPW9uZXNob3QKRXhlY1N0YXJ0PS91c3IvbG9jYWwvYmluL2Rvd25sb2FkLWNyZWRlbnRpYWxzLnNoICR2YXIKRU9GCgpjYXQgPi9ldGMvc3lzdGVtZC9zeXN0ZW0vZG93bmxvYWQtJHZhci1jcmVkZW50aWFscy50aW1lciA8PEVPRgpbVW5pdF0KRGVzY3JpcHRpb249UGVyaW9kaWMgJHZhciBjcmVkZW50aWFscyByZWZyZXNoCkFmdGVyPW5ldHdvcmstb25saW5lLnRhcmdldApXYW50cz1uZXR3b3JrLW9ubGluZS50YXJnZXQKCltUaW1lcl0KT25Cb290U2VjPTBtaW4KT25DYWxlbmRhcj0wLzEyOjAwOjAwCkFjY3VyYWN5U2VjPTVzCgpbSW5zdGFsbF0KV2FudGVkQnk9dGltZXJzLnRhcmdldApFT0YKZG9uZQoKY2F0ID4vdXNyL2xvY2FsL2Jpbi9kb3dubG9hZC1jcmVkZW50aWFscy5zaCA8PEVPRgojIS9iaW4vYmFzaApzZXQgLWV1CgpDT01QT05FTlQ9IlwkMSIKZWNobyAiRG93bmxvYWQgXCRDT01QT05FTlQgY3JlZGVudGlhbHMiCgpURU1QX0RJUj1cJChta3RlbXAgLWQpCmV4cG9ydCBBWlVSRV9DT05GSUdfRElSPVwkKG1rdGVtcCAtZCkKCmVjaG8gIkxvZ2dpbmcgaW50byBBenVyZS4uLiIKUkVUUklFUz0zCndoaWxlIFsgIlwkUkVUUklFUyIgLWd0IDAgXTsgZG8KICAgIGlmIGF6IGxvZ2luIC1pIC0tYWxsb3ctbm8tc3Vic2NyaXB0aW9ucwogICAgdGhlbgogICAgICAgIGVjaG8gImF6IGxvZ2luIHN1Y2Nlc3NmdWwiCiAgICAgICAgYnJlYWsKICAgIGVsc2UKICAgICAgICBlY2hvICJheiBsb2dpbiBmYWlsZWQuIFJldHJ5aW5nLi4uIgogICAgICAgIGxldCBSRVRSSUVTLT0xCiAgICAgICAgc2xlZXAgNQogICAgZmkKZG9uZQoKdHJhcCAiY2xlYW51cCIgRVhJVAoKY2xlYW51cCgpIHsKICBheiBsb2dvdXQKICBbWyAiXCRURU1QX0RJUiIgPX4gL3RtcC8uKyBdXSAmJiBybSAtcmYgXCRURU1QX0RJUgogIFtbICJcJEFaVVJFX0NPTkZJR19ESVIiID1+IC90bXAvLisgXV0gJiYgcm0gLXJmIFwkQVpVUkVfQ09ORklHX0RJUgp9CgppZiBbICJcJENPTVBPTkVOVCIgPSAibWRtIiBdOyB0aGVuCiAgQ1VSUkVOVF9DRVJUX0ZJTEU9Ii9ldGMvbWRtLnBlbSIKZWxpZiBbICJcJENPTVBPTkVOVCIgPSAibWRzZCIgXTsgdGhlbgogIENVUlJFTlRfQ0VSVF9GSUxFPSIvdmFyL2xpYi93YWFnZW50L01pY3Jvc29mdC5BenVyZS5LZXlWYXVsdC5TdG9yZS9tZHNkLnBlbSIKZWxzZQogIGVjaG8gSW52YWxpZCB1c2FnZSAmJiBleGl0IDEKZmkKClNFQ1JFVF9OQU1FPSJnd3ktXCR7Q09NUE9ORU5UfSIKTkVXX0NFUlRfRklMRT0iXCRURU1QX0RJUi9cJENPTVBPTkVOVC5wZW0iCmZvciBhdHRlbXB0IGluIHsxLi41fTsgZG8KICBheiBrZXl2YXVsdCBzZWNyZXQgZG93bmxvYWQgLS1maWxlIFwkTkVXX0NFUlRfRklMRSAtLWlkICJodHRwczovLyRLRVlWQVVMVFBSRUZJWC1nd3kuJEtFWVZBVUxURE5TU1VGRklYL3NlY3JldHMvXCRTRUNSRVRfTkFNRSIgJiYgYnJlYWsKICBpZiBbWyBcJGF0dGVtcHQgLWx0IDUgXV07IHRoZW4gc2xlZXAgMTA7IGVsc2UgZXhpdCAxOyBmaQpkb25lCgppZiBbIC1mIFwkTkVXX0NFUlRfRklMRSBdOyB0aGVuCiAgaWYgWyAiXCRDT01QT05FTlQiID0gIm1kc2QiIF07IHRoZW4KICAgIGNob3duIHN5c2xvZzpzeXNsb2cgXCRORVdfQ0VSVF9GSUxFCiAgZWxzZQogICAgc2VkIC1pIC1uZSAnMSwvRU5EIENFUlRJRklDQVRFLyBwJyBcJE5FV19DRVJUX0ZJTEUKICBmaQoKICBuZXdfY2VydF9zbj0iXCQob3BlbnNzbCB4NTA5IC1pbiAiXCRORVdfQ0VSVF9GSUxFIiAtbm9vdXQgLXNlcmlhbCB8IGF3ayAtRj0gJ3twcmludCBcJDJ9JykiCiAgY3VycmVudF9jZXJ0X3NuPSJcJChvcGVuc3NsIHg1MDkgLWluICJcJENVUlJFTlRfQ0VSVF9GSUxFIiAtbm9vdXQgLXNlcmlhbCB8IGF3ayAtRj0gJ3twcmludCBcJDJ9JykiCiAgaWYgW1sgISAteiBcJG5ld19jZXJ0X3NuIF1dICYmIFtbIFwkbmV3X2NlcnRfc24gIT0gIlwkY3VycmVudF9jZXJ0X3NuIiBdXTsgdGhlbgogICAgZWNobyB1cGRhdGluZyBjZXJ0aWZpY2F0ZSBmb3IgXCRDT01QT05FTlQKICAgIGNobW9kIDA2MDAgXCRORVdfQ0VSVF9GSUxFCiAgICBtdiBcJE5FV19DRVJUX0ZJTEUgXCRDVVJSRU5UX0NFUlRfRklMRQogIGZpCmVsc2UKICBlY2hvIEZhaWxlZCB0byByZWZyZXNoIGNlcnRpZmljYXRlIGZvciBcJENPTVBPTkVOVCAmJiBleGl0IDEKZmkKRU9GCgpjaG1vZCB1K3ggL3Vzci9sb2NhbC9iaW4vZG93bmxvYWQtY3JlZGVudGlhbHMuc2gKCnN5c3RlbWN0bCBlbmFibGUgZG93bmxvYWQtbWRzZC1jcmVkZW50aWFscy50aW1lcgpzeXN0ZW1jdGwgZW5hYmxlIGRvd25sb2FkLW1kbS1jcmVkZW50aWFscy50aW1lcgoKL3Vzci9sb2NhbC9iaW4vZG93bmxvYWQtY3JlZGVudGlhbHMuc2ggbWRzZAovdXNyL2xvY2FsL2Jpbi9kb3dubG9hZC1jcmVkZW50aWFscy5zaCBtZG0KTURTRENFUlRJRklDQVRFU0FOPSQob3BlbnNzbCB4NTA5IC1pbiAvdmFyL2xpYi93YWFnZW50L01pY3Jvc29mdC5BenVyZS5LZXlWYXVsdC5TdG9yZS9tZHNkLnBlbSAtbm9vdXQgLXN1YmplY3QgfCBzZWQgLWUgJ3MvLipDTiA9IC8vJykKCmNhdCA+L2V0Yy9zeXN0ZW1kL3N5c3RlbS93YXRjaC1tZG0tY3JlZGVudGlhbHMuc2VydmljZSA8PEVPRgpbVW5pdF0KRGVzY3JpcHRpb249V2F0Y2ggZm9yIGNoYW5nZXMgaW4gbWRtLnBlbSBhbmQgcmVzdGFydHMgdGhlIG1kbSBzZXJ2aWNlCgpbU2VydmljZV0KVHlwZT1vbmVzaG90CkV4ZWNTdGFydD0vdXNyL2Jpbi9zeXN0ZW1jdGwgcmVzdGFydCBtZG0uc2VydmljZQoKW0luc3RhbGxdCldhbnRlZEJ5PW11bHRpLXVzZXIudGFyZ2V0CkVPRgoKY2F0ID4vZXRjL3N5c3RlbWQvc3lzdGVtL3dhdGNoLW1kbS1jcmVkZW50aWFscy5wYXRoIDw8RU9GCltQYXRoXQpQYXRoTW9kaWZpZWQ9L2V0Yy9tZG0ucGVtCgpbSW5zdGFsbF0KV2FudGVkQnk9bXVsdGktdXNlci50YXJnZXQKRU9GCgpzeXN0ZW1jdGwgZW5hYmxlIHdhdGNoLW1kbS1jcmVkZW50aWFscy5wYXRoCnN5c3RlbWN0bCBzdGFydCB3YXRjaC1tZG0tY3JlZGVudGlhbHMucGF0aAoKbWtkaXIgL2V0Yy9zeXN0ZW1kL3N5c3RlbS9tZHNkLnNlcnZpY2UuZApjYXQgPi9ldGMvc3lzdGVtZC9zeXN0ZW0vbWRzZC5zZXJ2aWNlLmQvb3ZlcnJpZGUuY29uZiA8PCdFT0YnCltVbml0XQpBZnRlcj1uZXR3b3JrLW9ubGluZS50YXJnZXQKRU9GCgpjYXQgPi9ldGMvZGVmYXVsdC9tZHNkIDw8RU9GCk1EU0RfUk9MRV9QUkVGSVg9L3Zhci9ydW4vbWRzZC9kZWZhdWx0Ck1EU0RfT1BUSU9OUz0iLUEgLWQgLXIgXCRNRFNEX1JPTEVfUFJFRklYIgoKZXhwb3J0IE1PTklUT1JJTkdfR0NTX0VOVklST05NRU5UPSckTURTREVOVklST05NRU5UJwpleHBvcnQgTU9OSVRPUklOR19HQ1NfQUNDT1VOVD0nJFJQTURTREFDQ09VTlQnCmV4cG9ydCBNT05JVE9SSU5HX0dDU19SRUdJT049JyRMT0NBVElPTicKZXhwb3J0IE1PTklUT1JJTkdfR0NTX0FVVEhfSURfVFlQRT1BdXRoS2V5VmF1bHQKZXhwb3J0IE1PTklUT1JJTkdfR0NTX0FVVEhfSUQ9JyRNRFNEQ0VSVElGSUNBVEVTQU4nCmV4cG9ydCBNT05JVE9SSU5HX0dDU19OQU1FU1BBQ0U9JyRSUE1EU0ROQU1FU1BBQ0UnCmV4cG9ydCBNT05JVE9SSU5HX0NPTkZJR19WRVJTSU9OPSckR0FURVdBWU1EU0RDT05GSUdWRVJTSU9OJwpleHBvcnQgTU9OSVRPUklOR19VU0VfR0VORVZBX0NPTkZJR19TRVJWSUNFPXRydWUKCmV4cG9ydCBNT05JVE9SSU5HX1RFTkFOVD0nJExPQ0FUSU9OJwpleHBvcnQgTU9OSVRPUklOR19ST0xFPWdhdGV3YXkKZXhwb3J0IE1PTklUT1JJTkdfUk9MRV9JTlNUQU5DRT0nJChob3N0bmFtZSknCgpleHBvcnQgTURTRF9NU0dQQUNLX1NPUlRfQ09MVU1OUz0xCkVPRgoKIyBzZXR0aW5nIE1PTklUT1JJTkdfR0NTX0FVVEhfSURfVFlQRT1BdXRoS2V5VmF1bHQgc2VlbXMgdG8gaGF2ZSBjYXVzZWQgbWRzZCBub3QKIyB0byBob25vdXIgU1NMX0NFUlRfRklMRSBhbnkgbW9yZSwgaGVhdmVuIG9ubHkga25vd3Mgd2h5Lgpta2RpciAtcCAvdXNyL2xpYi9zc2wvY2VydHMKY3NwbGl0IC1mIC91c3IvbGliL3NzbC9jZXJ0cy9jZXJ0LSAtYiAlMDNkLnBlbSAvZXRjL3BraS90bHMvY2VydHMvY2EtYnVuZGxlLmNydCAvXiQvMSB7Kn0gPi9kZXYvbnVsbApjX3JlaGFzaCAvdXNyL2xpYi9zc2wvY2VydHMKCiMgd2UgbGVhdmUgY2xpZW50SWQgYmxhbmsgYXMgbG9uZyBhcyBvbmx5IDEgbWFuYWdlZCBpZGVudGl0eSBhc3NpZ25lZCB0byB2bXNzCiMgaWYgd2UgaGF2ZSBtb3JlIHRoYW4gMSwgd2Ugd2lsbCBuZWVkIHRvIHBvcHVsYXRlIHdpdGggY2xpZW50SWQgdXNlZCBmb3Igb2ZmLW5vZGUgc2Nhbm5pbmcKY2F0ID4vZXRjL2RlZmF1bHQvdnNhLW5vZGVzY2FuLWFnZW50LmNvbmZpZyA8PEVPRgp7CiAgICAiTmljZSI6IDE5LAogICAgIlRpbWVvdXQiOiAxMDgwMCwKICAgICJDbGllbnRJZCI6ICIiLAogICAgIlRlbmFudElkIjogIiRBWlVSRVNFQ1BBQ0tWU0FURU5BTlRJRCIsCiAgICAiUXVhbHlzU3RvcmVCYXNlVXJsIjogIiRBWlVSRVNFQ1BBQ0tRVUFMWVNVUkwiLAogICAgIlByb2Nlc3NUaW1lb3V0IjogMzAwLAogICAgIkNvbW1hbmREZWxheSI6IDAKICB9CkVPRgoKZWNobyAiZW5hYmxpbmcgYXJvIHNlcnZpY2VzIgpmb3Igc2VydmljZSBpbiBhcm8tZ2F0ZXdheSBhdW9tcyBhenNlY2QgYXpzZWNtb25kIG1kc2QgbWRtIGNocm9ueWQgZmx1ZW50Yml0OyBkbwogIHN5c3RlbWN0bCBlbmFibGUgJHNlcnZpY2Uuc2VydmljZQpkb25lCgpmb3Igc2NhbiBpbiBiYXNlbGluZSBjbGFtYXYgc29mdHdhcmU7IGRvCiAgL3Vzci9sb2NhbC9iaW4vYXpzZWNkIGNvbmZpZyAtcyAkc2NhbiAtZCBQMUQKZG9uZQoKZWNobyAicmVib290aW5nIgpyZXN0b3JlY29uIC1SRiAvdmFyL2xvZy8qCihzbGVlcCAzMDsgcmVib290KSAmCg==')))]" + "script": "[base64(concat(base64ToString('c2V0IC1leAoK'),'ACRRESOURCEID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('acrResourceId')),''')\n','AZURECLOUDNAME=$(base64 -d \u003c\u003c\u003c''',base64(parameters('azureCloudName')),''')\n','AZURESECPACKQUALYSURL=$(base64 -d \u003c\u003c\u003c''',base64(parameters('azureSecPackQualysUrl')),''')\n','AZURESECPACKVSATENANTID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('azureSecPackVSATenantId')),''')\n','DATABASEACCOUNTNAME=$(base64 -d \u003c\u003c\u003c''',base64(parameters('databaseAccountName')),''')\n','DBTOKENCLIENTID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('dbtokenClientId')),''')\n','DBTOKENURL=$(base64 -d \u003c\u003c\u003c''',base64(parameters('dbtokenUrl')),''')\n','MDMFRONTENDURL=$(base64 -d \u003c\u003c\u003c''',base64(parameters('mdmFrontendUrl')),''')\n','MDSDENVIRONMENT=$(base64 -d \u003c\u003c\u003c''',base64(parameters('mdsdEnvironment')),''')\n','FLUENTBITIMAGE=$(base64 -d \u003c\u003c\u003c''',base64(parameters('fluentbitImage')),''')\n','GATEWAYMDSDCONFIGVERSION=$(base64 -d \u003c\u003c\u003c''',base64(parameters('gatewayMdsdConfigVersion')),''')\n','GATEWAYDOMAINS=$(base64 -d \u003c\u003c\u003c''',base64(parameters('gatewayDomains')),''')\n','GATEWAYFEATURES=$(base64 -d \u003c\u003c\u003c''',base64(parameters('gatewayFeatures')),''')\n','KEYVAULTDNSSUFFIX=$(base64 -d \u003c\u003c\u003c''',base64(parameters('keyvaultDNSSuffix')),''')\n','KEYVAULTPREFIX=$(base64 -d \u003c\u003c\u003c''',base64(parameters('keyvaultPrefix')),''')\n','RPIMAGE=$(base64 -d \u003c\u003c\u003c''',base64(parameters('rpImage')),''')\n','RPMDMACCOUNT=$(base64 -d \u003c\u003c\u003c''',base64(parameters('rpMdmAccount')),''')\n','RPMDSDACCOUNT=$(base64 -d \u003c\u003c\u003c''',base64(parameters('rpMdsdAccount')),''')\n','RPMDSDNAMESPACE=$(base64 -d \u003c\u003c\u003c''',base64(parameters('rpMdsdNamespace')),''')\n','MDMIMAGE=''/genevamdm:2.2024.328.1744-c5fb79-20240328t1935''\n','LOCATION=$(base64 -d \u003c\u003c\u003c''',base64(resourceGroup().location),''')\n','SUBSCRIPTIONID=$(base64 -d \u003c\u003c\u003c''',base64(subscription().subscriptionId),''')\n','RESOURCEGROUPNAME=$(base64 -d \u003c\u003c\u003c''',base64(resourceGroup().name),''')\n','\n',base64ToString('IyEvYmluL2Jhc2gKCmVjaG8gInNldHRpbmcgc3NoIHBhc3N3b3JkIGF1dGhlbnRpY2F0aW9uIgojIFdlIG5lZWQgdG8gbWFudWFsbHkgc2V0IFBhc3N3b3JkQXV0aGVudGljYXRpb24gdG8gdHJ1ZSBpbiBvcmRlciBmb3IgdGhlIFZNU1MgQWNjZXNzIEpJVCB0byB3b3JrCnNlZCAtaSAncy9QYXNzd29yZEF1dGhlbnRpY2F0aW9uIG5vL1Bhc3N3b3JkQXV0aGVudGljYXRpb24geWVzL2cnIC9ldGMvc3NoL3NzaGRfY29uZmlnCnN5c3RlbWN0bCByZWxvYWQgc3NoZC5zZXJ2aWNlCgojQWRkaW5nIHJldHJ5IGxvZ2ljIHRvIHl1bSBjb21tYW5kcyBpbiBvcmRlciB0byBhdm9pZCBzdGFsbGluZyBvdXQgb24gcmVzb3VyY2UgbG9ja3MKZWNobyAicnVubmluZyBSSFVJIGZpeCIKZm9yIGF0dGVtcHQgaW4gezEuLjV9OyBkbwogIHl1bSB1cGRhdGUgLXkgLS1kaXNhYmxlcmVwbz0nKicgLS1lbmFibGVyZXBvPSdyaHVpLW1pY3Jvc29mdC1henVyZSonICYmIGJyZWFrCiAgaWYgW1sgJHthdHRlbXB0fSAtbHQgNSBdXTsgdGhlbiBzbGVlcCAxMDsgZWxzZSBleGl0IDE7IGZpCmRvbmUKCmVjaG8gInJ1bm5pbmcgeXVtIHVwZGF0ZSIKZm9yIGF0dGVtcHQgaW4gezEuLjV9OyBkbwogIHl1bSAteSAteCBXQUxpbnV4QWdlbnQgLXggV0FMaW51eEFnZW50LXVkZXYgdXBkYXRlIC0tYWxsb3dlcmFzaW5nICYmIGJyZWFrCiAgaWYgW1sgJHthdHRlbXB0fSAtbHQgNSBdXTsgdGhlbiBzbGVlcCAxMDsgZWxzZSBleGl0IDE7IGZpCmRvbmUKCmVjaG8gImV4dGVuZGluZyBwYXJ0aXRpb24gdGFibGUiCiMgTGludXggYmxvY2sgZGV2aWNlcyBhcmUgaW5jb25zaXN0ZW50bHkgbmFtZWQKIyBpdCdzIGRpZmZpY3VsdCB0byB0aWUgdGhlIGx2bSBwdiB0byB0aGUgcGh5c2ljYWwgZGlzayB1c2luZyAvZGV2L2Rpc2sgZmlsZXMsIHdoaWNoIGlzIHdoeSBsdnMgaXMgdXNlZCBoZXJlCnBoeXNpY2FsX2Rpc2s9IiQobHZzIC1vIGRldmljZXMgLWEgfCBoZWFkIC1uMiB8IHRhaWwgLW4xIHwgY3V0IC1kICcgJyAtZiAzIHwgY3V0IC1kIFwoIC1mIDEgfCB0ciAtZCAnWzpkaWdpdDpdJykiCmdyb3dwYXJ0ICIkcGh5c2ljYWxfZGlzayIgMgoKZWNobyAiZXh0ZW5kaW5nIGZpbGVzeXN0ZW1zIgpsdmV4dGVuZCAtbCArMjAlRlJFRSAvZGV2L3Jvb3R2Zy9yb290bHYKeGZzX2dyb3dmcyAvCgpsdmV4dGVuZCAtbCArMTAwJUZSRUUgL2Rldi9yb290dmcvdmFybHYKeGZzX2dyb3dmcyAvdmFyCgpycG0gLS1pbXBvcnQgaHR0cHM6Ly9kbC5mZWRvcmFwcm9qZWN0Lm9yZy9wdWIvZXBlbC9SUE0tR1BHLUtFWS1FUEVMLTgKcnBtIC0taW1wb3J0IGh0dHBzOi8vcGFja2FnZXMubWljcm9zb2Z0LmNvbS9rZXlzL21pY3Jvc29mdC5hc2MKCmZvciBhdHRlbXB0IGluIHsxLi41fTsgZG8KICB5dW0gLXkgaW5zdGFsbCBodHRwczovL2RsLmZlZG9yYXByb2plY3Qub3JnL3B1Yi9lcGVsL2VwZWwtcmVsZWFzZS1sYXRlc3QtOC5ub2FyY2gucnBtICYmIGJyZWFrCiAgaWYgW1sgJHthdHRlbXB0fSAtbHQgNSBdXTsgdGhlbiBzbGVlcCAxMDsgZWxzZSBleGl0IDE7IGZpCmRvbmUKCmVjaG8gImNvbmZpZ3VyaW5nIGxvZ3JvdGF0ZSIKCiMgZ2F0ZXdheV9sb2dkaXIgaXMgYSByZWFkb25seSB2YXJpYWJsZSB0aGF0IHNwZWNpZmllcyB0aGUgaG9zdCBwYXRoIG1vdW50IHBvaW50IGZvciB0aGUgZ2F0ZXdheSBjb250YWluZXIgbG9nIGZpbGUKIyBmb3IgdGhlIHB1cnBvc2Ugb2Ygcm90YXRpbmcgdGhlIGdhdGV3YXkgbG9ncwpkZWNsYXJlIC1yIGdhdGV3YXlfbG9nZGlyPScvdmFyL2xvZy9hcm8tZ2F0ZXdheScKCmNhdCA+L2V0Yy9sb2dyb3RhdGUuY29uZiA8PEVPRgojIHNlZSAibWFuIGxvZ3JvdGF0ZSIgZm9yIGRldGFpbHMKIyByb3RhdGUgbG9nIGZpbGVzIHdlZWtseQp3ZWVrbHkKCiMga2VlcCAyIHdlZWtzIHdvcnRoIG9mIGJhY2tsb2dzCnJvdGF0ZSAyCgojIGNyZWF0ZSBuZXcgKGVtcHR5KSBsb2cgZmlsZXMgYWZ0ZXIgcm90YXRpbmcgb2xkIG9uZXMKY3JlYXRlCgojIHVzZSBkYXRlIGFzIGEgc3VmZml4IG9mIHRoZSByb3RhdGVkIGZpbGUKZGF0ZWV4dAoKIyB1bmNvbW1lbnQgdGhpcyBpZiB5b3Ugd2FudCB5b3VyIGxvZyBmaWxlcyBjb21wcmVzc2VkCmNvbXByZXNzCgojIFJQTSBwYWNrYWdlcyBkcm9wIGxvZyByb3RhdGlvbiBpbmZvcm1hdGlvbiBpbnRvIHRoaXMgZGlyZWN0b3J5CmluY2x1ZGUgL2V0Yy9sb2dyb3RhdGUuZAoKIyBubyBwYWNrYWdlcyBvd24gd3RtcCBhbmQgYnRtcCAtLSB3ZSdsbCByb3RhdGUgdGhlbSBoZXJlCi92YXIvbG9nL3d0bXAgewogICAgbW9udGhseQogICAgY3JlYXRlIDA2NjQgcm9vdCB1dG1wCiAgICAgICAgbWluc2l6ZSAxTQogICAgcm90YXRlIDEKfQoKL3Zhci9sb2cvYnRtcCB7CiAgICBtaXNzaW5nb2sKICAgIG1vbnRobHkKICAgIGNyZWF0ZSAwNjAwIHJvb3QgdXRtcAogICAgcm90YXRlIDEKfQoKIyBNYXhpbXVtIGxvZyBkaXJlY3Rvcnkgc2l6ZSBpcyAxMDBHIHdpdGggdGhpcyBjb25maWd1cmF0aW9uCiMgU2V0dGluZyBsaW1pdCB0byAxMDBHIHRvIGFsbG93IHNwYWNlIGZvciBvdGhlciBsb2dnaW5nIHNlcnZpY2VzCiMgY29weXRydW5jYXRlIGlzIGEgY3JpdGljYWwgb3B0aW9uIHVzZWQgdG8gcHJldmVudCBsb2dzIGZyb20gYmVpbmcgc2hpcHBlZCB0d2ljZQoke2dhdGV3YXlfbG9nZGlyfSB7CiAgICBzaXplIDIwRwogICAgcm90YXRlIDUKICAgIGNyZWF0ZSAwNjAwIHJvb3Qgcm9vdAogICAgY29weXRydW5jYXRlCiAgICBub29sZGRpcgogICAgY29tcHJlc3MKfQpFT0YKCmVjaG8gImNvbmZpZ3VyaW5nIHl1bSByZXBvc2l0b3J5IGFuZCBydW5uaW5nIHl1bSB1cGRhdGUiCmNhdCA+L2V0Yy95dW0ucmVwb3MuZC9henVyZS5yZXBvIDw8J0VPRicKW2F6dXJlLWNsaV0KbmFtZT1henVyZS1jbGkKYmFzZXVybD1odHRwczovL3BhY2thZ2VzLm1pY3Jvc29mdC5jb20veXVtcmVwb3MvYXp1cmUtY2xpCmVuYWJsZWQ9eWVzCmdwZ2NoZWNrPXllcwoKW2F6dXJlY29yZV0KbmFtZT1henVyZWNvcmUKYmFzZXVybD1odHRwczovL3BhY2thZ2VzLm1pY3Jvc29mdC5jb20veXVtcmVwb3MvYXp1cmVjb3JlCmVuYWJsZWQ9eWVzCmdwZ2NoZWNrPW5vCkVPRgoKc2VtYW5hZ2UgZmNvbnRleHQgLWEgLXQgdmFyX2xvZ190ICIvdmFyL2xvZy9qb3VybmFsKC8uKik/Igpta2RpciAtcCAvdmFyL2xvZy9qb3VybmFsCgpmb3IgYXR0ZW1wdCBpbiB7MS4uNX07IGRvCiAgeXVtIC15IGluc3RhbGwgY2xhbWF2IGF6c2VjLWNsYW1hdiBhenNlYy1tb25pdG9yIGF6dXJlLWNsaSBhenVyZS1tZHNkIGF6dXJlLXNlY3VyaXR5IHBvZG1hbi1kb2NrZXIgb3BlbnNzbC1wZXJsIHB5dGhvbjMgJiYgYnJlYWsKICAjIGhhY2sgLSB3ZSBhcmUgaW5zdGFsbGluZyBweXRob24zIG9uIGhvc3RzIGR1ZSB0byBhbiBpc3N1ZSB3aXRoIEF6dXJlIExpbnV4IEV4dGVuc2lvbnMgaHR0cHM6Ly9naXRodWIuY29tL0F6dXJlL2F6dXJlLWxpbnV4LWV4dGVuc2lvbnMvcHVsbC8xNTA1CiAgaWYgW1sgJHthdHRlbXB0fSAtbHQgNSBdXTsgdGhlbiBzbGVlcCAxMDsgZWxzZSBleGl0IDE7IGZpCmRvbmUKCmVjaG8gImFwcGx5aW5nIGZpcmV3YWxsIHJ1bGVzIgojIGh0dHBzOi8vYWNjZXNzLnJlZGhhdC5jb20vc2VjdXJpdHkvY3ZlL2N2ZS0yMDIwLTEzNDAxCmNhdCA+L2V0Yy9zeXNjdGwuZC8wMi1kaXNhYmxlLWFjY2VwdC1yYS5jb25mIDw8J0VPRicKbmV0LmlwdjYuY29uZi5hbGwuYWNjZXB0X3JhPTAKRU9GCgpjYXQgPi9ldGMvc3lzY3RsLmQvMDEtZGlzYWJsZS1jb3JlLmNvbmYgPDwnRU9GJwprZXJuZWwuY29yZV9wYXR0ZXJuID0gfC9iaW4vdHJ1ZQpFT0YKc3lzY3RsIC0tc3lzdGVtCgpmaXJld2FsbC1jbWQgLS1hZGQtcG9ydD04MC90Y3AgLS1wZXJtYW5lbnQKZmlyZXdhbGwtY21kIC0tYWRkLXBvcnQ9ODA4MS90Y3AgLS1wZXJtYW5lbnQKZmlyZXdhbGwtY21kIC0tYWRkLXBvcnQ9NDQzL3RjcCAtLXBlcm1hbmVudAoKZWNobyAibG9nZ2luZyBpbnRvIHByb2QgYWNyIgpleHBvcnQgQVpVUkVfQ0xPVURfTkFNRT0kQVpVUkVDTE9VRE5BTUUKYXogbG9naW4gLWkgLS1hbGxvdy1uby1zdWJzY3JpcHRpb25zCgojIFRoZSBtYW5hZ2VkIGlkZW50aXR5IHRoYXQgdGhlIFZNIHJ1bnMgYXMgb25seSBoYXMgYSBzaW5nbGUgcm9sZWFzc2lnbm1lbnQuCiMgVGhpcyByb2xlIGFzc2lnbm1lbnQgaXMgQUNSUHVsbCB3aGljaCBpcyBub3QgbmVjZXNzYXJpbHkgcHJlc2VudCBpbiB0aGUKIyBzdWJzY3JpcHRpb24gd2UncmUgZGVwbG95aW5nIGludG8uICBJZiB0aGUgaWRlbnRpdHkgZG9lcyBub3QgaGF2ZSBhbnkKIyByb2xlIGFzc2lnbm1lbnRzIHNjb3BlZCBvbiB0aGUgc3Vic2NyaXB0aW9uIHdlJ3JlIGRlcGxveWluZyBpbnRvLCBpdCB3aWxsCiMgbm90IHNob3cgb24gYXogbG9naW4gLWksIHdoaWNoIGlzIHdoeSB0aGUgYmVsb3cgbGluZSBpcyBjb21tZW50ZWQuCiMgYXogYWNjb3VudCBzZXQgLXMgIiRTVUJTQ1JJUFRJT05JRCIKCiMgU3VwcHJlc3MgZW11bGF0aW9uIG91dHB1dCBmb3IgcG9kbWFuIGluc3RlYWQgb2YgZG9ja2VyIGZvciBheiBhY3IgY29tcGF0YWJpbGl0eQpta2RpciAtcCAvZXRjL2NvbnRhaW5lcnMvCnRvdWNoIC9ldGMvY29udGFpbmVycy9ub2RvY2tlcgoKbWtkaXIgLXAgL3Jvb3QvLmRvY2tlcgpSRUdJU1RSWV9BVVRIX0ZJTEU9Ii9yb290Ly5kb2NrZXIvY29uZmlnLmpzb24iCmF6IGFjciBsb2dpbiAtLW5hbWUgIiQoc2VkIC1lICdzfC4qL3x8JyA8PDwiJEFDUlJFU09VUkNFSUQiKSIKCk1ETUlNQUdFPSIke1JQSU1BR0UlJS8qfS8ke01ETUlNQUdFIyMqL30iCmRvY2tlciBwdWxsICIkTURNSU1BR0UiCmRvY2tlciBwdWxsICIkUlBJTUFHRSIKZG9ja2VyIHB1bGwgIiRGTFVFTlRCSVRJTUFHRSIKCmF6IGxvZ291dAoKZWNobyAiY29uZmlndXJpbmcgZmx1ZW50Yml0IHNlcnZpY2UiCm1rZGlyIC1wIC9ldGMvZmx1ZW50Yml0Lwpta2RpciAtcCAvdmFyL2xpYi9mbHVlbnQKCmNhdCA+L2V0Yy9mbHVlbnRiaXQvZmx1ZW50Yml0LmNvbmYgPDwnRU9GJwpbSU5QVVRdCglOYW1lIHN5c3RlbWQKCVRhZyBqb3VybmFsZAoJU3lzdGVtZF9GaWx0ZXIgX0NPTU09YXJvCglEQiAvdmFyL2xpYi9mbHVlbnQvam91cm5hbGRiCgpbRklMVEVSXQoJTmFtZSBtb2RpZnkKCU1hdGNoIGpvdXJuYWxkCglSZW1vdmVfd2lsZGNhcmQgXwoJUmVtb3ZlIFRJTUVTVEFNUAoKW09VVFBVVF0KCU5hbWUgZm9yd2FyZAoJTWF0Y2ggKgoJUG9ydCAyOTIzMApFT0YKCmVjaG8gIkZMVUVOVEJJVElNQUdFPSRGTFVFTlRCSVRJTUFHRSIgPi9ldGMvc3lzY29uZmlnL2ZsdWVudGJpdAoKY2F0ID4vZXRjL3N5c3RlbWQvc3lzdGVtL2ZsdWVudGJpdC5zZXJ2aWNlIDw8J0VPRicKW1VuaXRdCkFmdGVyPW5ldHdvcmstb25saW5lLnRhcmdldApXYW50cz1uZXR3b3JrLW9ubGluZS50YXJnZXQKU3RhcnRMaW1pdEludGVydmFsU2VjPTAKCltTZXJ2aWNlXQpSZXN0YXJ0U2VjPTFzCkVudmlyb25tZW50RmlsZT0vZXRjL3N5c2NvbmZpZy9mbHVlbnRiaXQKRXhlY1N0YXJ0UHJlPS0vdXNyL2Jpbi9kb2NrZXIgcm0gLWYgJU4KRXhlY1N0YXJ0PS91c3IvYmluL2RvY2tlciBydW4gXAogIC0tc2VjdXJpdHktb3B0IGxhYmVsPWRpc2FibGUgXAogIC0tZW50cnlwb2ludCAvb3B0L3RkLWFnZW50LWJpdC9iaW4vdGQtYWdlbnQtYml0IFwKICAtLW5ldD1ob3N0IFwKICAtLWhvc3RuYW1lICVIIFwKICAtLW5hbWUgJU4gXAogIC0tcm0gXAogIC0tY2FwLWRyb3AgbmV0X3JhdyBcCiAgLXYgL2V0Yy9mbHVlbnRiaXQvZmx1ZW50Yml0LmNvbmY6L2V0Yy9mbHVlbnRiaXQvZmx1ZW50Yml0LmNvbmYgXAogIC12IC92YXIvbGliL2ZsdWVudDovdmFyL2xpYi9mbHVlbnQ6eiBcCiAgLXYgL3Zhci9sb2cvam91cm5hbDovdmFyL2xvZy9qb3VybmFsOnJvIFwKICAtdiAvZXRjL21hY2hpbmUtaWQ6L2V0Yy9tYWNoaW5lLWlkOnJvIFwKICAkRkxVRU5UQklUSU1BR0UgXAogIC1jIC9ldGMvZmx1ZW50Yml0L2ZsdWVudGJpdC5jb25mCgpFeGVjU3RvcD0vdXNyL2Jpbi9kb2NrZXIgc3RvcCAlTgpSZXN0YXJ0PWFsd2F5cwpSZXN0YXJ0U2VjPTUKU3RhcnRMaW1pdEludGVydmFsPTAKCltJbnN0YWxsXQpXYW50ZWRCeT1tdWx0aS11c2VyLnRhcmdldApFT0YKCmVjaG8gImNvbmZpZ3VyaW5nIG1kbSBzZXJ2aWNlIgpjYXQgPi9ldGMvc3lzY29uZmlnL21kbSA8PEVPRgpNRE1GUk9OVEVORFVSTD0nJE1ETUZST05URU5EVVJMJwpNRE1JTUFHRT0nJE1ETUlNQUdFJwpNRE1TT1VSQ0VFTlZJUk9OTUVOVD0nJExPQ0FUSU9OJwpNRE1TT1VSQ0VST0xFPWdhdGV3YXkKTURNU09VUkNFUk9MRUlOU1RBTkNFPSckKGhvc3RuYW1lKScKRU9GCgpta2RpciAvdmFyL2V0dwpjYXQgPi9ldGMvc3lzdGVtZC9zeXN0ZW0vbWRtLnNlcnZpY2UgPDwnRU9GJwpbVW5pdF0KQWZ0ZXI9bmV0d29yay1vbmxpbmUudGFyZ2V0CldhbnRzPW5ldHdvcmstb25saW5lLnRhcmdldAoKW1NlcnZpY2VdCkVudmlyb25tZW50RmlsZT0vZXRjL3N5c2NvbmZpZy9tZG0KRXhlY1N0YXJ0UHJlPS0vdXNyL2Jpbi9kb2NrZXIgcm0gLWYgJU4KRXhlY1N0YXJ0PS91c3IvYmluL2RvY2tlciBydW4gXAogIC0tZW50cnlwb2ludCAvdXNyL3NiaW4vTWV0cmljc0V4dGVuc2lvbiBcCiAgLS1ob3N0bmFtZSAlSCBcCiAgLS1uYW1lICVOIFwKICAtLXJtIFwKICAtLWNhcC1kcm9wIG5ldF9yYXcgXAogIC1tIDJnIFwKICAtdiAvZXRjL21kbS5wZW06L2V0Yy9tZG0ucGVtIFwKICAtdiAvdmFyL2V0dzovdmFyL2V0dzp6IFwKICAkTURNSU1BR0UgXAogIC1DZXJ0RmlsZSAvZXRjL21kbS5wZW0gXAogIC1Gcm9udEVuZFVybCAkTURNRlJPTlRFTkRVUkwgXAogIC1Mb2dnZXIgQ29uc29sZSBcCiAgLUxvZ0xldmVsIFdhcm5pbmcgXAogIC1Qcml2YXRlS2V5RmlsZSAvZXRjL21kbS5wZW0gXAogIC1Tb3VyY2VFbnZpcm9ubWVudCAkTURNU09VUkNFRU5WSVJPTk1FTlQgXAogIC1Tb3VyY2VSb2xlICRNRE1TT1VSQ0VST0xFIFwKICAtU291cmNlUm9sZUluc3RhbmNlICRNRE1TT1VSQ0VST0xFSU5TVEFOQ0UKRXhlY1N0b3A9L3Vzci9iaW4vZG9ja2VyIHN0b3AgJU4KUmVzdGFydD1hbHdheXMKUmVzdGFydFNlYz0xClN0YXJ0TGltaXRJbnRlcnZhbD0wCgpbSW5zdGFsbF0KV2FudGVkQnk9bXVsdGktdXNlci50YXJnZXQKRU9GCgplY2hvICJjb25maWd1cmluZyBhcm8tZ2F0ZXdheSBzZXJ2aWNlIgpjYXQgPi9ldGMvc3lzY29uZmlnL2Fyby1nYXRld2F5IDw8RU9GCkFDUl9SRVNPVVJDRV9JRD0nJEFDUlJFU09VUkNFSUQnCkRBVEFCQVNFX0FDQ09VTlRfTkFNRT0nJERBVEFCQVNFQUNDT1VOVE5BTUUnCkFaVVJFX0RCVE9LRU5fQ0xJRU5UX0lEPSckREJUT0tFTkNMSUVOVElEJwpEQlRPS0VOX1VSTD0nJERCVE9LRU5VUkwnCk1ETV9BQ0NPVU5UPSIkUlBNRE1BQ0NPVU5UIgpNRE1fTkFNRVNQQUNFPUdhdGV3YXkKR0FURVdBWV9ET01BSU5TPSckR0FURVdBWURPTUFJTlMnCkdBVEVXQVlfRkVBVFVSRVM9JyRHQVRFV0FZRkVBVFVSRVMnClJQSU1BR0U9JyRSUElNQUdFJwpFT0YKCmNhdCA+L2V0Yy9zeXN0ZW1kL3N5c3RlbS9hcm8tZ2F0ZXdheS5zZXJ2aWNlIDw8RU9GCltVbml0XQpBZnRlcj1uZXR3b3JrLW9ubGluZS50YXJnZXQKV2FudHM9bmV0d29yay1vbmxpbmUudGFyZ2V0CgpbU2VydmljZV0KRW52aXJvbm1lbnRGaWxlPS9ldGMvc3lzY29uZmlnL2Fyby1nYXRld2F5CkV4ZWNTdGFydFByZT0tL3Vzci9iaW4vZG9ja2VyIHJtIC1mICVOCkV4ZWNTdGFydFByZT0vdXNyL2Jpbi9ta2RpciAtcCAke2dhdGV3YXlfbG9nZGlyfQpFeGVjU3RhcnQ9L3Vzci9iaW4vZG9ja2VyIHJ1biBcCiAgLS1ob3N0bmFtZSAlSCBcCiAgLS1uYW1lICVOIFwKICAtLXJtIFwKICAtLWNhcC1kcm9wIG5ldF9yYXcgXAogIC1lIEFDUl9SRVNPVVJDRV9JRCBcCiAgLWUgREFUQUJBU0VfQUNDT1VOVF9OQU1FIFwKICAtZSBBWlVSRV9EQlRPS0VOX0NMSUVOVF9JRCBcCiAgLWUgREJUT0tFTl9VUkwgXAogIC1lIEdBVEVXQVlfRE9NQUlOUyBcCiAgLWUgR0FURVdBWV9GRUFUVVJFUyBcCiAgLWUgTURNX0FDQ09VTlQgXAogIC1lIE1ETV9OQU1FU1BBQ0UgXAogIC1tIDJnIFwKICAtcCA4MDo4MDgwIFwKICAtcCA4MDgxOjgwODEgXAogIC1wIDQ0Mzo4NDQzIFwKICAtdiAvcnVuL3N5c3RlbWQvam91cm5hbDovcnVuL3N5c3RlbWQvam91cm5hbCBcCiAgLXYgL3Zhci9ldHc6L3Zhci9ldHc6eiBcCiAgLXYgJHtnYXRld2F5X2xvZ2Rpcn06L2N0ci5sb2c6eiBcCiAgXCRSUElNQUdFIFwKICBnYXRld2F5CkV4ZWNTdG9wPS91c3IvYmluL2RvY2tlciBzdG9wIC10IDM2MDAgJU4KVGltZW91dFN0b3BTZWM9MzYwMApSZXN0YXJ0PWFsd2F5cwpSZXN0YXJ0U2VjPTEKU3RhcnRMaW1pdEludGVydmFsPTAKCltJbnN0YWxsXQpXYW50ZWRCeT1tdWx0aS11c2VyLnRhcmdldApFT0YKCmNoY29uIC1SIHN5c3RlbV91Om9iamVjdF9yOnZhcl9sb2dfdDpzMCAvdmFyL29wdC9taWNyb3NvZnQvbGludXhtb25hZ2VudAoKbWtkaXIgLXAgL3Zhci9saWIvd2FhZ2VudC9NaWNyb3NvZnQuQXp1cmUuS2V5VmF1bHQuU3RvcmUKCmVjaG8gImNvbmZpZ3VyaW5nIG1kc2QgYW5kIG1kbSBzZXJ2aWNlcyIKZm9yIHZhciBpbiAibWRzZCIgIm1kbSI7IGRvCmNhdCA+L2V0Yy9zeXN0ZW1kL3N5c3RlbS9kb3dubG9hZC0kdmFyLWNyZWRlbnRpYWxzLnNlcnZpY2UgPDxFT0YKW1VuaXRdCkRlc2NyaXB0aW9uPVBlcmlvZGljICR2YXIgY3JlZGVudGlhbHMgcmVmcmVzaAoKW1NlcnZpY2VdClR5cGU9b25lc2hvdApFeGVjU3RhcnQ9L3Vzci9sb2NhbC9iaW4vZG93bmxvYWQtY3JlZGVudGlhbHMuc2ggJHZhcgpFT0YKCmNhdCA+L2V0Yy9zeXN0ZW1kL3N5c3RlbS9kb3dubG9hZC0kdmFyLWNyZWRlbnRpYWxzLnRpbWVyIDw8RU9GCltVbml0XQpEZXNjcmlwdGlvbj1QZXJpb2RpYyAkdmFyIGNyZWRlbnRpYWxzIHJlZnJlc2gKQWZ0ZXI9bmV0d29yay1vbmxpbmUudGFyZ2V0CldhbnRzPW5ldHdvcmstb25saW5lLnRhcmdldAoKW1RpbWVyXQpPbkJvb3RTZWM9MG1pbgpPbkNhbGVuZGFyPTAvMTI6MDA6MDAKQWNjdXJhY3lTZWM9NXMKCltJbnN0YWxsXQpXYW50ZWRCeT10aW1lcnMudGFyZ2V0CkVPRgpkb25lCgpjYXQgPi91c3IvbG9jYWwvYmluL2Rvd25sb2FkLWNyZWRlbnRpYWxzLnNoIDw8RU9GCiMhL2Jpbi9iYXNoCnNldCAtZXUKCkNPTVBPTkVOVD0iXCQxIgplY2hvICJEb3dubG9hZCBcJENPTVBPTkVOVCBjcmVkZW50aWFscyIKClRFTVBfRElSPVwkKG1rdGVtcCAtZCkKZXhwb3J0IEFaVVJFX0NPTkZJR19ESVI9XCQobWt0ZW1wIC1kKQoKZWNobyAiTG9nZ2luZyBpbnRvIEF6dXJlLi4uIgpSRVRSSUVTPTMKd2hpbGUgWyAiXCRSRVRSSUVTIiAtZ3QgMCBdOyBkbwogICAgaWYgYXogbG9naW4gLWkgLS1hbGxvdy1uby1zdWJzY3JpcHRpb25zCiAgICB0aGVuCiAgICAgICAgZWNobyAiYXogbG9naW4gc3VjY2Vzc2Z1bCIKICAgICAgICBicmVhawogICAgZWxzZQogICAgICAgIGVjaG8gImF6IGxvZ2luIGZhaWxlZC4gUmV0cnlpbmcuLi4iCiAgICAgICAgbGV0IFJFVFJJRVMtPTEKICAgICAgICBzbGVlcCA1CiAgICBmaQpkb25lCgp0cmFwICJjbGVhbnVwIiBFWElUCgpjbGVhbnVwKCkgewogIGF6IGxvZ291dAogIFtbICJcJFRFTVBfRElSIiA9fiAvdG1wLy4rIF1dICYmIHJtIC1yZiBcJFRFTVBfRElSCiAgW1sgIlwkQVpVUkVfQ09ORklHX0RJUiIgPX4gL3RtcC8uKyBdXSAmJiBybSAtcmYgXCRBWlVSRV9DT05GSUdfRElSCn0KCmlmIFsgIlwkQ09NUE9ORU5UIiA9ICJtZG0iIF07IHRoZW4KICBDVVJSRU5UX0NFUlRfRklMRT0iL2V0Yy9tZG0ucGVtIgplbGlmIFsgIlwkQ09NUE9ORU5UIiA9ICJtZHNkIiBdOyB0aGVuCiAgQ1VSUkVOVF9DRVJUX0ZJTEU9Ii92YXIvbGliL3dhYWdlbnQvTWljcm9zb2Z0LkF6dXJlLktleVZhdWx0LlN0b3JlL21kc2QucGVtIgplbHNlCiAgZWNobyBJbnZhbGlkIHVzYWdlICYmIGV4aXQgMQpmaQoKU0VDUkVUX05BTUU9Imd3eS1cJHtDT01QT05FTlR9IgpORVdfQ0VSVF9GSUxFPSJcJFRFTVBfRElSL1wkQ09NUE9ORU5ULnBlbSIKZm9yIGF0dGVtcHQgaW4gezEuLjV9OyBkbwogIGF6IGtleXZhdWx0IHNlY3JldCBkb3dubG9hZCAtLWZpbGUgXCRORVdfQ0VSVF9GSUxFIC0taWQgImh0dHBzOi8vJEtFWVZBVUxUUFJFRklYLWd3eS4kS0VZVkFVTFRETlNTVUZGSVgvc2VjcmV0cy9cJFNFQ1JFVF9OQU1FIiAmJiBicmVhawogIGlmIFtbIFwkYXR0ZW1wdCAtbHQgNSBdXTsgdGhlbiBzbGVlcCAxMDsgZWxzZSBleGl0IDE7IGZpCmRvbmUKCmlmIFsgLWYgXCRORVdfQ0VSVF9GSUxFIF07IHRoZW4KICBpZiBbICJcJENPTVBPTkVOVCIgPSAibWRzZCIgXTsgdGhlbgogICAgY2hvd24gc3lzbG9nOnN5c2xvZyBcJE5FV19DRVJUX0ZJTEUKICBlbHNlCiAgICBzZWQgLWkgLW5lICcxLC9FTkQgQ0VSVElGSUNBVEUvIHAnIFwkTkVXX0NFUlRfRklMRQogIGZpCgogIG5ld19jZXJ0X3NuPSJcJChvcGVuc3NsIHg1MDkgLWluICJcJE5FV19DRVJUX0ZJTEUiIC1ub291dCAtc2VyaWFsIHwgYXdrIC1GPSAne3ByaW50IFwkMn0nKSIKICBjdXJyZW50X2NlcnRfc249IlwkKG9wZW5zc2wgeDUwOSAtaW4gIlwkQ1VSUkVOVF9DRVJUX0ZJTEUiIC1ub291dCAtc2VyaWFsIHwgYXdrIC1GPSAne3ByaW50IFwkMn0nKSIKICBpZiBbWyAhIC16IFwkbmV3X2NlcnRfc24gXV0gJiYgW1sgXCRuZXdfY2VydF9zbiAhPSAiXCRjdXJyZW50X2NlcnRfc24iIF1dOyB0aGVuCiAgICBlY2hvIHVwZGF0aW5nIGNlcnRpZmljYXRlIGZvciBcJENPTVBPTkVOVAogICAgY2htb2QgMDYwMCBcJE5FV19DRVJUX0ZJTEUKICAgIG12IFwkTkVXX0NFUlRfRklMRSBcJENVUlJFTlRfQ0VSVF9GSUxFCiAgZmkKZWxzZQogIGVjaG8gRmFpbGVkIHRvIHJlZnJlc2ggY2VydGlmaWNhdGUgZm9yIFwkQ09NUE9ORU5UICYmIGV4aXQgMQpmaQpFT0YKCmNobW9kIHUreCAvdXNyL2xvY2FsL2Jpbi9kb3dubG9hZC1jcmVkZW50aWFscy5zaAoKc3lzdGVtY3RsIGVuYWJsZSBkb3dubG9hZC1tZHNkLWNyZWRlbnRpYWxzLnRpbWVyCnN5c3RlbWN0bCBlbmFibGUgZG93bmxvYWQtbWRtLWNyZWRlbnRpYWxzLnRpbWVyCgovdXNyL2xvY2FsL2Jpbi9kb3dubG9hZC1jcmVkZW50aWFscy5zaCBtZHNkCi91c3IvbG9jYWwvYmluL2Rvd25sb2FkLWNyZWRlbnRpYWxzLnNoIG1kbQpNRFNEQ0VSVElGSUNBVEVTQU49JChvcGVuc3NsIHg1MDkgLWluIC92YXIvbGliL3dhYWdlbnQvTWljcm9zb2Z0LkF6dXJlLktleVZhdWx0LlN0b3JlL21kc2QucGVtIC1ub291dCAtc3ViamVjdCB8IHNlZCAtZSAncy8uKkNOID0gLy8nKQoKY2F0ID4vZXRjL3N5c3RlbWQvc3lzdGVtL3dhdGNoLW1kbS1jcmVkZW50aWFscy5zZXJ2aWNlIDw8RU9GCltVbml0XQpEZXNjcmlwdGlvbj1XYXRjaCBmb3IgY2hhbmdlcyBpbiBtZG0ucGVtIGFuZCByZXN0YXJ0cyB0aGUgbWRtIHNlcnZpY2UKCltTZXJ2aWNlXQpUeXBlPW9uZXNob3QKRXhlY1N0YXJ0PS91c3IvYmluL3N5c3RlbWN0bCByZXN0YXJ0IG1kbS5zZXJ2aWNlCgpbSW5zdGFsbF0KV2FudGVkQnk9bXVsdGktdXNlci50YXJnZXQKRU9GCgpjYXQgPi9ldGMvc3lzdGVtZC9zeXN0ZW0vd2F0Y2gtbWRtLWNyZWRlbnRpYWxzLnBhdGggPDxFT0YKW1BhdGhdClBhdGhNb2RpZmllZD0vZXRjL21kbS5wZW0KCltJbnN0YWxsXQpXYW50ZWRCeT1tdWx0aS11c2VyLnRhcmdldApFT0YKCnN5c3RlbWN0bCBlbmFibGUgd2F0Y2gtbWRtLWNyZWRlbnRpYWxzLnBhdGgKc3lzdGVtY3RsIHN0YXJ0IHdhdGNoLW1kbS1jcmVkZW50aWFscy5wYXRoCgpta2RpciAvZXRjL3N5c3RlbWQvc3lzdGVtL21kc2Quc2VydmljZS5kCmNhdCA+L2V0Yy9zeXN0ZW1kL3N5c3RlbS9tZHNkLnNlcnZpY2UuZC9vdmVycmlkZS5jb25mIDw8J0VPRicKW1VuaXRdCkFmdGVyPW5ldHdvcmstb25saW5lLnRhcmdldApFT0YKCmNhdCA+L2V0Yy9kZWZhdWx0L21kc2QgPDxFT0YKTURTRF9ST0xFX1BSRUZJWD0vdmFyL3J1bi9tZHNkL2RlZmF1bHQKTURTRF9PUFRJT05TPSItQSAtZCAtciBcJE1EU0RfUk9MRV9QUkVGSVgiCgpleHBvcnQgTU9OSVRPUklOR19HQ1NfRU5WSVJPTk1FTlQ9JyRNRFNERU5WSVJPTk1FTlQnCmV4cG9ydCBNT05JVE9SSU5HX0dDU19BQ0NPVU5UPSckUlBNRFNEQUNDT1VOVCcKZXhwb3J0IE1PTklUT1JJTkdfR0NTX1JFR0lPTj0nJExPQ0FUSU9OJwpleHBvcnQgTU9OSVRPUklOR19HQ1NfQVVUSF9JRF9UWVBFPUF1dGhLZXlWYXVsdApleHBvcnQgTU9OSVRPUklOR19HQ1NfQVVUSF9JRD0nJE1EU0RDRVJUSUZJQ0FURVNBTicKZXhwb3J0IE1PTklUT1JJTkdfR0NTX05BTUVTUEFDRT0nJFJQTURTRE5BTUVTUEFDRScKZXhwb3J0IE1PTklUT1JJTkdfQ09ORklHX1ZFUlNJT049JyRHQVRFV0FZTURTRENPTkZJR1ZFUlNJT04nCmV4cG9ydCBNT05JVE9SSU5HX1VTRV9HRU5FVkFfQ09ORklHX1NFUlZJQ0U9dHJ1ZQoKZXhwb3J0IE1PTklUT1JJTkdfVEVOQU5UPSckTE9DQVRJT04nCmV4cG9ydCBNT05JVE9SSU5HX1JPTEU9Z2F0ZXdheQpleHBvcnQgTU9OSVRPUklOR19ST0xFX0lOU1RBTkNFPSckKGhvc3RuYW1lKScKCmV4cG9ydCBNRFNEX01TR1BBQ0tfU09SVF9DT0xVTU5TPTEKRU9GCgojIHNldHRpbmcgTU9OSVRPUklOR19HQ1NfQVVUSF9JRF9UWVBFPUF1dGhLZXlWYXVsdCBzZWVtcyB0byBoYXZlIGNhdXNlZCBtZHNkIG5vdAojIHRvIGhvbm91ciBTU0xfQ0VSVF9GSUxFIGFueSBtb3JlLCBoZWF2ZW4gb25seSBrbm93cyB3aHkuCm1rZGlyIC1wIC91c3IvbGliL3NzbC9jZXJ0cwpjc3BsaXQgLWYgL3Vzci9saWIvc3NsL2NlcnRzL2NlcnQtIC1iICUwM2QucGVtIC9ldGMvcGtpL3Rscy9jZXJ0cy9jYS1idW5kbGUuY3J0IC9eJC8xIHsqfSA+L2Rldi9udWxsCmNfcmVoYXNoIC91c3IvbGliL3NzbC9jZXJ0cwoKIyB3ZSBsZWF2ZSBjbGllbnRJZCBibGFuayBhcyBsb25nIGFzIG9ubHkgMSBtYW5hZ2VkIGlkZW50aXR5IGFzc2lnbmVkIHRvIHZtc3MKIyBpZiB3ZSBoYXZlIG1vcmUgdGhhbiAxLCB3ZSB3aWxsIG5lZWQgdG8gcG9wdWxhdGUgd2l0aCBjbGllbnRJZCB1c2VkIGZvciBvZmYtbm9kZSBzY2FubmluZwpjYXQgPi9ldGMvZGVmYXVsdC92c2Etbm9kZXNjYW4tYWdlbnQuY29uZmlnIDw8RU9GCnsKICAgICJOaWNlIjogMTksCiAgICAiVGltZW91dCI6IDEwODAwLAogICAgIkNsaWVudElkIjogIiIsCiAgICAiVGVuYW50SWQiOiAiJEFaVVJFU0VDUEFDS1ZTQVRFTkFOVElEIiwKICAgICJRdWFseXNTdG9yZUJhc2VVcmwiOiAiJEFaVVJFU0VDUEFDS1FVQUxZU1VSTCIsCiAgICAiUHJvY2Vzc1RpbWVvdXQiOiAzMDAsCiAgICAiQ29tbWFuZERlbGF5IjogMAogIH0KRU9GCgplY2hvICJlbmFibGluZyBhcm8gc2VydmljZXMiCmZvciBzZXJ2aWNlIGluIGFyby1nYXRld2F5IGF1b21zIGF6c2VjZCBhenNlY21vbmQgbWRzZCBtZG0gY2hyb255ZCBmbHVlbnRiaXQ7IGRvCiAgc3lzdGVtY3RsIGVuYWJsZSAkc2VydmljZS5zZXJ2aWNlCmRvbmUKCmZvciBzY2FuIGluIGJhc2VsaW5lIGNsYW1hdiBzb2Z0d2FyZTsgZG8KICAvdXNyL2xvY2FsL2Jpbi9henNlY2QgY29uZmlnIC1zICRzY2FuIC1kIFAxRApkb25lCgplY2hvICJyZWJvb3RpbmciCnJlc3RvcmVjb24gLVJGIC92YXIvbG9nLyoKKHNsZWVwIDMwOyByZWJvb3QpICYK')))]" } } } diff --git a/pkg/deploy/assets/rp-production.json b/pkg/deploy/assets/rp-production.json index 7b80cdb2236..eec290c2170 100644 --- a/pkg/deploy/assets/rp-production.json +++ b/pkg/deploy/assets/rp-production.json @@ -516,7 +516,7 @@ "autoUpgradeMinorVersion": true, "settings": {}, "protectedSettings": { - "script": "[base64(concat(base64ToString('c2V0IC1leAoK'),'ACRRESOURCEID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('acrResourceId')),''')\n','ADMINAPICLIENTCERTCOMMONNAME=$(base64 -d \u003c\u003c\u003c''',base64(parameters('adminApiClientCertCommonName')),''')\n','ARMAPICLIENTCERTCOMMONNAME=$(base64 -d \u003c\u003c\u003c''',base64(parameters('armApiClientCertCommonName')),''')\n','ARMCLIENTID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('armClientId')),''')\n','AZURECLOUDNAME=$(base64 -d \u003c\u003c\u003c''',base64(parameters('azureCloudName')),''')\n','AZURESECPACKQUALYSURL=$(base64 -d \u003c\u003c\u003c''',base64(parameters('azureSecPackQualysUrl')),''')\n','AZURESECPACKVSATENANTID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('azureSecPackVSATenantId')),''')\n','BILLINGE2ESTORAGEACCOUNTID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('billingE2EStorageAccountId')),''')\n','CLUSTERMDMACCOUNT=$(base64 -d \u003c\u003c\u003c''',base64(parameters('clusterMdmAccount')),''')\n','CLUSTERMDSDACCOUNT=$(base64 -d \u003c\u003c\u003c''',base64(parameters('clusterMdsdAccount')),''')\n','CLUSTERMDSDCONFIGVERSION=$(base64 -d \u003c\u003c\u003c''',base64(parameters('clusterMdsdConfigVersion')),''')\n','CLUSTERMDSDNAMESPACE=$(base64 -d \u003c\u003c\u003c''',base64(parameters('clusterMdsdNamespace')),''')\n','CLUSTERPARENTDOMAINNAME=$(base64 -d \u003c\u003c\u003c''',base64(parameters('clusterParentDomainName')),''')\n','DATABASEACCOUNTNAME=$(base64 -d \u003c\u003c\u003c''',base64(parameters('databaseAccountName')),''')\n','DBTOKENCLIENTID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('dbtokenClientId')),''')\n','FLUENTBITIMAGE=$(base64 -d \u003c\u003c\u003c''',base64(parameters('fluentbitImage')),''')\n','FPCLIENTID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('fpClientId')),''')\n','FPSERVICEPRINCIPALID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('fpServicePrincipalId')),''')\n','GATEWAYDOMAINS=$(base64 -d \u003c\u003c\u003c''',base64(parameters('gatewayDomains')),''')\n','GATEWAYRESOURCEGROUPNAME=$(base64 -d \u003c\u003c\u003c''',base64(parameters('gatewayResourceGroupName')),''')\n','GATEWAYSERVICEPRINCIPALID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('gatewayServicePrincipalId')),''')\n','KEYVAULTDNSSUFFIX=$(base64 -d \u003c\u003c\u003c''',base64(parameters('keyvaultDNSSuffix')),''')\n','KEYVAULTPREFIX=$(base64 -d \u003c\u003c\u003c''',base64(parameters('keyvaultPrefix')),''')\n','MDMFRONTENDURL=$(base64 -d \u003c\u003c\u003c''',base64(parameters('mdmFrontendUrl')),''')\n','MDSDENVIRONMENT=$(base64 -d \u003c\u003c\u003c''',base64(parameters('mdsdEnvironment')),''')\n','PORTALACCESSGROUPIDS=$(base64 -d \u003c\u003c\u003c''',base64(parameters('portalAccessGroupIds')),''')\n','PORTALCLIENTID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('portalClientId')),''')\n','PORTALELEVATEDGROUPIDS=$(base64 -d \u003c\u003c\u003c''',base64(parameters('portalElevatedGroupIds')),''')\n','RPFEATURES=$(base64 -d \u003c\u003c\u003c''',base64(parameters('rpFeatures')),''')\n','RPIMAGE=$(base64 -d \u003c\u003c\u003c''',base64(parameters('rpImage')),''')\n','RPMDMACCOUNT=$(base64 -d \u003c\u003c\u003c''',base64(parameters('rpMdmAccount')),''')\n','RPMDSDACCOUNT=$(base64 -d \u003c\u003c\u003c''',base64(parameters('rpMdsdAccount')),''')\n','RPMDSDCONFIGVERSION=$(base64 -d \u003c\u003c\u003c''',base64(parameters('rpMdsdConfigVersion')),''')\n','RPMDSDNAMESPACE=$(base64 -d \u003c\u003c\u003c''',base64(parameters('rpMdsdNamespace')),''')\n','RPPARENTDOMAINNAME=$(base64 -d \u003c\u003c\u003c''',base64(parameters('rpParentDomainName')),''')\n','CLUSTERSINSTALLVIAHIVE=$(base64 -d \u003c\u003c\u003c''',base64(parameters('clustersInstallViaHive')),''')\n','CLUSTERSADOPTBYHIVE=$(base64 -d \u003c\u003c\u003c''',base64(parameters('clustersAdoptByHive')),''')\n','CLUSTERDEFAULTINSTALLERPULLSPEC=$(base64 -d \u003c\u003c\u003c''',base64(parameters('clusterDefaultInstallerPullspec')),''')\n','USECHECKACCESS=$(base64 -d \u003c\u003c\u003c''',base64(parameters('useCheckAccess')),''')\n','ADMINAPICABUNDLE=''',parameters('adminApiCaBundle'),'''\n','ARMAPICABUNDLE=''',parameters('armApiCaBundle'),'''\n','MDMIMAGE=''/genevamdm:2.2024.328.1744-c5fb79-20240328t1935''\n','LOCATION=$(base64 -d \u003c\u003c\u003c''',base64(resourceGroup().location),''')\n','SUBSCRIPTIONID=$(base64 -d \u003c\u003c\u003c''',base64(subscription().subscriptionId),''')\n','RESOURCEGROUPNAME=$(base64 -d \u003c\u003c\u003c''',base64(resourceGroup().name),''')\n','\n',base64ToString('IyEvYmluL2Jhc2gKCmVjaG8gInNldHRpbmcgc3NoIHBhc3N3b3JkIGF1dGhlbnRpY2F0aW9uIgojIFdlIG5lZWQgdG8gbWFudWFsbHkgc2V0IFBhc3N3b3JkQXV0aGVudGljYXRpb24gdG8gdHJ1ZSBpbiBvcmRlciBmb3IgdGhlIFZNU1MgQWNjZXNzIEpJVCB0byB3b3JrCnNlZCAtaSAncy9QYXNzd29yZEF1dGhlbnRpY2F0aW9uIG5vL1Bhc3N3b3JkQXV0aGVudGljYXRpb24geWVzL2cnIC9ldGMvc3NoL3NzaGRfY29uZmlnCnN5c3RlbWN0bCByZWxvYWQgc3NoZC5zZXJ2aWNlCgojQWRkaW5nIHJldHJ5IGxvZ2ljIHRvIHl1bSBjb21tYW5kcyBpbiBvcmRlciB0byBhdm9pZCBzdGFsbGluZyBvdXQgb24gcmVzb3VyY2UgbG9ja3MKZWNobyAicnVubmluZyBSSFVJIGZpeCIKZm9yIGF0dGVtcHQgaW4gezEuLjV9OyBkbwogIHl1bSB1cGRhdGUgLXkgLS1kaXNhYmxlcmVwbz0nKicgLS1lbmFibGVyZXBvPSdyaHVpLW1pY3Jvc29mdC1henVyZSonICYmIGJyZWFrCiAgaWYgW1sgJHthdHRlbXB0fSAtbHQgNSBdXTsgdGhlbiBzbGVlcCAxMDsgZWxzZSBleGl0IDE7IGZpCmRvbmUKCmVjaG8gInJ1bm5pbmcgeXVtIHVwZGF0ZSIKZm9yIGF0dGVtcHQgaW4gezEuLjV9OyBkbwogIHl1bSAteSAteCBXQUxpbnV4QWdlbnQgLXggV0FMaW51eEFnZW50LXVkZXYgdXBkYXRlIC0tYWxsb3dlcmFzaW5nICYmIGJyZWFrCiAgaWYgW1sgJHthdHRlbXB0fSAtbHQgNSBdXTsgdGhlbiBzbGVlcCAxMDsgZWxzZSBleGl0IDE7IGZpCmRvbmUKCmVjaG8gImV4dGVuZGluZyBwYXJ0aXRpb24gdGFibGUiCiMgTGludXggYmxvY2sgZGV2aWNlcyBhcmUgaW5jb25zaXN0ZW50bHkgbmFtZWQKIyBpdCdzIGRpZmZpY3VsdCB0byB0aWUgdGhlIGx2bSBwdiB0byB0aGUgcGh5c2ljYWwgZGlzayB1c2luZyAvZGV2L2Rpc2sgZmlsZXMsIHdoaWNoIGlzIHdoeSBsdnMgaXMgdXNlZCBoZXJlCnBoeXNpY2FsRGlzaz0iJChsdnMgLW8gZGV2aWNlcyAtYSB8IGhlYWQgLW4yIHwgdGFpbCAtbjEgfCBjdXQgLWQgJyAnIC1mIDMgfCBjdXQgLWQgXCggLWYgMSB8IHRyIC1kICdbOmRpZ2l0Ol0nKSIKZ3Jvd3BhcnQgIiRwaHlzaWNhbERpc2siIDIKCmVjaG8gImV4dGVuZGluZyBmaWxlc3lzdGVtcyIKbHZleHRlbmQgLWwgKzIwJUZSRUUgL2Rldi9yb290dmcvcm9vdGx2Cnhmc19ncm93ZnMgLwoKbHZleHRlbmQgLWwgKzEwMCVGUkVFIC9kZXYvcm9vdHZnL3Zhcmx2Cnhmc19ncm93ZnMgL3ZhcgoKZWNobyAiaW1wb3J0aW5nIHJwbSByZXBvc2l0b3JpZXMiCnJwbSAtLWltcG9ydCBodHRwczovL2RsLmZlZG9yYXByb2plY3Qub3JnL3B1Yi9lcGVsL1JQTS1HUEctS0VZLUVQRUwtOApycG0gLS1pbXBvcnQgaHR0cHM6Ly9wYWNrYWdlcy5taWNyb3NvZnQuY29tL2tleXMvbWljcm9zb2Z0LmFzYwoKZm9yIGF0dGVtcHQgaW4gezEuLjV9OyBkbwogIHl1bSAteSBpbnN0YWxsIGh0dHBzOi8vZGwuZmVkb3JhcHJvamVjdC5vcmcvcHViL2VwZWwvZXBlbC1yZWxlYXNlLWxhdGVzdC04Lm5vYXJjaC5ycG0gJiYgYnJlYWsKICBpZiBbWyAke2F0dGVtcHR9IC1sdCA1IF1dOyB0aGVuIHNsZWVwIDEwOyBlbHNlIGV4aXQgMTsgZmkKZG9uZQoKZWNobyAiY29uZmlndXJpbmcgbG9ncm90YXRlIgpjYXQgPi9ldGMvbG9ncm90YXRlLmNvbmYgPDwnRU9GJwojIHNlZSAibWFuIGxvZ3JvdGF0ZSIgZm9yIGRldGFpbHMKIyByb3RhdGUgbG9nIGZpbGVzIHdlZWtseQp3ZWVrbHkKCiMga2VlcCAyIHdlZWtzIHdvcnRoIG9mIGJhY2tsb2dzCnJvdGF0ZSAyCgojIGNyZWF0ZSBuZXcgKGVtcHR5KSBsb2cgZmlsZXMgYWZ0ZXIgcm90YXRpbmcgb2xkIG9uZXMKY3JlYXRlCgojIHVzZSBkYXRlIGFzIGEgc3VmZml4IG9mIHRoZSByb3RhdGVkIGZpbGUKZGF0ZWV4dAoKIyB1bmNvbW1lbnQgdGhpcyBpZiB5b3Ugd2FudCB5b3VyIGxvZyBmaWxlcyBjb21wcmVzc2VkCmNvbXByZXNzCgojIFJQTSBwYWNrYWdlcyBkcm9wIGxvZyByb3RhdGlvbiBpbmZvcm1hdGlvbiBpbnRvIHRoaXMgZGlyZWN0b3J5CmluY2x1ZGUgL2V0Yy9sb2dyb3RhdGUuZAoKIyBubyBwYWNrYWdlcyBvd24gd3RtcCBhbmQgYnRtcCAtLSB3ZSdsbCByb3RhdGUgdGhlbSBoZXJlCi92YXIvbG9nL3d0bXAgewogICAgbW9udGhseQogICAgY3JlYXRlIDA2NjQgcm9vdCB1dG1wCiAgICAgICAgbWluc2l6ZSAxTQogICAgcm90YXRlIDEKfQoKL3Zhci9sb2cvYnRtcCB7CiAgICBtaXNzaW5nb2sKICAgIG1vbnRobHkKICAgIGNyZWF0ZSAwNjAwIHJvb3QgdXRtcAogICAgcm90YXRlIDEKfQpFT0YKCmVjaG8gImNvbmZpZ3VyaW5nIHl1bSByZXBvc2l0b3J5IGFuZCBydW5uaW5nIHl1bSB1cGRhdGUiCmNhdCA+L2V0Yy95dW0ucmVwb3MuZC9henVyZS5yZXBvIDw8J0VPRicKW2F6dXJlLWNsaV0KbmFtZT1henVyZS1jbGkKYmFzZXVybD1odHRwczovL3BhY2thZ2VzLm1pY3Jvc29mdC5jb20veXVtcmVwb3MvYXp1cmUtY2xpCmVuYWJsZWQ9eWVzCmdwZ2NoZWNrPXllcwoKW2F6dXJlY29yZV0KbmFtZT1henVyZWNvcmUKYmFzZXVybD1odHRwczovL3BhY2thZ2VzLm1pY3Jvc29mdC5jb20veXVtcmVwb3MvYXp1cmVjb3JlCmVuYWJsZWQ9eWVzCmdwZ2NoZWNrPW5vCkVPRgoKc2VtYW5hZ2UgZmNvbnRleHQgLWEgLXQgdmFyX2xvZ190ICIvdmFyL2xvZy9qb3VybmFsKC8uKik/Igpta2RpciAtcCAvdmFyL2xvZy9qb3VybmFsCgpmb3IgYXR0ZW1wdCBpbiB7MS4uNX07IGRvCnl1bSAteSBpbnN0YWxsIGNsYW1hdiBhenNlYy1jbGFtYXYgYXpzZWMtbW9uaXRvciBhenVyZS1jbGkgYXp1cmUtbWRzZCBhenVyZS1zZWN1cml0eSBwb2RtYW4gcG9kbWFuLWRvY2tlciBvcGVuc3NsLXBlcmwgcHl0aG9uMyAmJiBicmVhawogICMgaGFjayAtIHdlIGFyZSBpbnN0YWxsaW5nIHB5dGhvbjMgb24gaG9zdHMgZHVlIHRvIGFuIGlzc3VlIHdpdGggQXp1cmUgTGludXggRXh0ZW5zaW9ucyBodHRwczovL2dpdGh1Yi5jb20vQXp1cmUvYXp1cmUtbGludXgtZXh0ZW5zaW9ucy9wdWxsLzE1MDUKICBpZiBbWyAke2F0dGVtcHR9IC1sdCA1IF1dOyB0aGVuIHNsZWVwIDEwOyBlbHNlIGV4aXQgMTsgZmkKZG9uZQoKIyBodHRwczovL2FjY2Vzcy5yZWRoYXQuY29tL3NlY3VyaXR5L2N2ZS9jdmUtMjAyMC0xMzQwMQplY2hvICJhcHBseWluZyBmaXJld2FsbCBydWxlcyIKY2F0ID4vZXRjL3N5c2N0bC5kLzAyLWRpc2FibGUtYWNjZXB0LXJhLmNvbmYgPDwnRU9GJwpuZXQuaXB2Ni5jb25mLmFsbC5hY2NlcHRfcmE9MApFT0YKCmNhdCA+L2V0Yy9zeXNjdGwuZC8wMS1kaXNhYmxlLWNvcmUuY29uZiA8PCdFT0YnCmtlcm5lbC5jb3JlX3BhdHRlcm4gPSB8L2Jpbi90cnVlCkVPRgpzeXNjdGwgLS1zeXN0ZW0KCmZpcmV3YWxsLWNtZCAtLWFkZC1wb3J0PTQ0My90Y3AgLS1wZXJtYW5lbnQKZmlyZXdhbGwtY21kIC0tYWRkLXBvcnQ9NDQ0L3RjcCAtLXBlcm1hbmVudApmaXJld2FsbC1jbWQgLS1hZGQtcG9ydD00NDUvdGNwIC0tcGVybWFuZW50CmZpcmV3YWxsLWNtZCAtLWFkZC1wb3J0PTIyMjIvdGNwIC0tcGVybWFuZW50CgpleHBvcnQgQVpVUkVfQ0xPVURfTkFNRT0kQVpVUkVDTE9VRE5BTUUKCmVjaG8gImxvZ2dpbmcgaW50byBwcm9kIGFjciIKYXogbG9naW4gLWkgLS1hbGxvdy1uby1zdWJzY3JpcHRpb25zCgojIFN1cHByZXNzIGVtdWxhdGlvbiBvdXRwdXQgZm9yIHBvZG1hbiBpbnN0ZWFkIG9mIGRvY2tlciBmb3IgYXogYWNyIGNvbXBhdGFiaWxpdHkKbWtkaXIgLXAgL2V0Yy9jb250YWluZXJzLwp0b3VjaCAvZXRjL2NvbnRhaW5lcnMvbm9kb2NrZXIKCm1rZGlyIC1wIC9yb290Ly5kb2NrZXIKUkVHSVNUUllfQVVUSF9GSUxFPS9yb290Ly5kb2NrZXIvY29uZmlnLmpzb24gYXogYWNyIGxvZ2luIC0tbmFtZSAiJChzZWQgLWUgJ3N8LiovfHwnIDw8PCIkQUNSUkVTT1VSQ0VJRCIpIgoKTURNSU1BR0U9IiR7UlBJTUFHRSUlLyp9LyR7TURNSU1BR0UjIyovfSIKZG9ja2VyIHB1bGwgIiRNRE1JTUFHRSIKZG9ja2VyIHB1bGwgIiRSUElNQUdFIgpkb2NrZXIgcHVsbCAiJEZMVUVOVEJJVElNQUdFIgoKYXogbG9nb3V0CgplY2hvICJjb25maWd1cmluZyBmbHVlbnRiaXQgc2VydmljZSIKbWtkaXIgLXAgL2V0Yy9mbHVlbnRiaXQvCm1rZGlyIC1wIC92YXIvbGliL2ZsdWVudAoKY2F0ID4vZXRjL2ZsdWVudGJpdC9mbHVlbnRiaXQuY29uZiA8PCdFT0YnCltJTlBVVF0KCU5hbWUgc3lzdGVtZAoJVGFnIGpvdXJuYWxkCglTeXN0ZW1kX0ZpbHRlciBfQ09NTT1hcm8KCURCIC92YXIvbGliL2ZsdWVudC9qb3VybmFsZGIKCltGSUxURVJdCglOYW1lIG1vZGlmeQoJTWF0Y2ggam91cm5hbGQKCVJlbW92ZV93aWxkY2FyZCBfCglSZW1vdmUgVElNRVNUQU1QCgpbRklMVEVSXQoJTmFtZSByZXdyaXRlX3RhZwoJTWF0Y2ggam91cm5hbGQKCVJ1bGUgJExPR0tJTkQgYXN5bmNxb3MgYXN5bmNxb3MgdHJ1ZQoKW0ZJTFRFUl0KCU5hbWUgbW9kaWZ5CglNYXRjaCBhc3luY3FvcwoJUmVtb3ZlIENMSUVOVF9QUklOQ0lQQUxfTkFNRQoJUmVtb3ZlIEZJTEUKCVJlbW92ZSBDT01QT05FTlQKCltGSUxURVJdCglOYW1lIHJld3JpdGVfdGFnCglNYXRjaCBqb3VybmFsZAoJUnVsZSAkTE9HS0lORCBpZnhhdWRpdCBpZnhhdWRpdCBmYWxzZQoKW09VVFBVVF0KCU5hbWUgZm9yd2FyZAoJTWF0Y2ggKgoJUG9ydCAyOTIzMApFT0YKCmVjaG8gIkZMVUVOVEJJVElNQUdFPSRGTFVFTlRCSVRJTUFHRSIgPi9ldGMvc3lzY29uZmlnL2ZsdWVudGJpdAoKY2F0ID4vZXRjL3N5c3RlbWQvc3lzdGVtL2ZsdWVudGJpdC5zZXJ2aWNlIDw8J0VPRicKW1VuaXRdCkFmdGVyPW5ldHdvcmstb25saW5lLnRhcmdldApXYW50cz1uZXR3b3JrLW9ubGluZS50YXJnZXQKU3RhcnRMaW1pdEludGVydmFsU2VjPTAKCltTZXJ2aWNlXQpSZXN0YXJ0U2VjPTFzCkVudmlyb25tZW50RmlsZT0vZXRjL3N5c2NvbmZpZy9mbHVlbnRiaXQKRXhlY1N0YXJ0UHJlPS0vdXNyL2Jpbi9kb2NrZXIgcm0gLWYgJU4KRXhlY1N0YXJ0PS91c3IvYmluL2RvY2tlciBydW4gXAogIC0tc2VjdXJpdHktb3B0IGxhYmVsPWRpc2FibGUgXAogIC0tZW50cnlwb2ludCAvb3B0L3RkLWFnZW50LWJpdC9iaW4vdGQtYWdlbnQtYml0IFwKICAtLW5ldD1ob3N0IFwKICAtLWhvc3RuYW1lICVIIFwKICAtLW5hbWUgJU4gXAogIC0tcm0gXAogIC0tY2FwLWRyb3AgbmV0X3JhdyBcCiAgLXYgL2V0Yy9mbHVlbnRiaXQvZmx1ZW50Yml0LmNvbmY6L2V0Yy9mbHVlbnRiaXQvZmx1ZW50Yml0LmNvbmYgXAogIC12IC92YXIvbGliL2ZsdWVudDovdmFyL2xpYi9mbHVlbnQ6eiBcCiAgLXYgL3Zhci9sb2cvam91cm5hbDovdmFyL2xvZy9qb3VybmFsOnJvIFwKICAtdiAvZXRjL21hY2hpbmUtaWQ6L2V0Yy9tYWNoaW5lLWlkOnJvIFwKICAkRkxVRU5UQklUSU1BR0UgXAogIC1jIC9ldGMvZmx1ZW50Yml0L2ZsdWVudGJpdC5jb25mCgpFeGVjU3RvcD0vdXNyL2Jpbi9kb2NrZXIgc3RvcCAlTgpSZXN0YXJ0PWFsd2F5cwpSZXN0YXJ0U2VjPTUKU3RhcnRMaW1pdEludGVydmFsPTAKCltJbnN0YWxsXQpXYW50ZWRCeT1tdWx0aS11c2VyLnRhcmdldApFT0YKCm1rZGlyIC9ldGMvYXJvLXJwCmJhc2U2NCAtZCA8PDwiJEFETUlOQVBJQ0FCVU5ETEUiID4vZXRjL2Fyby1ycC9hZG1pbi1jYS1idW5kbGUucGVtCmlmIFtbIC1uICIkQVJNQVBJQ0FCVU5ETEUiIF1dOyB0aGVuCiAgYmFzZTY0IC1kIDw8PCIkQVJNQVBJQ0FCVU5ETEUiID4vZXRjL2Fyby1ycC9hcm0tY2EtYnVuZGxlLnBlbQpmaQpjaG93biAtUiAxMDAwOjEwMDAgL2V0Yy9hcm8tcnAKCmVjaG8gImNvbmZpZ3VyaW5nIG1kbSBzZXJ2aWNlIgpjYXQgPi9ldGMvc3lzY29uZmlnL21kbSA8PEVPRgpNRE1GUk9OVEVORFVSTD0nJE1ETUZST05URU5EVVJMJwpNRE1JTUFHRT0nJE1ETUlNQUdFJwpNRE1TT1VSQ0VFTlZJUk9OTUVOVD0nJExPQ0FUSU9OJwpNRE1TT1VSQ0VST0xFPXJwCk1ETVNPVVJDRVJPTEVJTlNUQU5DRT0nJChob3N0bmFtZSknCkVPRgoKbWtkaXIgL3Zhci9ldHcKY2F0ID4vZXRjL3N5c3RlbWQvc3lzdGVtL21kbS5zZXJ2aWNlIDw8J0VPRicKW1VuaXRdCkFmdGVyPW5ldHdvcmstb25saW5lLnRhcmdldApXYW50cz1uZXR3b3JrLW9ubGluZS50YXJnZXQKCltTZXJ2aWNlXQpFbnZpcm9ubWVudEZpbGU9L2V0Yy9zeXNjb25maWcvbWRtCkV4ZWNTdGFydFByZT0tL3Vzci9iaW4vZG9ja2VyIHJtIC1mICVOCkV4ZWNTdGFydD0vdXNyL2Jpbi9kb2NrZXIgcnVuIFwKICAtLWVudHJ5cG9pbnQgL3Vzci9zYmluL01ldHJpY3NFeHRlbnNpb24gXAogIC0taG9zdG5hbWUgJUggXAogIC0tbmFtZSAlTiBcCiAgLS1ybSBcCiAgLS1jYXAtZHJvcCBuZXRfcmF3IFwKICAtbSAyZyBcCiAgLXYgL2V0Yy9tZG0ucGVtOi9ldGMvbWRtLnBlbSBcCiAgLXYgL3Zhci9ldHc6L3Zhci9ldHc6eiBcCiAgJE1ETUlNQUdFIFwKICAtQ2VydEZpbGUgL2V0Yy9tZG0ucGVtIFwKICAtRnJvbnRFbmRVcmwgJE1ETUZST05URU5EVVJMIFwKICAtTG9nZ2VyIENvbnNvbGUgXAogIC1Mb2dMZXZlbCBXYXJuaW5nIFwKICAtUHJpdmF0ZUtleUZpbGUgL2V0Yy9tZG0ucGVtIFwKICAtU291cmNlRW52aXJvbm1lbnQgJE1ETVNPVVJDRUVOVklST05NRU5UIFwKICAtU291cmNlUm9sZSAkTURNU09VUkNFUk9MRSBcCiAgLVNvdXJjZVJvbGVJbnN0YW5jZSAkTURNU09VUkNFUk9MRUlOU1RBTkNFCkV4ZWNTdG9wPS91c3IvYmluL2RvY2tlciBzdG9wICVOClJlc3RhcnQ9YWx3YXlzClJlc3RhcnRTZWM9MQpTdGFydExpbWl0SW50ZXJ2YWw9MAoKW0luc3RhbGxdCldhbnRlZEJ5PW11bHRpLXVzZXIudGFyZ2V0CkVPRgoKZWNobyAiY29uZmlndXJpbmcgYXJvLXJwIHNlcnZpY2UiCmNhdCA+L2V0Yy9zeXNjb25maWcvYXJvLXJwIDw8RU9GCkFDUl9SRVNPVVJDRV9JRD0nJEFDUlJFU09VUkNFSUQnCkFETUlOX0FQSV9DTElFTlRfQ0VSVF9DT01NT05fTkFNRT0nJEFETUlOQVBJQ0xJRU5UQ0VSVENPTU1PTk5BTUUnCkFSTV9BUElfQ0xJRU5UX0NFUlRfQ09NTU9OX05BTUU9JyRBUk1BUElDTElFTlRDRVJUQ09NTU9OTkFNRScKQVpVUkVfQVJNX0NMSUVOVF9JRD0nJEFSTUNMSUVOVElEJwpBWlVSRV9GUF9DTElFTlRfSUQ9JyRGUENMSUVOVElEJwpBWlVSRV9GUF9TRVJWSUNFX1BSSU5DSVBBTF9JRD0nJEZQU0VSVklDRVBSSU5DSVBBTElEJwpCSUxMSU5HX0UyRV9TVE9SQUdFX0FDQ09VTlRfSUQ9JyRCSUxMSU5HRTJFU1RPUkFHRUFDQ09VTlRJRCcKQ0xVU1RFUl9NRE1fQUNDT1VOVD0nJENMVVNURVJNRE1BQ0NPVU5UJwpDTFVTVEVSX01ETV9OQU1FU1BBQ0U9UlAKQ0xVU1RFUl9NRFNEX0FDQ09VTlQ9JyRDTFVTVEVSTURTREFDQ09VTlQnCkNMVVNURVJfTURTRF9DT05GSUdfVkVSU0lPTj0nJENMVVNURVJNRFNEQ09ORklHVkVSU0lPTicKQ0xVU1RFUl9NRFNEX05BTUVTUEFDRT0nJENMVVNURVJNRFNETkFNRVNQQUNFJwpEQVRBQkFTRV9BQ0NPVU5UX05BTUU9JyREQVRBQkFTRUFDQ09VTlROQU1FJwpET01BSU5fTkFNRT0nJExPQ0FUSU9OLiRDTFVTVEVSUEFSRU5URE9NQUlOTkFNRScKR0FURVdBWV9ET01BSU5TPSckR0FURVdBWURPTUFJTlMnCkdBVEVXQVlfUkVTT1VSQ0VHUk9VUD0nJEdBVEVXQVlSRVNPVVJDRUdST1VQTkFNRScKS0VZVkFVTFRfUFJFRklYPSckS0VZVkFVTFRQUkVGSVgnCk1ETV9BQ0NPVU5UPSckUlBNRE1BQ0NPVU5UJwpNRE1fTkFNRVNQQUNFPVJQCk1EU0RfRU5WSVJPTk1FTlQ9JyRNRFNERU5WSVJPTk1FTlQnClJQX0ZFQVRVUkVTPSckUlBGRUFUVVJFUycKUlBJTUFHRT0nJFJQSU1BR0UnCkFST19JTlNUQUxMX1ZJQV9ISVZFPSckQ0xVU1RFUlNJTlNUQUxMVklBSElWRScKQVJPX0hJVkVfREVGQVVMVF9JTlNUQUxMRVJfUFVMTFNQRUM9JyRDTFVTVEVSREVGQVVMVElOU1RBTExFUlBVTExTUEVDJwpBUk9fQURPUFRfQllfSElWRT0nJENMVVNURVJTQURPUFRCWUhJVkUnClVTRV9DSEVDS0FDQ0VTUz0nJFVTRUNIRUNLQUNDRVNTJwpFT0YKCmNhdCA+L2V0Yy9zeXN0ZW1kL3N5c3RlbS9hcm8tcnAuc2VydmljZSA8PCdFT0YnCltVbml0XQpBZnRlcj1uZXR3b3JrLW9ubGluZS50YXJnZXQKV2FudHM9bmV0d29yay1vbmxpbmUudGFyZ2V0CgpbU2VydmljZV0KRW52aXJvbm1lbnRGaWxlPS9ldGMvc3lzY29uZmlnL2Fyby1ycApFeGVjU3RhcnRQcmU9LS91c3IvYmluL2RvY2tlciBybSAtZiAlTgpFeGVjU3RhcnQ9L3Vzci9iaW4vZG9ja2VyIHJ1biBcCiAgLS1ob3N0bmFtZSAlSCBcCiAgLS1uYW1lICVOIFwKICAtLXJtIFwKICAtLWNhcC1kcm9wIG5ldF9yYXcgXAogIC1lIEFDUl9SRVNPVVJDRV9JRCBcCiAgLWUgQURNSU5fQVBJX0NMSUVOVF9DRVJUX0NPTU1PTl9OQU1FIFwKICAtZSBBUk1fQVBJX0NMSUVOVF9DRVJUX0NPTU1PTl9OQU1FIFwKICAtZSBBWlVSRV9BUk1fQ0xJRU5UX0lEIFwKICAtZSBBWlVSRV9GUF9DTElFTlRfSUQgXAogIC1lIEJJTExJTkdfRTJFX1NUT1JBR0VfQUNDT1VOVF9JRCBcCiAgLWUgQ0xVU1RFUl9NRE1fQUNDT1VOVCBcCiAgLWUgQ0xVU1RFUl9NRE1fTkFNRVNQQUNFIFwKICAtZSBDTFVTVEVSX01EU0RfQUNDT1VOVCBcCiAgLWUgQ0xVU1RFUl9NRFNEX0NPTkZJR19WRVJTSU9OIFwKICAtZSBDTFVTVEVSX01EU0RfTkFNRVNQQUNFIFwKICAtZSBEQVRBQkFTRV9BQ0NPVU5UX05BTUUgXAogIC1lIERPTUFJTl9OQU1FIFwKICAtZSBHQVRFV0FZX0RPTUFJTlMgXAogIC1lIEdBVEVXQVlfUkVTT1VSQ0VHUk9VUCBcCiAgLWUgS0VZVkFVTFRfUFJFRklYIFwKICAtZSBNRE1fQUNDT1VOVCBcCiAgLWUgTURNX05BTUVTUEFDRSBcCiAgLWUgTURTRF9FTlZJUk9OTUVOVCBcCiAgLWUgUlBfRkVBVFVSRVMgXAogIC1lIEFST19JTlNUQUxMX1ZJQV9ISVZFIFwKICAtZSBBUk9fSElWRV9ERUZBVUxUX0lOU1RBTExFUl9QVUxMU1BFQyBcCiAgLWUgQVJPX0FET1BUX0JZX0hJVkUgXAogIC1lIFVTRV9DSEVDS0FDQ0VTUyBcCiAgLW0gMmcgXAogIC1wIDQ0Mzo4NDQzIFwKICAtdiAvZXRjL2Fyby1ycDovZXRjL2Fyby1ycCBcCiAgLXYgL3J1bi9zeXN0ZW1kL2pvdXJuYWw6L3J1bi9zeXN0ZW1kL2pvdXJuYWwgXAogIC12IC92YXIvZXR3Oi92YXIvZXR3OnogXAogICRSUElNQUdFIFwKICBycApFeGVjU3RvcD0vdXNyL2Jpbi9kb2NrZXIgc3RvcCAtdCAzNjAwICVOClRpbWVvdXRTdG9wU2VjPTM2MDAKUmVzdGFydD1hbHdheXMKUmVzdGFydFNlYz0xClN0YXJ0TGltaXRJbnRlcnZhbD0wCgpbSW5zdGFsbF0KV2FudGVkQnk9bXVsdGktdXNlci50YXJnZXQKRU9GCgplY2hvICJjb25maWd1cmluZyBhcm8tZGJ0b2tlbiBzZXJ2aWNlIgpjYXQgPi9ldGMvc3lzY29uZmlnL2Fyby1kYnRva2VuIDw8RU9GCkRBVEFCQVNFX0FDQ09VTlRfTkFNRT0nJERBVEFCQVNFQUNDT1VOVE5BTUUnCkFaVVJFX0RCVE9LRU5fQ0xJRU5UX0lEPSckREJUT0tFTkNMSUVOVElEJwpBWlVSRV9HQVRFV0FZX1NFUlZJQ0VfUFJJTkNJUEFMX0lEPSckR0FURVdBWVNFUlZJQ0VQUklOQ0lQQUxJRCcKS0VZVkFVTFRfUFJFRklYPSckS0VZVkFVTFRQUkVGSVgnCk1ETV9BQ0NPVU5UPSckUlBNRE1BQ0NPVU5UJwpNRE1fTkFNRVNQQUNFPURCVG9rZW4KUlBJTUFHRT0nJFJQSU1BR0UnCkVPRgoKY2F0ID4vZXRjL3N5c3RlbWQvc3lzdGVtL2Fyby1kYnRva2VuLnNlcnZpY2UgPDwnRU9GJwpbVW5pdF0KQWZ0ZXI9bmV0d29yay1vbmxpbmUudGFyZ2V0CldhbnRzPW5ldHdvcmstb25saW5lLnRhcmdldAoKW1NlcnZpY2VdCkVudmlyb25tZW50RmlsZT0vZXRjL3N5c2NvbmZpZy9hcm8tZGJ0b2tlbgpFeGVjU3RhcnRQcmU9LS91c3IvYmluL2RvY2tlciBybSAtZiAlTgpFeGVjU3RhcnQ9L3Vzci9iaW4vZG9ja2VyIHJ1biBcCiAgLS1ob3N0bmFtZSAlSCBcCiAgLS1uYW1lICVOIFwKICAtLXJtIFwKICAtLWNhcC1kcm9wIG5ldF9yYXcgXAogIC1lIEFaVVJFX0dBVEVXQVlfU0VSVklDRV9QUklOQ0lQQUxfSUQgXAogIC1lIERBVEFCQVNFX0FDQ09VTlRfTkFNRSBcCiAgLWUgQVpVUkVfREJUT0tFTl9DTElFTlRfSUQgXAogIC1lIEtFWVZBVUxUX1BSRUZJWCBcCiAgLWUgTURNX0FDQ09VTlQgXAogIC1lIE1ETV9OQU1FU1BBQ0UgXAogIC1tIDJnIFwKICAtcCA0NDU6ODQ0NSBcCiAgLXYgL3J1bi9zeXN0ZW1kL2pvdXJuYWw6L3J1bi9zeXN0ZW1kL2pvdXJuYWwgXAogIC12IC92YXIvZXR3Oi92YXIvZXR3OnogXAogICRSUElNQUdFIFwKICBkYnRva2VuCkV4ZWNTdG9wPS91c3IvYmluL2RvY2tlciBzdG9wIC10IDM2MDAgJU4KVGltZW91dFN0b3BTZWM9MzYwMApSZXN0YXJ0PWFsd2F5cwpSZXN0YXJ0U2VjPTEKU3RhcnRMaW1pdEludGVydmFsPTAKCltJbnN0YWxsXQpXYW50ZWRCeT1tdWx0aS11c2VyLnRhcmdldApFT0YKCiMgRE9NQUlOX05BTUUsIENMVVNURVJfTURTRF9BQ0NPVU5ULCBDTFVTVEVSX01EU0RfQ09ORklHX1ZFUlNJT04sIEdBVEVXQVlfRE9NQUlOUywgR0FURVdBWV9SRVNPVVJDRUdST1VQLCBNRFNEX0VOVklST05NRU5UIENMVVNURVJfTURTRF9OQU1FU1BBQ0UKIyBhcmUgbm90IHVzZWQsIGJ1dCBjYW4ndCBlYXNpbHkgYmUgcmVmYWN0b3JlZCBvdXQuIFNob3VsZCBiZSByZXZpc2l0ZWQgaW4gdGhlIGZ1dHVyZS4KZWNobyAiY29uZmlndXJpbmcgYXJvLW1vbml0b3Igc2VydmljZSIKY2F0ID4vZXRjL3N5c2NvbmZpZy9hcm8tbW9uaXRvciA8PEVPRgpBWlVSRV9GUF9DTElFTlRfSUQ9JyRGUENMSUVOVElEJwpET01BSU5fTkFNRT0nJExPQ0FUSU9OLiRDTFVTVEVSUEFSRU5URE9NQUlOTkFNRScKQ0xVU1RFUl9NRFNEX0FDQ09VTlQ9JyRDTFVTVEVSTURTREFDQ09VTlQnCkNMVVNURVJfTURTRF9DT05GSUdfVkVSU0lPTj0nJENMVVNURVJNRFNEQ09ORklHVkVSU0lPTicKR0FURVdBWV9ET01BSU5TPSckR0FURVdBWURPTUFJTlMnCkdBVEVXQVlfUkVTT1VSQ0VHUk9VUD0nJEdBVEVXQVlSRVNPVVJDRUdST1VQTkFNRScKTURTRF9FTlZJUk9OTUVOVD0nJE1EU0RFTlZJUk9OTUVOVCcKQ0xVU1RFUl9NRFNEX05BTUVTUEFDRT0nJENMVVNURVJNRFNETkFNRVNQQUNFJwpDTFVTVEVSX01ETV9BQ0NPVU5UPSckQ0xVU1RFUk1ETUFDQ09VTlQnCkNMVVNURVJfTURNX05BTUVTUEFDRT1CQk0KREFUQUJBU0VfQUNDT1VOVF9OQU1FPSckREFUQUJBU0VBQ0NPVU5UTkFNRScKS0VZVkFVTFRfUFJFRklYPSckS0VZVkFVTFRQUkVGSVgnCk1ETV9BQ0NPVU5UPSckUlBNRE1BQ0NPVU5UJwpNRE1fTkFNRVNQQUNFPUJCTQpSUElNQUdFPSckUlBJTUFHRScKRU9GCgpjYXQgPi9ldGMvc3lzdGVtZC9zeXN0ZW0vYXJvLW1vbml0b3Iuc2VydmljZSA8PCdFT0YnCltVbml0XQpBZnRlcj1uZXR3b3JrLW9ubGluZS50YXJnZXQKV2FudHM9bmV0d29yay1vbmxpbmUudGFyZ2V0CgpbU2VydmljZV0KRW52aXJvbm1lbnRGaWxlPS9ldGMvc3lzY29uZmlnL2Fyby1tb25pdG9yCkV4ZWNTdGFydFByZT0tL3Vzci9iaW4vZG9ja2VyIHJtIC1mICVOCkV4ZWNTdGFydD0vdXNyL2Jpbi9kb2NrZXIgcnVuIFwKICAtLWhvc3RuYW1lICVIIFwKICAtLW5hbWUgJU4gXAogIC0tcm0gXAogIC0tY2FwLWRyb3AgbmV0X3JhdyBcCiAgLWUgQVpVUkVfRlBfQ0xJRU5UX0lEIFwKICAtZSBET01BSU5fTkFNRSBcCiAgLWUgQ0xVU1RFUl9NRFNEX0FDQ09VTlQgXAogIC1lIENMVVNURVJfTURTRF9DT05GSUdfVkVSU0lPTiBcCiAgLWUgR0FURVdBWV9ET01BSU5TIFwKICAtZSBHQVRFV0FZX1JFU09VUkNFR1JPVVAgXAogIC1lIE1EU0RfRU5WSVJPTk1FTlQgXAogIC1lIENMVVNURVJfTURTRF9OQU1FU1BBQ0UgXAogIC1lIENMVVNURVJfTURNX0FDQ09VTlQgXAogIC1lIENMVVNURVJfTURNX05BTUVTUEFDRSBcCiAgLWUgREFUQUJBU0VfQUNDT1VOVF9OQU1FIFwKICAtZSBLRVlWQVVMVF9QUkVGSVggXAogIC1lIE1ETV9BQ0NPVU5UIFwKICAtZSBNRE1fTkFNRVNQQUNFIFwKICAtbSAyLjVnIFwKICAtdiAvcnVuL3N5c3RlbWQvam91cm5hbDovcnVuL3N5c3RlbWQvam91cm5hbCBcCiAgLXYgL3Zhci9ldHc6L3Zhci9ldHc6eiBcCiAgJFJQSU1BR0UgXAogIG1vbml0b3IKUmVzdGFydD1hbHdheXMKUmVzdGFydFNlYz0xClN0YXJ0TGltaXRJbnRlcnZhbD0wCgpbSW5zdGFsbF0KV2FudGVkQnk9bXVsdGktdXNlci50YXJnZXQKRU9GCgplY2hvICJjb25maWd1cmluZyBhcm8tcG9ydGFsIHNlcnZpY2UiCmNhdCA+L2V0Yy9zeXNjb25maWcvYXJvLXBvcnRhbCA8PEVPRgpBWlVSRV9QT1JUQUxfQUNDRVNTX0dST1VQX0lEUz0nJFBPUlRBTEFDQ0VTU0dST1VQSURTJwpBWlVSRV9QT1JUQUxfQ0xJRU5UX0lEPSckUE9SVEFMQ0xJRU5USUQnCkFaVVJFX1BPUlRBTF9FTEVWQVRFRF9HUk9VUF9JRFM9JyRQT1JUQUxFTEVWQVRFREdST1VQSURTJwpEQVRBQkFTRV9BQ0NPVU5UX05BTUU9JyREQVRBQkFTRUFDQ09VTlROQU1FJwpLRVlWQVVMVF9QUkVGSVg9JyRLRVlWQVVMVFBSRUZJWCcKTURNX0FDQ09VTlQ9JyRSUE1ETUFDQ09VTlQnCk1ETV9OQU1FU1BBQ0U9UG9ydGFsClBPUlRBTF9IT1NUTkFNRT0nJExPQ0FUSU9OLmFkbWluLiRSUFBBUkVOVERPTUFJTk5BTUUnClJQSU1BR0U9JyRSUElNQUdFJwpFT0YKCmNhdCA+L2V0Yy9zeXN0ZW1kL3N5c3RlbS9hcm8tcG9ydGFsLnNlcnZpY2UgPDwnRU9GJwpbVW5pdF0KQWZ0ZXI9bmV0d29yay1vbmxpbmUudGFyZ2V0CldhbnRzPW5ldHdvcmstb25saW5lLnRhcmdldApTdGFydExpbWl0SW50ZXJ2YWw9MAoKW1NlcnZpY2VdCkVudmlyb25tZW50RmlsZT0vZXRjL3N5c2NvbmZpZy9hcm8tcG9ydGFsCkV4ZWNTdGFydFByZT0tL3Vzci9iaW4vZG9ja2VyIHJtIC1mICVOCkV4ZWNTdGFydD0vdXNyL2Jpbi9kb2NrZXIgcnVuIFwKICAtLWhvc3RuYW1lICVIIFwKICAtLW5hbWUgJU4gXAogIC0tcm0gXAogIC0tY2FwLWRyb3AgbmV0X3JhdyBcCiAgLWUgQVpVUkVfUE9SVEFMX0FDQ0VTU19HUk9VUF9JRFMgXAogIC1lIEFaVVJFX1BPUlRBTF9DTElFTlRfSUQgXAogIC1lIEFaVVJFX1BPUlRBTF9FTEVWQVRFRF9HUk9VUF9JRFMgXAogIC1lIERBVEFCQVNFX0FDQ09VTlRfTkFNRSBcCiAgLWUgS0VZVkFVTFRfUFJFRklYIFwKICAtZSBNRE1fQUNDT1VOVCBcCiAgLWUgTURNX05BTUVTUEFDRSBcCiAgLWUgUE9SVEFMX0hPU1ROQU1FIFwKICAtbSAyZyBcCiAgLXAgNDQ0Ojg0NDQgXAogIC1wIDIyMjI6MjIyMiBcCiAgLXYgL3J1bi9zeXN0ZW1kL2pvdXJuYWw6L3J1bi9zeXN0ZW1kL2pvdXJuYWwgXAogIC12IC92YXIvZXR3Oi92YXIvZXR3OnogXAogICRSUElNQUdFIFwKICBwb3J0YWwKUmVzdGFydD1hbHdheXMKUmVzdGFydFNlYz0xCgpbSW5zdGFsbF0KV2FudGVkQnk9bXVsdGktdXNlci50YXJnZXQKRU9GCgplY2hvICJjb25maWd1cmluZyBtZHNkIGFuZCBtZG0gc2VydmljZXMiCmNoY29uIC1SIHN5c3RlbV91Om9iamVjdF9yOnZhcl9sb2dfdDpzMCAvdmFyL29wdC9taWNyb3NvZnQvbGludXhtb25hZ2VudAoKbWtkaXIgLXAgL3Zhci9saWIvd2FhZ2VudC9NaWNyb3NvZnQuQXp1cmUuS2V5VmF1bHQuU3RvcmUKCmZvciB2YXIgaW4gIm1kc2QiICJtZG0iOyBkbwpjYXQgPi9ldGMvc3lzdGVtZC9zeXN0ZW0vZG93bmxvYWQtJHZhci1jcmVkZW50aWFscy5zZXJ2aWNlIDw8RU9GCltVbml0XQpEZXNjcmlwdGlvbj1QZXJpb2RpYyAkdmFyIGNyZWRlbnRpYWxzIHJlZnJlc2gKCltTZXJ2aWNlXQpUeXBlPW9uZXNob3QKRXhlY1N0YXJ0PS91c3IvbG9jYWwvYmluL2Rvd25sb2FkLWNyZWRlbnRpYWxzLnNoICR2YXIKRU9GCgpjYXQgPi9ldGMvc3lzdGVtZC9zeXN0ZW0vZG93bmxvYWQtJHZhci1jcmVkZW50aWFscy50aW1lciA8PEVPRgpbVW5pdF0KRGVzY3JpcHRpb249UGVyaW9kaWMgJHZhciBjcmVkZW50aWFscyByZWZyZXNoCkFmdGVyPW5ldHdvcmstb25saW5lLnRhcmdldApXYW50cz1uZXR3b3JrLW9ubGluZS50YXJnZXQKCltUaW1lcl0KT25Cb290U2VjPTBtaW4KT25DYWxlbmRhcj0wLzEyOjAwOjAwCkFjY3VyYWN5U2VjPTVzCgpbSW5zdGFsbF0KV2FudGVkQnk9dGltZXJzLnRhcmdldApFT0YKZG9uZQoKY2F0ID4vdXNyL2xvY2FsL2Jpbi9kb3dubG9hZC1jcmVkZW50aWFscy5zaCA8PEVPRgojIS9iaW4vYmFzaApzZXQgLWV1CgpDT01QT05FTlQ9IlwkMSIKZWNobyAiRG93bmxvYWQgXCRDT01QT05FTlQgY3JlZGVudGlhbHMiCgpURU1QX0RJUj1cJChta3RlbXAgLWQpCmV4cG9ydCBBWlVSRV9DT05GSUdfRElSPVwkKG1rdGVtcCAtZCkKCmVjaG8gIkxvZ2dpbmcgaW50byBBenVyZS4uLiIKUkVUUklFUz0zCndoaWxlIFsgIlwkUkVUUklFUyIgLWd0IDAgXTsgZG8KICAgIGlmIGF6IGxvZ2luIC1pIC0tYWxsb3ctbm8tc3Vic2NyaXB0aW9ucwogICAgdGhlbgogICAgICAgIGVjaG8gImF6IGxvZ2luIHN1Y2Nlc3NmdWwiCiAgICAgICAgYnJlYWsKICAgIGVsc2UKICAgICAgICBlY2hvICJheiBsb2dpbiBmYWlsZWQuIFJldHJ5aW5nLi4uIgogICAgICAgIGxldCBSRVRSSUVTLT0xCiAgICAgICAgc2xlZXAgNQogICAgZmkKZG9uZQoKdHJhcCAiY2xlYW51cCIgRVhJVAoKY2xlYW51cCgpIHsKICBheiBsb2dvdXQKICBbWyAiXCRURU1QX0RJUiIgPX4gL3RtcC8uKyBdXSAmJiBybSAtcmYgXCRURU1QX0RJUgogIFtbICJcJEFaVVJFX0NPTkZJR19ESVIiID1+IC90bXAvLisgXV0gJiYgcm0gLXJmIFwkQVpVUkVfQ09ORklHX0RJUgp9CgppZiBbICJcJENPTVBPTkVOVCIgPSAibWRtIiBdOyB0aGVuCiAgQ1VSUkVOVF9DRVJUX0ZJTEU9Ii9ldGMvbWRtLnBlbSIKZWxpZiBbICJcJENPTVBPTkVOVCIgPSAibWRzZCIgXTsgdGhlbgogIENVUlJFTlRfQ0VSVF9GSUxFPSIvdmFyL2xpYi93YWFnZW50L01pY3Jvc29mdC5BenVyZS5LZXlWYXVsdC5TdG9yZS9tZHNkLnBlbSIKZWxzZQogIGVjaG8gSW52YWxpZCB1c2FnZSAmJiBleGl0IDEKZmkKClNFQ1JFVF9OQU1FPSJycC1cJHtDT01QT05FTlR9IgpORVdfQ0VSVF9GSUxFPSJcJFRFTVBfRElSL1wkQ09NUE9ORU5ULnBlbSIKZm9yIGF0dGVtcHQgaW4gezEuLjV9OyBkbwogIGF6IGtleXZhdWx0IHNlY3JldCBkb3dubG9hZCAtLWZpbGUgXCRORVdfQ0VSVF9GSUxFIC0taWQgImh0dHBzOi8vJEtFWVZBVUxUUFJFRklYLXN2Yy4kS0VZVkFVTFRETlNTVUZGSVgvc2VjcmV0cy9cJFNFQ1JFVF9OQU1FIiAmJiBicmVhawogIGlmIFtbIFwkYXR0ZW1wdCAtbHQgNSBdXTsgdGhlbiBzbGVlcCAxMDsgZWxzZSBleGl0IDE7IGZpCmRvbmUKCmlmIFsgLWYgXCRORVdfQ0VSVF9GSUxFIF07IHRoZW4KICBpZiBbICJcJENPTVBPTkVOVCIgPSAibWRzZCIgXTsgdGhlbgogICAgY2hvd24gc3lzbG9nOnN5c2xvZyBcJE5FV19DRVJUX0ZJTEUKICBlbHNlCiAgICBzZWQgLWkgLW5lICcxLC9FTkQgQ0VSVElGSUNBVEUvIHAnIFwkTkVXX0NFUlRfRklMRQogIGZpCgogIG5ld19jZXJ0X3NuPSJcJChvcGVuc3NsIHg1MDkgLWluICJcJE5FV19DRVJUX0ZJTEUiIC1ub291dCAtc2VyaWFsIHwgYXdrIC1GPSAne3ByaW50IFwkMn0nKSIKICBjdXJyZW50X2NlcnRfc249IlwkKG9wZW5zc2wgeDUwOSAtaW4gIlwkQ1VSUkVOVF9DRVJUX0ZJTEUiIC1ub291dCAtc2VyaWFsIHwgYXdrIC1GPSAne3ByaW50IFwkMn0nKSIKICBpZiBbWyAhIC16IFwkbmV3X2NlcnRfc24gXV0gJiYgW1sgXCRuZXdfY2VydF9zbiAhPSAiXCRjdXJyZW50X2NlcnRfc24iIF1dOyB0aGVuCiAgICBlY2hvIHVwZGF0aW5nIGNlcnRpZmljYXRlIGZvciBcJENPTVBPTkVOVAogICAgY2htb2QgMDYwMCBcJE5FV19DRVJUX0ZJTEUKICAgIG12IFwkTkVXX0NFUlRfRklMRSBcJENVUlJFTlRfQ0VSVF9GSUxFCiAgZmkKZWxzZQogIGVjaG8gRmFpbGVkIHRvIHJlZnJlc2ggY2VydGlmaWNhdGUgZm9yIFwkQ09NUE9ORU5UICYmIGV4aXQgMQpmaQpFT0YKCmNobW9kIHUreCAvdXNyL2xvY2FsL2Jpbi9kb3dubG9hZC1jcmVkZW50aWFscy5zaAoKc3lzdGVtY3RsIGVuYWJsZSBkb3dubG9hZC1tZHNkLWNyZWRlbnRpYWxzLnRpbWVyCnN5c3RlbWN0bCBlbmFibGUgZG93bmxvYWQtbWRtLWNyZWRlbnRpYWxzLnRpbWVyCgovdXNyL2xvY2FsL2Jpbi9kb3dubG9hZC1jcmVkZW50aWFscy5zaCBtZHNkCi91c3IvbG9jYWwvYmluL2Rvd25sb2FkLWNyZWRlbnRpYWxzLnNoIG1kbQpNRFNEQ0VSVElGSUNBVEVTQU49JChvcGVuc3NsIHg1MDkgLWluIC92YXIvbGliL3dhYWdlbnQvTWljcm9zb2Z0LkF6dXJlLktleVZhdWx0LlN0b3JlL21kc2QucGVtIC1ub291dCAtc3ViamVjdCB8IHNlZCAtZSAncy8uKkNOID0gLy8nKQoKY2F0ID4vZXRjL3N5c3RlbWQvc3lzdGVtL3dhdGNoLW1kbS1jcmVkZW50aWFscy5zZXJ2aWNlIDw8RU9GCltVbml0XQpEZXNjcmlwdGlvbj1XYXRjaCBmb3IgY2hhbmdlcyBpbiBtZG0ucGVtIGFuZCByZXN0YXJ0cyB0aGUgbWRtIHNlcnZpY2UKCltTZXJ2aWNlXQpUeXBlPW9uZXNob3QKRXhlY1N0YXJ0PS91c3IvYmluL3N5c3RlbWN0bCByZXN0YXJ0IG1kbS5zZXJ2aWNlCgpbSW5zdGFsbF0KV2FudGVkQnk9bXVsdGktdXNlci50YXJnZXQKRU9GCgpjYXQgPi9ldGMvc3lzdGVtZC9zeXN0ZW0vd2F0Y2gtbWRtLWNyZWRlbnRpYWxzLnBhdGggPDxFT0YKW1BhdGhdClBhdGhNb2RpZmllZD0vZXRjL21kbS5wZW0KCltJbnN0YWxsXQpXYW50ZWRCeT1tdWx0aS11c2VyLnRhcmdldApFT0YKCnN5c3RlbWN0bCBlbmFibGUgd2F0Y2gtbWRtLWNyZWRlbnRpYWxzLnBhdGgKc3lzdGVtY3RsIHN0YXJ0IHdhdGNoLW1kbS1jcmVkZW50aWFscy5wYXRoCgpta2RpciAvZXRjL3N5c3RlbWQvc3lzdGVtL21kc2Quc2VydmljZS5kCmNhdCA+L2V0Yy9zeXN0ZW1kL3N5c3RlbS9tZHNkLnNlcnZpY2UuZC9vdmVycmlkZS5jb25mIDw8J0VPRicKW1VuaXRdCkFmdGVyPW5ldHdvcmstb25saW5lLnRhcmdldApFT0YKCmNhdCA+L2V0Yy9kZWZhdWx0L21kc2QgPDxFT0YKTURTRF9ST0xFX1BSRUZJWD0vdmFyL3J1bi9tZHNkL2RlZmF1bHQKTURTRF9PUFRJT05TPSItQSAtZCAtciBcJE1EU0RfUk9MRV9QUkVGSVgiCgpleHBvcnQgTU9OSVRPUklOR19HQ1NfRU5WSVJPTk1FTlQ9JyRNRFNERU5WSVJPTk1FTlQnCmV4cG9ydCBNT05JVE9SSU5HX0dDU19BQ0NPVU5UPSckUlBNRFNEQUNDT1VOVCcKZXhwb3J0IE1PTklUT1JJTkdfR0NTX1JFR0lPTj0nJExPQ0FUSU9OJwpleHBvcnQgTU9OSVRPUklOR19HQ1NfQVVUSF9JRF9UWVBFPUF1dGhLZXlWYXVsdApleHBvcnQgTU9OSVRPUklOR19HQ1NfQVVUSF9JRD0nJE1EU0RDRVJUSUZJQ0FURVNBTicKZXhwb3J0IE1PTklUT1JJTkdfR0NTX05BTUVTUEFDRT0nJFJQTURTRE5BTUVTUEFDRScKZXhwb3J0IE1PTklUT1JJTkdfQ09ORklHX1ZFUlNJT049JyRSUE1EU0RDT05GSUdWRVJTSU9OJwpleHBvcnQgTU9OSVRPUklOR19VU0VfR0VORVZBX0NPTkZJR19TRVJWSUNFPXRydWUKCmV4cG9ydCBNT05JVE9SSU5HX1RFTkFOVD0nJExPQ0FUSU9OJwpleHBvcnQgTU9OSVRPUklOR19ST0xFPXJwCmV4cG9ydCBNT05JVE9SSU5HX1JPTEVfSU5TVEFOQ0U9JyQoaG9zdG5hbWUpJwoKZXhwb3J0IE1EU0RfTVNHUEFDS19TT1JUX0NPTFVNTlM9MQpFT0YKCiMgc2V0dGluZyBNT05JVE9SSU5HX0dDU19BVVRIX0lEX1RZUEU9QXV0aEtleVZhdWx0IHNlZW1zIHRvIGhhdmUgY2F1c2VkIG1kc2Qgbm90CiMgdG8gaG9ub3VyIFNTTF9DRVJUX0ZJTEUgYW55IG1vcmUsIGhlYXZlbiBvbmx5IGtub3dzIHdoeS4KbWtkaXIgLXAgL3Vzci9saWIvc3NsL2NlcnRzCmNzcGxpdCAtZiAvdXNyL2xpYi9zc2wvY2VydHMvY2VydC0gLWIgJTAzZC5wZW0gL2V0Yy9wa2kvdGxzL2NlcnRzL2NhLWJ1bmRsZS5jcnQgL14kLzEgeyp9ID4vZGV2L251bGwKY19yZWhhc2ggL3Vzci9saWIvc3NsL2NlcnRzCgojIHdlIGxlYXZlIGNsaWVudElkIGJsYW5rIGFzIGxvbmcgYXMgb25seSAxIG1hbmFnZWQgaWRlbnRpdHkgYXNzaWduZWQgdG8gdm1zcwojIGlmIHdlIGhhdmUgbW9yZSB0aGFuIDEsIHdlIHdpbGwgbmVlZCB0byBwb3B1bGF0ZSB3aXRoIGNsaWVudElkIHVzZWQgZm9yIG9mZi1ub2RlIHNjYW5uaW5nCmNhdCA+L2V0Yy9kZWZhdWx0L3ZzYS1ub2Rlc2Nhbi1hZ2VudC5jb25maWcgPDxFT0YKewogICAgIk5pY2UiOiAxOSwKICAgICJUaW1lb3V0IjogMTA4MDAsCiAgICAiQ2xpZW50SWQiOiAiIiwKICAgICJUZW5hbnRJZCI6ICIkQVpVUkVTRUNQQUNLVlNBVEVOQU5USUQiLAogICAgIlF1YWx5c1N0b3JlQmFzZVVybCI6ICIkQVpVUkVTRUNQQUNLUVVBTFlTVVJMIiwKICAgICJQcm9jZXNzVGltZW91dCI6IDMwMCwKICAgICJDb21tYW5kRGVsYXkiOiAwCiAgfQpFT0YKCmVjaG8gImVuYWJsaW5nIGFybyBzZXJ2aWNlcyIKZm9yIHNlcnZpY2UgaW4gYXJvLWRidG9rZW4gYXJvLW1vbml0b3IgYXJvLXBvcnRhbCBhcm8tcnAgYXVvbXMgYXpzZWNkIGF6c2VjbW9uZCBtZHNkIG1kbSBjaHJvbnlkIGZsdWVudGJpdDsgZG8KICBzeXN0ZW1jdGwgZW5hYmxlICRzZXJ2aWNlLnNlcnZpY2UKZG9uZQoKZm9yIHNjYW4gaW4gYmFzZWxpbmUgY2xhbWF2IHNvZnR3YXJlOyBkbwogIC91c3IvbG9jYWwvYmluL2F6c2VjZCBjb25maWcgLXMgJHNjYW4gLWQgUDFECmRvbmUKCmVjaG8gInJlYm9vdGluZyIKcmVzdG9yZWNvbiAtUkYgL3Zhci9sb2cvKgooc2xlZXAgMzA7IHJlYm9vdCkgJgo=')))]" + "script": "[base64(concat(base64ToString('c2V0IC1leAoK'),'ACRRESOURCEID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('acrResourceId')),''')\n','ADMINAPICLIENTCERTCOMMONNAME=$(base64 -d \u003c\u003c\u003c''',base64(parameters('adminApiClientCertCommonName')),''')\n','ARMAPICLIENTCERTCOMMONNAME=$(base64 -d \u003c\u003c\u003c''',base64(parameters('armApiClientCertCommonName')),''')\n','ARMCLIENTID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('armClientId')),''')\n','AZURECLOUDNAME=$(base64 -d \u003c\u003c\u003c''',base64(parameters('azureCloudName')),''')\n','AZURESECPACKQUALYSURL=$(base64 -d \u003c\u003c\u003c''',base64(parameters('azureSecPackQualysUrl')),''')\n','AZURESECPACKVSATENANTID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('azureSecPackVSATenantId')),''')\n','BILLINGE2ESTORAGEACCOUNTID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('billingE2EStorageAccountId')),''')\n','CLUSTERMDMACCOUNT=$(base64 -d \u003c\u003c\u003c''',base64(parameters('clusterMdmAccount')),''')\n','CLUSTERMDSDACCOUNT=$(base64 -d \u003c\u003c\u003c''',base64(parameters('clusterMdsdAccount')),''')\n','CLUSTERMDSDCONFIGVERSION=$(base64 -d \u003c\u003c\u003c''',base64(parameters('clusterMdsdConfigVersion')),''')\n','CLUSTERMDSDNAMESPACE=$(base64 -d \u003c\u003c\u003c''',base64(parameters('clusterMdsdNamespace')),''')\n','CLUSTERPARENTDOMAINNAME=$(base64 -d \u003c\u003c\u003c''',base64(parameters('clusterParentDomainName')),''')\n','DATABASEACCOUNTNAME=$(base64 -d \u003c\u003c\u003c''',base64(parameters('databaseAccountName')),''')\n','DBTOKENCLIENTID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('dbtokenClientId')),''')\n','FLUENTBITIMAGE=$(base64 -d \u003c\u003c\u003c''',base64(parameters('fluentbitImage')),''')\n','FPCLIENTID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('fpClientId')),''')\n','FPSERVICEPRINCIPALID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('fpServicePrincipalId')),''')\n','GATEWAYDOMAINS=$(base64 -d \u003c\u003c\u003c''',base64(parameters('gatewayDomains')),''')\n','GATEWAYRESOURCEGROUPNAME=$(base64 -d \u003c\u003c\u003c''',base64(parameters('gatewayResourceGroupName')),''')\n','GATEWAYSERVICEPRINCIPALID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('gatewayServicePrincipalId')),''')\n','KEYVAULTDNSSUFFIX=$(base64 -d \u003c\u003c\u003c''',base64(parameters('keyvaultDNSSuffix')),''')\n','KEYVAULTPREFIX=$(base64 -d \u003c\u003c\u003c''',base64(parameters('keyvaultPrefix')),''')\n','MDMFRONTENDURL=$(base64 -d \u003c\u003c\u003c''',base64(parameters('mdmFrontendUrl')),''')\n','MDSDENVIRONMENT=$(base64 -d \u003c\u003c\u003c''',base64(parameters('mdsdEnvironment')),''')\n','PORTALACCESSGROUPIDS=$(base64 -d \u003c\u003c\u003c''',base64(parameters('portalAccessGroupIds')),''')\n','PORTALCLIENTID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('portalClientId')),''')\n','PORTALELEVATEDGROUPIDS=$(base64 -d \u003c\u003c\u003c''',base64(parameters('portalElevatedGroupIds')),''')\n','RPFEATURES=$(base64 -d \u003c\u003c\u003c''',base64(parameters('rpFeatures')),''')\n','RPIMAGE=$(base64 -d \u003c\u003c\u003c''',base64(parameters('rpImage')),''')\n','RPMDMACCOUNT=$(base64 -d \u003c\u003c\u003c''',base64(parameters('rpMdmAccount')),''')\n','RPMDSDACCOUNT=$(base64 -d \u003c\u003c\u003c''',base64(parameters('rpMdsdAccount')),''')\n','RPMDSDCONFIGVERSION=$(base64 -d \u003c\u003c\u003c''',base64(parameters('rpMdsdConfigVersion')),''')\n','RPMDSDNAMESPACE=$(base64 -d \u003c\u003c\u003c''',base64(parameters('rpMdsdNamespace')),''')\n','RPPARENTDOMAINNAME=$(base64 -d \u003c\u003c\u003c''',base64(parameters('rpParentDomainName')),''')\n','CLUSTERSINSTALLVIAHIVE=$(base64 -d \u003c\u003c\u003c''',base64(parameters('clustersInstallViaHive')),''')\n','CLUSTERSADOPTBYHIVE=$(base64 -d \u003c\u003c\u003c''',base64(parameters('clustersAdoptByHive')),''')\n','CLUSTERDEFAULTINSTALLERPULLSPEC=$(base64 -d \u003c\u003c\u003c''',base64(parameters('clusterDefaultInstallerPullspec')),''')\n','USECHECKACCESS=$(base64 -d \u003c\u003c\u003c''',base64(parameters('useCheckAccess')),''')\n','ADMINAPICABUNDLE=''',parameters('adminApiCaBundle'),'''\n','ARMAPICABUNDLE=''',parameters('armApiCaBundle'),'''\n','MDMIMAGE=''/genevamdm:2.2024.328.1744-c5fb79-20240328t1935''\n','LOCATION=$(base64 -d \u003c\u003c\u003c''',base64(resourceGroup().location),''')\n','SUBSCRIPTIONID=$(base64 -d \u003c\u003c\u003c''',base64(subscription().subscriptionId),''')\n','RESOURCEGROUPNAME=$(base64 -d \u003c\u003c\u003c''',base64(resourceGroup().name),''')\n','\n',base64ToString('IyEvYmluL2Jhc2gKCnNldCAtbyBlcnJleGl0IFwKICAgIC1vIG5vdW5zZXQKCnRyYXAgJ2NhdGNoJyBFUlIKCm1haW4oKSB7CiAgICBjb25maWd1cmVfc3NoZAogICAgY29uZmlndXJlX2FuZF9pbnN0YWxsX2RuZl9wa2dzX3JlcG9zCiAgICBjb25maWd1cmVfZGlza19wYXJ0aXRpb25zCiAgICBjb25maWd1cmVfbG9ncm90YXRlCiAgICBjb25maWd1cmVfc2VsaW51eAoKICAgIG1rZGlyIC1wIC92YXIvbG9nL2pvdXJuYWwKICAgIG1rZGlyIC1wIC92YXIvbGliL3dhYWdlbnQvTWljcm9zb2Z0LkF6dXJlLktleVZhdWx0LlN0b3JlCgogICAgY29uZmlndXJlX2ZpcmV3YWxsZF9ydWxlcwogICAgcHVsbF9jb250YWluZXJfaW1hZ2VzCiAgICBjb25maWd1cmVfc3lzdGVtX3NlcnZpY2VzCiAgICByZWJvb3Rfdm0KfQoKIyBXZSBuZWVkIHRvIGNvbmZpZ3VyZSBQYXNzd29yZEF1dGhlbnRpY2F0aW9uIHRvIHllcyBpbiBvcmRlciBmb3IgdGhlIFZNU1MgQWNjZXNzIEpJVCB0byB3b3JrCmNvbmZpZ3VyZV9zc2hkKCkgewogICAgbG9nICJzZXR0aW5nIHNzaCBwYXNzd29yZCBhdXRoZW50aWNhdGlvbiIKICAgIHNlZCAtaSAncy9QYXNzd29yZEF1dGhlbnRpY2F0aW9uIG5vL1Bhc3N3b3JkQXV0aGVudGljYXRpb24geWVzL2cnIC9ldGMvc3NoL3NzaGRfY29uZmlnCgogICAgc3lzdGVtY3RsIHJlbG9hZCBzc2hkLnNlcnZpY2UKICAgIHN5c3RlbWN0bCBpcy1hY3RpdmUgLS1xdWlldCBzc2hkIHx8IGFib3J0ICJzc2hkIGZhaWxlZCB0byByZWxvYWQiCn0KCiMgY29uZmlndXJlX2FuZF9pbnN0YWxsX2RuZl9wa2dzX3JlcG9zCmNvbmZpZ3VyZV9hbmRfaW5zdGFsbF9kbmZfcGtnc19yZXBvcygpIHsKICAgIGNvbmZpZ3VyZV9yaHVpX3JlcG8KICAgIGNyZWF0ZV9henVyZV9ycG1fcmVwb3MKICAgIGRuZl91cGRhdGVfcGtncwogICAgZG5mX2luc3RhbGxfcGtncwp9CgojIGNvbmZpZ3VyZV9yaHVpX3JlcG8KY29uZmlndXJlX3JodWlfcmVwbygpIHsKICAgIGxvZyAicnVubmluZyBSSFVJIHBhY2thZ2UgdXBkYXRlcyIKICAgICNBZGRpbmcgcmV0cnkgbG9naWMgdG8geXVtIGNvbW1hbmRzIGluIG9yZGVyIHRvIGF2b2lkIHN0YWxsaW5nIG91dCBvbiByZXNvdXJjZSBsb2NrcwogICAgZm9yIGF0dGVtcHQgaW4gezEuLjV9OyBkbwogICAgICAgIGRuZiB1cGRhdGUgXAogICAgICAgICAgICAteSBcCiAgICAgICAgICAgIC0tZGlzYWJsZXJlcG89JyonIFwKICAgICAgICAgICAgLS1lbmFibGVyZXBvPSdyaHVpLW1pY3Jvc29mdC1henVyZSonIFwKICAgICAgICAgICAgJiYgYnJlYWsKICAgICAgICBpZiBbWyAke2F0dGVtcHR9IC1sdCA1IF1dOyB0aGVuCiAgICAgICAgICAgIHNsZWVwIDEwCiAgICAgICAgZWxzZQogICAgICAgICAgICBhYm9ydCAiZmFpbGVkIHRvIHJ1biBkbmYgdXBkYXRlIgogICAgICAgIGZpCiAgICBkb25lCn0KCiMgZG5mX3VwZGF0ZV9wa2dzCmRuZl91cGRhdGVfcGtncygpIHsKICAgIGxvZyAicnVubmluZyBkbmYgdXBkYXRlIgogICAgZm9yIGF0dGVtcHQgaW4gezEuLjV9OyBkbwogICAgICAgIGRuZiAteSBcCiAgICAgICAgICAgIC14IFdBTGludXhBZ2VudCBcCiAgICAgICAgICAgIC14IFdBTGludXhBZ2VudC11ZGV2IFwKICAgICAgICAgICAgdXBkYXRlIC0tYWxsb3dlcmFzaW5nIFwKICAgICAgICAgICAgJiYgYnJlYWsKICAgICAgICBpZiBbWyAke2F0dGVtcHR9IC1sdCA1IF1dOyB0aGVuCiAgICAgICAgICAgIHNsZWVwIDEwCiAgICAgICAgZWxzZQogICAgICAgICAgICByZXR1cm4gMQogICAgICAgIGZpCiAgICBkb25lCn0KCiMgZG5mX2luc3RhbGxfcGtncwpkbmZfaW5zdGFsbF9wa2dzKCkgewogICAgbG9nICJpbXBvcnRpbmcgcnBtIHJlcG9zaXRvcmllcyIKICAgIHJwbSAtLWltcG9ydCBodHRwczovL2RsLmZlZG9yYXByb2plY3Qub3JnL3B1Yi9lcGVsL1JQTS1HUEctS0VZLUVQRUwtOAogICAgcnBtIC0taW1wb3J0IGh0dHBzOi8vcGFja2FnZXMubWljcm9zb2Z0LmNvbS9rZXlzL21pY3Jvc29mdC5hc2MKCiAgICBmb3IgYXR0ZW1wdCBpbiB7MS4uNX07IGRvCiAgICAgICAgZG5mIC15IFwKICAgICAgICAgICAgaW5zdGFsbCBodHRwczovL2RsLmZlZG9yYXByb2plY3Qub3JnL3B1Yi9lcGVsL2VwZWwtcmVsZWFzZS1sYXRlc3QtOC5ub2FyY2gucnBtIFwKICAgICAgICAgICAgJiYgYnJlYWsKICAgICAgICBpZiBbWyAke2F0dGVtcHR9IC1sdCA1IF1dOyB0aGVuCiAgICAgICAgICAgIHNsZWVwIDEwCiAgICAgICAgZWxzZQogICAgICAgICAgICByZXR1cm4gMQogICAgICAgIGZpCiAgICBkb25lCgogICAgZm9yIGF0dGVtcHQgaW4gezEuLjV9OyBkbwogICAgICAgIGRuZiAteSBcCiAgICAgICAgICAgIGluc3RhbGwgXAogICAgICAgICAgICBjbGFtYXYgXAogICAgICAgICAgICBhenNlYy1jbGFtYXYgXAogICAgICAgICAgICBhenNlYy1tb25pdG9yIFwKICAgICAgICAgICAgYXp1cmUtY2xpIFwKICAgICAgICAgICAgYXp1cmUtbWRzZCBcCiAgICAgICAgICAgIGF6dXJlLXNlY3VyaXR5IFwKICAgICAgICAgICAgcG9kbWFuIFwKICAgICAgICAgICAgcG9kbWFuLWRvY2tlciBcCiAgICAgICAgICAgIG9wZW5zc2wtcGVybCBcCiAgICAgICAgICAgIHB5dGhvbjMgXAogICAgICAgICAgICAmJiBicmVhawogICAgICAgICMgaGFjayAtIHdlIGFyZSBpbnN0YWxsaW5nIHB5dGhvbjMgb24gaG9zdHMgZHVlIHRvIGFuIGlzc3VlIHdpdGggQXp1cmUgTGludXggRXh0ZW5zaW9ucyBodHRwczovL2dpdGh1Yi5jb20vQXp1cmUvYXp1cmUtbGludXgtZXh0ZW5zaW9ucy9wdWxsLzE1MDUKICAgICAgICBpZiBbWyAke2F0dGVtcHR9IC1sdCA1IF1dOyB0aGVuCiAgICAgICAgICAgIHNsZWVwIDEwCiAgICAgICAgZWxzZQogICAgICAgICAgICBhYm9ydCAiZmFpbGVkIHRvIGluc3RhbGwgcmVxdWlyZWQgcGFja2FnZXMiCiAgICAgICAgZmkKICAgIGRvbmUKfQoKIyBjb25maWd1cmVfZGlza19wYXJ0aXRpb25zCmNvbmZpZ3VyZV9kaXNrX3BhcnRpdGlvbnMoKSB7CiAgICBsb2cgImV4dGVuZGluZyBwYXJ0aXRpb24gdGFibGUiCiAgICAjIExpbnV4IGJsb2NrIGRldmljZXMgYXJlIGluY29uc2lzdGVudGx5IG5hbWVkCiAgICAjIGl0J3MgZGlmZmljdWx0IHRvIHRpZSB0aGUgbHZtIHB2IHRvIHRoZSBwaHlzaWNhbCBkaXNrIHVzaW5nIC9kZXYvZGlzayBmaWxlcywgd2hpY2ggaXMgd2h5IGx2cyBpcyB1c2VkIGhlcmUKICAgIHBoeXNpY2FsRGlzaz0iJChsdnMgLW8gZGV2aWNlcyAtYSB8IGhlYWQgLW4yIHwgdGFpbCAtbjEgfCBjdXQgLWQgJyAnIC1mIDMgfCBjdXQgLWQgXCggLWYgMSB8IHRyIC1kICdbOmRpZ2l0Ol0nKSIKICAgIGdyb3dwYXJ0ICIkcGh5c2ljYWxEaXNrIiAyCgogICAgbG9nICJleHRlbmRpbmcgZmlsZXN5c3RlbXMiCiAgICBsb2cgImV4dGVuZGluZyByb290IGx2bSIKICAgIGx2ZXh0ZW5kIC1sICsyMCVGUkVFIC9kZXYvcm9vdHZnL3Jvb3RsdgogICAgbG9nICJncm93aW5nIHJvb3QgZmlsZXN5c3RlbSIKICAgIHhmc19ncm93ZnMgLwoKICAgIGxvZyAiZXh0ZW5kaW5nIHZhciBsdm0iCiAgICBsdmV4dGVuZCAtbCArMTAwJUZSRUUgL2Rldi9yb290dmcvdmFybHYKICAgIGxvZyAiZ3Jvd2luZyB2YXIgZmlsZXN5c3RlbSIKICAgIHhmc19ncm93ZnMgL3Zhcgp9CgojIGNvbmZpZ3VyZV9sb2dyb3RhdGUgY2xvYmJlcnMgL2V0Yy9sb2dyb3RhdGUuY29uZgpjb25maWd1cmVfbG9ncm90YXRlKCkgewogICAgbG9jYWwgLXIgbG9ncm90YXRlX2NvbmZfZmlsZW5hbWU9Jy9ldGMvbG9ncm90YXRlLmNvbmYnCiAgICBsb2NhbCAtciBsb2dyb3RhdGVfY29uZl9maWxlPScjIHNlZSAibWFuIGxvZ3JvdGF0ZSIgZm9yIGRldGFpbHMKIyByb3RhdGUgbG9nIGZpbGVzIHdlZWtseQp3ZWVrbHkKCiMga2VlcCAyIHdlZWtzIHdvcnRoIG9mIGJhY2tsb2dzCnJvdGF0ZSAyCgojIGNyZWF0ZSBuZXcgKGVtcHR5KSBsb2cgZmlsZXMgYWZ0ZXIgcm90YXRpbmcgb2xkIG9uZXMKY3JlYXRlCgojIHVzZSBkYXRlIGFzIGEgc3VmZml4IG9mIHRoZSByb3RhdGVkIGZpbGUKZGF0ZWV4dAoKIyB1bmNvbW1lbnQgdGhpcyBpZiB5b3Ugd2FudCB5b3VyIGxvZyBmaWxlcyBjb21wcmVzc2VkCmNvbXByZXNzCgojIFJQTSBwYWNrYWdlcyBkcm9wIGxvZyByb3RhdGlvbiBpbmZvcm1hdGlvbiBpbnRvIHRoaXMgZGlyZWN0b3J5CmluY2x1ZGUgL2V0Yy9sb2dyb3RhdGUuZAoKIyBubyBwYWNrYWdlcyBvd24gd3RtcCBhbmQgYnRtcCAtLSB3ZSB3aWxsIHJvdGF0ZSB0aGVtIGhlcmUKL3Zhci9sb2cvd3RtcCB7CiAgICBtb250aGx5CiAgICBjcmVhdGUgMDY2NCByb290IHV0bXAKICAgICAgICBtaW5zaXplIDFNCiAgICByb3RhdGUgMQp9CgovdmFyL2xvZy9idG1wIHsKICAgIG1pc3NpbmdvawogICAgbW9udGhseQogICAgY3JlYXRlIDA2MDAgcm9vdCB1dG1wCiAgICByb3RhdGUgMQp9JwoKICAgIHdyaXRlX2ZpbGUgbG9ncm90YXRlX2NvbmZfZmlsZW5hbWUgbG9ncm90YXRlX2NvbmZfZmlsZSB0cnVlCn0KCiMgY3JlYXRlX2F6dXJlX3JwbV9yZXBvcyBjcmVhdGVzIC9ldGMveXVtLnJlcG9zLmQvYXp1cmUucmVwbyByZXBvc2l0b3J5IGZpbGUKY3JlYXRlX2F6dXJlX3JwbV9yZXBvcygpIHsKICAgIGxvY2FsIC1yIGF6dXJlX3JlcG9fZmlsZW5hbWU9Jy9ldGMveXVtLnJlcG9zLmQvYXp1cmUucmVwbycKICAgIGxvY2FsIC1yIGF6dXJlX3JlcG9fZmlsZT0nW2F6dXJlLWNsaV0KbmFtZT1henVyZS1jbGkKYmFzZXVybD1odHRwczovL3BhY2thZ2VzLm1pY3Jvc29mdC5jb20veXVtcmVwb3MvYXp1cmUtY2xpCmVuYWJsZWQ9eWVzCmdwZ2NoZWNrPXllcwoKW2F6dXJlY29yZV0KbmFtZT1henVyZWNvcmUKYmFzZXVybD1odHRwczovL3BhY2thZ2VzLm1pY3Jvc29mdC5jb20veXVtcmVwb3MvYXp1cmVjb3JlCmVuYWJsZWQ9eWVzCmdwZ2NoZWNrPW5vJwoKICAgIHdyaXRlX2ZpbGUgYXp1cmVfcmVwb19maWxlbmFtZSBhenVyZV9yZXBvX2ZpbGUKfQoKIyBjb25maWd1cmVfc2VsaW51eApjb25maWd1cmVfc2VsaW51eCgpIHsKICAgIGxvY2FsIC1yIHJlbGFiZWw9IiR7MTotZmFsc2V9IgoKICAgIGFscmVhZHlfZGVmaW5lZF9pZ25vcmVfZXJyb3I9IkZpbGUgY29udGV4dCBmb3IgL3Zhci9sb2cvam91cm5hbCgvLiopPyBhbHJlYWR5IGRlZmluZWQiCiAgICBzZW1hbmFnZSBmY29udGV4dCAtYSAtdCB2YXJfbG9nX3QgIi92YXIvbG9nL2pvdXJuYWwoLy4qKT8iIHx8IGxvZyAiJGFscmVhZHlfZGVmaW5lZF9pZ25vcmVfZXJyb3IiCiAgICBjaGNvbiAtUiBzeXN0ZW1fdTpvYmplY3Rfcjp2YXJfbG9nX3Q6czAgL3Zhci9vcHQvbWljcm9zb2Z0L2xpbnV4bW9uYWdlbnQKCiAgICBpZiAiJHJlbGFiZWwiOyB0aGVuCiAgICAgICAgcmVzdG9yZWNvbiAtUkYgL3Zhci9sb2cvKiB8fCBsb2cgIiRhbHJlYWR5X2RlZmluZWRfaWdub3JlX2Vycm9yIgogICAgZmkKfQoKIyBjb25maWd1cmVfZmlyZXdhbGxkX3J1bGVzCmNvbmZpZ3VyZV9maXJld2FsbGRfcnVsZXMoKSB7CiAgICAjIGh0dHBzOi8vYWNjZXNzLnJlZGhhdC5jb20vc2VjdXJpdHkvY3ZlL2N2ZS0yMDIwLTEzNDAxCiAgICBsb2NhbCAtciBwcmVmaXg9Ii9ldGMvc3lzY3RsLmQiCiAgICBsb2NhbCAtciBkaWFibGVfYWNjZXB0X3JhX2NvbmY9IiRwcmVmaXgvMDItZGlzYWJsZS1hY2NlcHQtcmEuY29uZiIKICAgIGxvZyAiV3JpdGluZyAkZGlhYmxlX2FjY2VwdF9yYV9jb25mIgpjYXQgPiIkZGlhYmxlX2FjY2VwdF9yYV9jb25mIiA8PCdFT0YnCm5ldC5pcHY2LmNvbmYuYWxsLmFjY2VwdF9yYT0wCkVPRgoKICAgIGxvY2FsIC1yIGRpc2FibGVfY29yZV9maWxlbmFtZT0iJHByZWZpeC8wMS1kaXNhYmxlLWNvcmUuY29uZiIKICAgIGxvY2FsIC1yIGRpc2FibGVfY29yZV9maWxlPSJrZXJuZWwuY29yZV9wYXR0ZXJuID0gfC9iaW4vdHJ1ZQogICAgIgogICAgd3JpdGVfZmlsZSBkaXNhYmxlX2NvcmVfZmlsZW5hbWUgZGlzYWJsZV9jb3JlX2ZpbGUKCiAgICBzeXNjdGwgLS1zeXN0ZW0KCiAgICBlbmFibGVfcG9ydHM9KAogICAgICAgICI0NDMvdGNwIgogICAgICAgICI0NDQvdGNwIgogICAgICAgICI0NDUvdGNwIgogICAgICAgICIyMjIyL3RjcCIKICAgICkKICAgIGxvZyAiRW5hYmxpbmcgcG9ydHMgJHtlbmFibGVfcG9ydHNbKl19IG9uIGRlZmF1bHQgZmlyZXdhbGxkIHpvbmUiCiAgICAjIHNoZWxsY2hlY2sgZGlzYWJsZT1TQzIwNjgKICAgIGZvciBwb3J0IGluICR7ZW5hYmxlX3BvcnRzW0BdfTsgZG8KICAgICAgICBsb2cgIkVuYWJsaW5nIHBvcnQgJHBvcnQgbm93IgogICAgICAgIGZpcmV3YWxsLWNtZCAiLS1hZGQtcG9ydD0kcG9ydCIKICAgIGRvbmUKCiAgICBmaXJld2FsbC1jbWQgLS1ydW50aW1lLXRvLXBlcm1hbmVudAp9CgojIHB1bGxfY29udGFpbmVyX2ltYWdlcwpwdWxsX2NvbnRhaW5lcl9pbWFnZXMoKSB7CiAgICBlY2hvICJsb2dnaW5nIGludG8gcHJvZCBhY3IiCiAgICBheiBsb2dpbiAtaSAtLWFsbG93LW5vLXN1YnNjcmlwdGlvbnMKCiAgICAjIFN1cHByZXNzIGVtdWxhdGlvbiBvdXRwdXQgZm9yIHBvZG1hbiBpbnN0ZWFkIG9mIGRvY2tlciBmb3IgYXogYWNyIGNvbXBhdGFiaWxpdHkKICAgIG1rZGlyIC1wIC9ldGMvY29udGFpbmVycy8KICAgIHRvdWNoIC9ldGMvY29udGFpbmVycy9ub2RvY2tlcgoKICAgIG1rZGlyIC1wIC9yb290Ly5kb2NrZXIKICAgIGxvY2FsIC1yIFJFR0lTVFJZX0FVVEhfRklMRT0iL3Jvb3QvLmRvY2tlci9jb25maWcuanNvbiIKICAgIAogICAgYXogYWNyIGxvZ2luIC0tbmFtZSAiJChzZWQgLWUgJ3N8LiovfHwnIDw8PCIkQUNSUkVTT1VSQ0VJRCIpIgoKICAgIE1ETUlNQUdFPSIke1JQSU1BR0UlJS8qfS8ke01ETUlNQUdFIyMqL30iCiAgICBkb2NrZXIgcHVsbCAiJE1ETUlNQUdFIgogICAgZG9ja2VyIHB1bGwgIiRSUElNQUdFIgogICAgZG9ja2VyIHB1bGwgIiRGTFVFTlRCSVRJTUFHRSIKCiAgICBheiBsb2dvdXQKfQoKIyBjb25maWd1cmVfc3lzdGVtX3NlcnZpY2VzIGNyZWF0ZXMsIGNvbmZpZ3VyZXMsIGFuZCBlbmFibGVzIHRoZSBmb2xsb3dpbmcgc3lzdGVtZCBzZXJ2aWNlcyBhbmQgdGltZXJzCiMgc2VydmljZXMKIyAgIGZsdWVudGJpdAojICAgbWRtCiMgICBtZHNkCiMgICBhcnAtcnAKIyAgIGFyby1kYnRva2VuCiMgICBhcm8tbW9uaXRvcgojICAgYXJvLXBvcnRhbApjb25maWd1cmVfc3lzdGVtX3NlcnZpY2VzKCkgewogICAgY29uZmlndXJlX3NlcnZpY2VfZmx1ZW50Yml0CiAgICBjb25maWd1cmVfc2VydmljZV9tZG0KICAgIGNvbmZpZ3VyZV90aW1lcnNfbWRtX21kc2QKICAgIGNvbmZpZ3VyZV9zZXJ2aWNlX2Fyb19ycAogICAgY29uZmlndXJlX3NlcnZpY2VfYXJvX2RidG9rZW4KICAgIGNvbmZpZ3VyZV9zZXJ2aWNlX2Fyb19tb25pdG9yCiAgICBjb25maWd1cmVfc2VydmljZV9hcm9fcG9ydGFsCiAgICBjb25maWd1cmVfc2VydmljZV9tZHNkCn0KCiMgZW5hYmxlX2Fyb19zZXJ2aWNlcyBlbmFibGVzIGFsbCBzZXJ2aWNlcyByZXF1aXJlZCBmb3IgYXJvIHJwCmVuYWJsZV9hcm9fc2VydmljZXMoKSB7CiAgICBsb2NhbCAtcmEgYXJvX3NlcnZpY2VzPSgKICAgICAgICAiYXJvLWRidG9rZW4iCiAgICAgICAgImFyby1tb25pdG9yIgogICAgICAgICJhcm8tcG9ydGFsIgogICAgICAgICJhcm8tcnAiCiAgICAgICAgImF1b21zIgogICAgICAgICJhenNlY2QiCiAgICAgICAgImF6c2VjbW9uZCIKICAgICAgICAibWRzZCIKICAgICAgICAibWRtIgogICAgICAgICJjaHJvbnlkIgogICAgICAgICJmbHVlbnRiaXQiCiAgICApCiAgICBsb2cgImVuYWJsaW5nIGFybyBzZXJ2aWNlcyAke2Fyb19zZXJ2aWNlc1sqXX0iCiAgICAjIHNoZWxsY2hlY2sgZGlzYWJsZT1TQzIwNjgKICAgIGZvciBzZXJ2aWNlIGluICR7YXJvX3NlcnZpY2VzW0BdfTsgZG8KICAgICAgICBsb2cgIkVuYWJsaW5nICRzZXJ2aWNlIG5vdyIKICAgICAgICBzeXN0ZW1jdGwgZW5hYmxlICIkc2VydmljZS5zZXJ2aWNlIgogICAgZG9uZQp9CgojIGNvbmZpZ3VyZV9zZXJ2aWNlX2ZsdWVudGJpdApjb25maWd1cmVfc2VydmljZV9mbHVlbnRiaXQoKSB7CiAgICBsb2cgImNvbmZpZ3VyaW5nIGZsdWVudGJpdCBzZXJ2aWNlIgogICAgbWtkaXIgLXAgL2V0Yy9mbHVlbnRiaXQvCiAgICBta2RpciAtcCAvdmFyL2xpYi9mbHVlbnQKCiAgICBsb2NhbCAtciBmbHVlbnRiaXRfY29uZl9maWxlbmFtZT0nL2V0Yy9mbHVlbnRiaXQvZmx1ZW50Yml0LmNvbmYnCiAgICBsb2NhbCAtciBmbHVlbnRiaXRfY29uZl9maWxlPSJbSU5QVVRdCk5hbWUgc3lzdGVtZApUYWcgam91cm5hbGQKU3lzdGVtZF9GaWx0ZXIgX0NPTU09YXJvCkRCIC92YXIvbGliL2ZsdWVudC9qb3VybmFsZGIKCltGSUxURVJdCglOYW1lIG1vZGlmeQoJTWF0Y2ggam91cm5hbGQKCVJlbW92ZV93aWxkY2FyZCBfCglSZW1vdmUgVElNRVNUQU1QCgpbRklMVEVSXQoJTmFtZSByZXdyaXRlX3RhZwoJTWF0Y2ggam91cm5hbGQKCVJ1bGUgJExPR0tJTkQgYXN5bmNxb3MgYXN5bmNxb3MgdHJ1ZQoKW0ZJTFRFUl0KCU5hbWUgbW9kaWZ5CglNYXRjaCBhc3luY3FvcwoJUmVtb3ZlIENMSUVOVF9QUklOQ0lQQUxfTkFNRQoJUmVtb3ZlIEZJTEUKCVJlbW92ZSBDT01QT05FTlQKCltGSUxURVJdCglOYW1lIHJld3JpdGVfdGFnCglNYXRjaCBqb3VybmFsZAoJUnVsZSAkTE9HS0lORCBpZnhhdWRpdCBpZnhhdWRpdCBmYWxzZQoKW09VVFBVVF0KCU5hbWUgZm9yd2FyZAoJTWF0Y2ggKgoJUG9ydCAyOTIzMCIKCiAgICB3cml0ZV9maWxlIGZsdWVudGJpdF9jb25mX2ZpbGVuYW1lIGZsdWVudGJpdF9jb25mX2ZpbGUKCiAgICBsb2NhbCAtciBzeXNjb25maWdfZmx1ZW50Yml0X2ZpbGVuYW1lPScvZXRjL3N5c2NvbmZpZy9mbHVlbnRiaXQnCiAgICBsb2NhbCAtciBzeXNjb25maWdfZmx1ZW50Yml0X2ZpbGU9IkZMVUVOVEJJVElNQUdFPSRGTFVFTlRCSVRJTUFHRSIKCiAgICB3cml0ZV9maWxlIHN5c2NvbmZpZ19mbHVlbnRiaXRfZmlsZW5hbWUgc3lzY29uZmlnX2ZsdWVudGJpdF9maWxlCgogICAgbG9jYWwgLXIgZmx1ZW50Yml0X3NlcnZpY2VfZmlsZW5hbWU9Jy9ldGMvc3lzdGVtZC9zeXN0ZW0vZmx1ZW50Yml0LnNlcnZpY2UnCgogICAgbG9jYWwgLXIgZmx1ZW50Yml0X3NlcnZpY2VfZmlsZT0iW1VuaXRdCkFmdGVyPW5ldHdvcmstb25saW5lLnRhcmdldApXYW50cz1uZXR3b3JrLW9ubGluZS50YXJnZXQKU3RhcnRMaW1pdEludGVydmFsU2VjPTAKCltTZXJ2aWNlXQpSZXN0YXJ0U2VjPTFzCkVudmlyb25tZW50RmlsZT0vZXRjL3N5c2NvbmZpZy9mbHVlbnRiaXQKRXhlY1N0YXJ0UHJlPS0vdXNyL2Jpbi9kb2NrZXIgcm0gLWYgJU4KRXhlY1N0YXJ0PS91c3IvYmluL2RvY2tlciBydW4gXAogIC0tc2VjdXJpdHktb3B0IGxhYmVsPWRpc2FibGUgXAogIC0tZW50cnlwb2ludCAvb3B0L3RkLWFnZW50LWJpdC9iaW4vdGQtYWdlbnQtYml0IFwKICAtLW5ldD1ob3N0IFwKICAtLWhvc3RuYW1lICVIIFwKICAtLW5hbWUgJU4gXAogIC0tcm0gXAogIC0tY2FwLWRyb3AgbmV0X3JhdyBcCiAgLXYgL2V0Yy9mbHVlbnRiaXQvZmx1ZW50Yml0LmNvbmY6L2V0Yy9mbHVlbnRiaXQvZmx1ZW50Yml0LmNvbmYgXAogIC12IC92YXIvbGliL2ZsdWVudDovdmFyL2xpYi9mbHVlbnQ6eiBcCiAgLXYgL3Zhci9sb2cvam91cm5hbDovdmFyL2xvZy9qb3VybmFsOnJvIFwKICAtdiAvZXRjL21hY2hpbmUtaWQ6L2V0Yy9tYWNoaW5lLWlkOnJvIFwKICAkRkxVRU5UQklUSU1BR0UgXAogIC1jIC9ldGMvZmx1ZW50Yml0L2ZsdWVudGJpdC5jb25mCgpFeGVjU3RvcD0vdXNyL2Jpbi9kb2NrZXIgc3RvcCAlTgpSZXN0YXJ0PWFsd2F5cwpSZXN0YXJ0U2VjPTUKU3RhcnRMaW1pdEludGVydmFsPTAKCltJbnN0YWxsXQpXYW50ZWRCeT1tdWx0aS11c2VyLnRhcmdldCIKCiAgICB3cml0ZV9maWxlIGZsdWVudGJpdF9jb25mX2ZpbGVuYW1lIGZsdWVudGJpdF9jb25mX2ZpbGUKfQoKIyBjb25maWd1cmVfY2VydHMKY29uZmlndXJlX2NlcnRzKCkgewogICAgbWtkaXIgL2V0Yy9hcm8tcnAKICAgIGJhc2U2NCAtZCA8PDwiJEFETUlOQVBJQ0FCVU5ETEUiID4vZXRjL2Fyby1ycC9hZG1pbi1jYS1idW5kbGUucGVtCiAgICBpZiBbWyAtbiAiJEFSTUFQSUNBQlVORExFIiBdXTsgdGhlbgogICAgYmFzZTY0IC1kIDw8PCIkQVJNQVBJQ0FCVU5ETEUiID4vZXRjL2Fyby1ycC9hcm0tY2EtYnVuZGxlLnBlbQogICAgZmkKICAgIGNob3duIC1SIDEwMDA6MTAwMCAvZXRjL2Fyby1ycAoKICAgICMgc2V0dGluZyBNT05JVE9SSU5HX0dDU19BVVRIX0lEX1RZUEU9QXV0aEtleVZhdWx0IHNlZW1zIHRvIGhhdmUgY2F1c2VkIG1kc2Qgbm90CiAgICAjIHRvIGhvbm91ciBTU0xfQ0VSVF9GSUxFIGFueSBtb3JlLCBoZWF2ZW4gb25seSBrbm93cyB3aHkuCiAgICBta2RpciAtcCAvdXNyL2xpYi9zc2wvY2VydHMKICAgIGNzcGxpdCAtZiAvdXNyL2xpYi9zc2wvY2VydHMvY2VydC0gLWIgJTAzZC5wZW0gL2V0Yy9wa2kvdGxzL2NlcnRzL2NhLWJ1bmRsZS5jcnQgL14kLzEgInsqfSIgPi9kZXYvbnVsbAogICAgY19yZWhhc2ggL3Vzci9saWIvc3NsL2NlcnRzCgojIHdlIGxlYXZlIGNsaWVudElkIGJsYW5rIGFzIGxvbmcgYXMgb25seSAxIG1hbmFnZWQgaWRlbnRpdHkgYXNzaWduZWQgdG8gdm1zcwojIGlmIHdlIGhhdmUgbW9yZSB0aGFuIDEsIHdlIHdpbGwgbmVlZCB0byBwb3B1bGF0ZSB3aXRoIGNsaWVudElkIHVzZWQgZm9yIG9mZi1ub2RlIHNjYW5uaW5nCiAgICBsb2NhbCAtciBub2Rlc2Nhbl9hZ2VudF9maWxlbmFtZT0iL2V0Yy9kZWZhdWx0L3ZzYS1ub2Rlc2Nhbi1hZ2VudC5jb25maWciCiAgICBsb2NhbCAtciBub2Rlc2Nhbl9hZ2VudF9maWxlPSJ7CiAgICBcIk5pY2VcIjogMTksCiAgICBcIlRpbWVvdXRcIjogMTA4MDAsCiAgICBcIkNsaWVudElkXCI6IFwiXCIsCiAgICBcIlRlbmFudElkXCI6ICRBWlVSRVNFQ1BBQ0tWU0FURU5BTlRJRCwKICAgIFwiUXVhbHlzU3RvcmVCYXNlVXJsXCI6ICRBWlVSRVNFQ1BBQ0tRVUFMWVNVUkwsCiAgICBcIlByb2Nlc3NUaW1lb3V0XCI6IDMwMCwKICAgIFwiQ29tbWFuZERlbGF5XCI6IDAKICB9IgoKICAgIHdyaXRlX2ZpbGUgbm9kZXNjYW5fYWdlbnRfZmlsZW5hbWUgbm9kZXNjYW5fYWdlbnRfZmlsZQp9CgojIGNvbmZpZ3VyZV9zZXJ2aWNlX21kbQpjb25maWd1cmVfc2VydmljZV9tZG0oKSB7CiAgICBsb2cgImNvbmZpZ3VyaW5nIG1kbSBzZXJ2aWNlIgoKICAgIGxvY2FsIC1yIHN5c2NvbmZpZ19tZG1fZmlsZW5hbWU9Ii9ldGMvc3lzY29uZmlnL21kbSIKICAgIGxvY2FsIC1yIHN5c2NvbmZpZ19tZG1fZmlsZT0iTURNRlJPTlRFTkRVUkw9JyRNRE1GUk9OVEVORFVSTCcKTURNSU1BR0U9JyRNRE1JTUFHRScKTURNU09VUkNFRU5WSVJPTk1FTlQ9JyRMT0NBVElPTicKTURNU09VUkNFUk9MRT1ycApNRE1TT1VSQ0VST0xFSU5TVEFOQ0U9XCIkKGhvc3RuYW1lKVwiIgoKICAgIHdyaXRlX2ZpbGUgc3lzY29uZmlnX21kbV9maWxlbmFtZSBzeXNjb25maWdfbWRtX2ZpbGUKCiAgICBta2RpciAtcCAvdmFyL2V0dwogICAgbG9jYWwgLXIgbWRtX3NlcnZpY2VfZmlsZW5hbWU9Ii9ldGMvc3lzdGVtZC9zeXN0ZW0vbWRtLnNlcnZpY2UiCiAgICBsb2NhbCAtciBtZG1fc2VydmljZV9maWxlPSJbVW5pdF0KQWZ0ZXI9bmV0d29yay1vbmxpbmUudGFyZ2V0CldhbnRzPW5ldHdvcmstb25saW5lLnRhcmdldAoKW1NlcnZpY2VdCkVudmlyb25tZW50RmlsZT0vZXRjL3N5c2NvbmZpZy9tZG0KRXhlY1N0YXJ0UHJlPS0vdXNyL2Jpbi9kb2NrZXIgcm0gLWYgJU4KRXhlY1N0YXJ0PS91c3IvYmluL2RvY2tlciBydW4gXAogIC0tZW50cnlwb2ludCAvdXNyL3NiaW4vTWV0cmljc0V4dGVuc2lvbiBcCiAgLS1ob3N0bmFtZSAlSCBcCiAgLS1uYW1lICVOIFwKICAtLXJtIFwKICAtLWNhcC1kcm9wIG5ldF9yYXcgXAogIC1tIDJnIFwKICAtdiAvZXRjL21kbS5wZW06L2V0Yy9tZG0ucGVtIFwKICAtdiAvdmFyL2V0dzovdmFyL2V0dzp6IFwKICAkTURNSU1BR0UgXAogIC1DZXJ0RmlsZSAvZXRjL21kbS5wZW0gXAogIC1Gcm9udEVuZFVybCAkTURNRlJPTlRFTkRVUkwgXAogIC1Mb2dnZXIgQ29uc29sZSBcCiAgLUxvZ0xldmVsIFdhcm5pbmcgXAogIC1Qcml2YXRlS2V5RmlsZSAvZXRjL21kbS5wZW0gXAogIC1Tb3VyY2VFbnZpcm9ubWVudCAkTURNU09VUkNFRU5WSVJPTk1FTlQgXAogIC1Tb3VyY2VSb2xlICRNRE1TT1VSQ0VST0xFIFwKICAtU291cmNlUm9sZUluc3RhbmNlICRNRE1TT1VSQ0VST0xFSU5TVEFOQ0UKRXhlY1N0b3A9L3Vzci9iaW4vZG9ja2VyIHN0b3AgJU4KUmVzdGFydD1hbHdheXMKUmVzdGFydFNlYz0xClN0YXJ0TGltaXRJbnRlcnZhbD0wCgpbSW5zdGFsbF0KV2FudGVkQnk9bXVsdGktdXNlci50YXJnZXQiCgogICAgd3JpdGVfZmlsZSBtZG1fc2VydmljZV9maWxlbmFtZSBtZG1fc2VydmljZV9maWxlCn0KCiMgY29uZmlndXJlX3RpbWVyc19tZG1fbWRzZApjb25maWd1cmVfdGltZXJzX21kbV9tZHNkKCkgewogICAgZm9yIHZhciBpbiAibWRzZCIgIm1kbSI7IGRvCiAgICAgICAgbG9jYWwgZG93bmxvYWRfY3JlZHNfc2VydmljZV9maWxlbmFtZT0iL2V0Yy9zeXN0ZW1kL3N5c3RlbS9kb3dubG9hZC0kdmFyLWNyZWRlbnRpYWxzLnNlcnZpY2UiCiAgICAgICAgbG9jYWwgZG93bmxvYWRfY3JlZHNfc2VydmljZV9maWxlPSJbVW5pdF0KRGVzY3JpcHRpb249UGVyaW9kaWMgJHZhciBjcmVkZW50aWFscyByZWZyZXNoCgpbU2VydmljZV0KVHlwZT1vbmVzaG90CkV4ZWNTdGFydD0vdXNyL2xvY2FsL2Jpbi9kb3dubG9hZC1jcmVkZW50aWFscy5zaCAkdmFyIgoKICAgICAgICB3cml0ZV9maWxlIGRvd25sb2FkX2NyZWRzX3NlcnZpY2VfZmlsZW5hbWUgZG93bmxvYWRfY3JlZHNfc2VydmljZV9maWxlCgogICAgICAgIGxvY2FsIGRvd25sb2FkX2NyZWRzX3RpbWVyX2ZpbGVuYW1lPSIvZXRjL3N5c3RlbWQvc3lzdGVtL2Rvd25sb2FkLSR2YXItY3JlZGVudGlhbHMudGltZXIiCiAgICAgICAgbG9jYWwgZG93bmxvYWRfY3JlZHNfdGltZXJfZmlsZT0iW1VuaXRdCkRlc2NyaXB0aW9uPVBlcmlvZGljICR2YXIgY3JlZGVudGlhbHMgcmVmcmVzaApBZnRlcj1uZXR3b3JrLW9ubGluZS50YXJnZXQKV2FudHM9bmV0d29yay1vbmxpbmUudGFyZ2V0CgpbVGltZXJdCk9uQm9vdFNlYz0wbWluCk9uQ2FsZW5kYXI9MC8xMjowMDowMApBY2N1cmFjeVNlYz01cwoKW0luc3RhbGxdCldhbnRlZEJ5PXRpbWVycy50YXJnZXQiCgogICAgICAgIHdyaXRlX2ZpbGUgZG93bmxvYWRfY3JlZHNfdGltZXJfZmlsZW5hbWUgZG93bmxvYWRfY3JlZHNfdGltZXJfZmlsZQogICAgZG9uZQoKICAgIGxvY2FsIC1yIGRvd25sb2FkX2NyZWRzX3NjcmlwdF9maWxlbmFtZT0iL3Vzci9sb2NhbC9iaW4vZG93bmxvYWQtY3JlZGVudGlhbHMuc2giCiAgICBsb2NhbCAtciBkb3dubG9hZF9jcmVkc19zY3JpcHRfZmlsZT0iIyEvYmluL2Jhc2gKc2V0IC1ldQoKQ09NUE9ORU5UPVwkMQplY2hvIFwiRG93bmxvYWQgXCRDT01QT05FTlQgY3JlZGVudGlhbHNcIgoKVEVNUF9ESVI9XCJcJChta3RlbXAgLWQpXCIKZXhwb3J0IEFaVVJFX0NPTkZJR19ESVI9XCJcJChta3RlbXAgLWQpXCIKCmVjaG8gXCJMb2dnaW5nIGludG8gQXp1cmUuLi5cIgpSRVRSSUVTPTMKd2hpbGUgW1sgXCRSRVRSSUVTIC1ndCAwIF1dOyBkbwogICAgaWYgYXogbG9naW4gLWkgLS1hbGxvdy1uby1zdWJzY3JpcHRpb25zCiAgICB0aGVuCiAgICAgICAgZWNobyBcImF6IGxvZ2luIHN1Y2Nlc3NmdWxcIgogICAgICAgIGJyZWFrCiAgICBlbHNlCiAgICAgICAgZWNobyBcImF6IGxvZ2luIGZhaWxlZC4gUmV0cnlpbmcuLi5cIgogICAgICAgIGxldCBSRVRSSUVTLT0xCiAgICAgICAgc2xlZXAgNQogICAgZmkKZG9uZQoKdHJhcCBcImNsZWFudXBcIiBFWElUCgpjbGVhbnVwKCkgewogIGF6IGxvZ291dAogIFtbIFwkVEVNUF9ESVIgPX4gL3RtcC8uKyBdXSAmJiBybSAtcmYgXCRURU1QX0RJUgogIFtbIFwkQVpVUkVfQ09ORklHX0RJUiA9fiAvdG1wLy4rIF1dICYmIHJtIC1yZiBcJEFaVVJFX0NPTkZJR19ESVIKfQoKaWYgW1sgXCRDT01QT05FTlQgPSBcIm1kbVwiIF1dOyB0aGVuCiAgQ1VSUkVOVF9DRVJUX0ZJTEU9XCIvZXRjL21kbS5wZW1cIgplbGlmIFtbIFwkQ09NUE9ORU5UXCA9IFwibWRzZFwiIF1dOyB0aGVuCiAgQ1VSUkVOVF9DRVJUX0ZJTEU9XCIvdmFyL2xpYi93YWFnZW50L01pY3Jvc29mdC5BenVyZS5LZXlWYXVsdC5TdG9yZS9tZHNkLnBlbVwiCmVsc2UKICBlY2hvIEludmFsaWQgdXNhZ2UgJiYgZXhpdCAxCmZpCgpTRUNSRVRfTkFNRT1cInJwLVwke0NPTVBPTkVOVH1cIgpORVdfQ0VSVF9GSUxFPVwiXCRURU1QX0RJUi9cJENPTVBPTkVOVC5wZW1cIgpmb3IgYXR0ZW1wdCBpbiB7MS4uNX07IGRvCiAgYXoga2V5dmF1bHQgXAogICAgc2VjcmV0IFwKICAgIGRvd25sb2FkIFwKICAgIC0tZmlsZSBcIlwkTkVXX0NFUlRfRklMRVwiIFwKICAgIC0taWQgXCJodHRwczovLyRLRVlWQVVMVFBSRUZJWC1zdmMuJEtFWVZBVUxURE5TU1VGRklYL3NlY3JldHMvXCRTRUNSRVRfTkFNRVwiIFwKICAgICYmIGJyZWFrCiAgaWYgW1sgXCRhdHRlbXB0IC1sdCA1IF1dOyB0aGVuIHNsZWVwIDEwOyBlbHNlIGV4aXQgMTsgZmkKZG9uZQoKaWYgWyAtZiBcJE5FV19DRVJUX0ZJTEUgXTsgdGhlbgogIGlmIFtbIFwkQ09NUE9ORU5UID0gXCJtZHNkXCIgXV07IHRoZW4KICAgIGNob3duIHN5c2xvZzpzeXNsb2cgXCRORVdfQ0VSVF9GSUxFCiAgZWxzZQogICAgc2VkIC1pIC1uZSAnMSwvRU5EIENFUlRJRklDQVRFLyBwJyBcJE5FV19DRVJUX0ZJTEUKICBmaQoKICBuZXdfY2VydF9zbj1cIlwkKG9wZW5zc2wgeDUwOSAtaW4gXCJcJE5FV19DRVJUX0ZJTEVcIiAtbm9vdXQgLXNlcmlhbCB8IGF3ayAtRj0gJ3twcmludCBcJDJ9JylcIgogIGN1cnJlbnRfY2VydF9zbj1cIlwkKG9wZW5zc2wgeDUwOSAtaW4gXCJcJENVUlJFTlRfQ0VSVF9GSUxFXCIgLW5vb3V0IC1zZXJpYWwgfCBhd2sgLUY9ICd7cHJpbnQgXCQyfScpXCIKICBpZiBbWyAhIC16IFwkbmV3X2NlcnRfc24gXV0gJiYgW1sgXCRuZXdfY2VydF9zbiAhPSBcIlwkY3VycmVudF9jZXJ0X3NuXCIgXV07IHRoZW4KICAgIGVjaG8gdXBkYXRpbmcgY2VydGlmaWNhdGUgZm9yIFwkQ09NUE9ORU5UCiAgICBjaG1vZCAwNjAwIFwkTkVXX0NFUlRfRklMRQogICAgbXYgXCRORVdfQ0VSVF9GSUxFIFwkQ1VSUkVOVF9DRVJUX0ZJTEUKICBmaQplbHNlCiAgZWNobyBGYWlsZWQgdG8gcmVmcmVzaCBjZXJ0aWZpY2F0ZSBmb3IgXCRDT01QT05FTlQgJiYgZXhpdCAxCmZpIgoKICAgIHdyaXRlX2ZpbGUgZG93bmxvYWRfY3JlZHNfc2NyaXB0X2ZpbGVuYW1lIGRvd25sb2FkX2NyZWRzX3NjcmlwdF9maWxlCgogICAgY2htb2QgdSt4IC91c3IvbG9jYWwvYmluL2Rvd25sb2FkLWNyZWRlbnRpYWxzLnNoCgogICAgc3lzdGVtY3RsIGVuYWJsZSBkb3dubG9hZC1tZHNkLWNyZWRlbnRpYWxzLnRpbWVyCiAgICBzeXN0ZW1jdGwgZW5hYmxlIGRvd25sb2FkLW1kbS1jcmVkZW50aWFscy50aW1lcgoKICAgIC91c3IvbG9jYWwvYmluL2Rvd25sb2FkLWNyZWRlbnRpYWxzLnNoIG1kc2QKICAgIC91c3IvbG9jYWwvYmluL2Rvd25sb2FkLWNyZWRlbnRpYWxzLnNoIG1kbQoKICAgIGxvY2FsIC1yIE1EU0RDRVJUSUZJQ0FURVNBTj0iJChvcGVuc3NsIHg1MDkgLWluIC92YXIvbGliL3dhYWdlbnQvTWljcm9zb2Z0LkF6dXJlLktleVZhdWx0LlN0b3JlL21kc2QucGVtIC1ub291dCAtc3ViamVjdCB8IHNlZCAtZSAncy8uKkNOID0gLy8nKSIKICAgIGxvY2FsIC1yIHdhdGNoX21kbV9jcmVkc19zZXJ2aWNlX2ZpbGVuYW1lPSIvZXRjL3N5c3RlbWQvc3lzdGVtL3dhdGNoLW1kbS1jcmVkZW50aWFscy5zZXJ2aWNlIgogICAgbG9jYWwgLXIgd2F0Y2hfbWRtX2NyZWRzX3NlcnZpY2VfZmlsZT0iW1VuaXRdCkRlc2NyaXB0aW9uPVdhdGNoIGZvciBjaGFuZ2VzIGluIG1kbS5wZW0gYW5kIHJlc3RhcnRzIHRoZSBtZG0gc2VydmljZQoKW1NlcnZpY2VdClR5cGU9b25lc2hvdApFeGVjU3RhcnQ9L3Vzci9iaW4vc3lzdGVtY3RsIHJlc3RhcnQgbWRtLnNlcnZpY2UKCltJbnN0YWxsXQpXYW50ZWRCeT1tdWx0aS11c2VyLnRhcmdldCIKCiAgICB3cml0ZV9maWxlIHdhdGNoX21kbV9jcmVkc19zZXJ2aWNlX2ZpbGVuYW1lIHdhdGNoX21kbV9jcmVkc19zZXJ2aWNlX2ZpbGUKCiAgICBsb2NhbCAtciB3YXRjaF9tZG1fY3JlZHNfcGF0aF9maWxlbmFtZT0nL2V0Yy9zeXN0ZW1kL3N5c3RlbS93YXRjaC1tZG0tY3JlZGVudGlhbHMucGF0aCcKICAgIGxvY2FsIC1yIHdhdGNoX21kbV9jcmVkc19wYXRoX2ZpbGU9J1tQYXRoXQpQYXRoTW9kaWZpZWQ9L2V0Yy9tZG0ucGVtCgpbSW5zdGFsbF0KV2FudGVkQnk9bXVsdGktdXNlci50YXJnZXQnCgogICAgd3JpdGVfZmlsZSB3YXRjaF9tZG1fY3JlZHNfcGF0aF9maWxlbmFtZSB3YXRjaF9tZG1fY3JlZHNfcGF0aF9maWxlCgogICAgbG9jYWwgLXIgd2F0Y2hfbWRtX2NyZWRzPSd3YXRjaC1tZG0tY3JlZGVudGlhbHMucGF0aCcKICAgIHN5c3RlbWN0bCBlbmFibGUgIiR3YXRjaF9tZG1fY3JlZHMiIHx8IGFib3J0ICJmYWlsZWQgdG8gZW5hYmxlICR3YXRjaF9tZG1fY3JlZHMiCiAgICBzeXN0ZW1jdGwgc3RhcnQgIiR3YXRjaF9tZG1fY3JlZHMiIHx8IGFib3J0ICJmYWlsZWQgdG8gc3RhcnQgJHdhdGNoX21kbV9jcmVkcyIKfQoKIyBjb25maWd1cmVfc2VydmljZV9hcm9fcnAKY29uZmlndXJlX3NlcnZpY2VfYXJvX3JwKCkgewogICAgbG9jYWwgLXIgYXJvX3JwX2NvbmZfZmlsZW5hbWU9Jy9ldGMvc3lzY29uZmlnL2Fyby1ycCcKICAgIGxvY2FsIC1yIGFyb19ycF9jb25mX2ZpbGU9IkFDUl9SRVNPVVJDRV9JRD0nJEFDUlJFU09VUkNFSUQnCkFETUlOX0FQSV9DTElFTlRfQ0VSVF9DT01NT05fTkFNRT0nJEFETUlOQVBJQ0xJRU5UQ0VSVENPTU1PTk5BTUUnCkFSTV9BUElfQ0xJRU5UX0NFUlRfQ09NTU9OX05BTUU9JyRBUk1BUElDTElFTlRDRVJUQ09NTU9OTkFNRScKQVpVUkVfQVJNX0NMSUVOVF9JRD0nJEFSTUNMSUVOVElEJwpBWlVSRV9GUF9DTElFTlRfSUQ9JyRGUENMSUVOVElEJwpBWlVSRV9GUF9TRVJWSUNFX1BSSU5DSVBBTF9JRD0nJEZQU0VSVklDRVBSSU5DSVBBTElEJwpCSUxMSU5HX0UyRV9TVE9SQUdFX0FDQ09VTlRfSUQ9JyRCSUxMSU5HRTJFU1RPUkFHRUFDQ09VTlRJRCcKQ0xVU1RFUl9NRE1fQUNDT1VOVD0nJENMVVNURVJNRE1BQ0NPVU5UJwpDTFVTVEVSX01ETV9OQU1FU1BBQ0U9UlAKQ0xVU1RFUl9NRFNEX0FDQ09VTlQ9JyRDTFVTVEVSTURTREFDQ09VTlQnCkNMVVNURVJfTURTRF9DT05GSUdfVkVSU0lPTj0nJENMVVNURVJNRFNEQ09ORklHVkVSU0lPTicKQ0xVU1RFUl9NRFNEX05BTUVTUEFDRT0nJENMVVNURVJNRFNETkFNRVNQQUNFJwpEQVRBQkFTRV9BQ0NPVU5UX05BTUU9JyREQVRBQkFTRUFDQ09VTlROQU1FJwpET01BSU5fTkFNRT0nJExPQ0FUSU9OLiRDTFVTVEVSUEFSRU5URE9NQUlOTkFNRScKR0FURVdBWV9ET01BSU5TPSckR0FURVdBWURPTUFJTlMnCkdBVEVXQVlfUkVTT1VSQ0VHUk9VUD0nJEdBVEVXQVlSRVNPVVJDRUdST1VQTkFNRScKS0VZVkFVTFRfUFJFRklYPSckS0VZVkFVTFRQUkVGSVgnCk1ETV9BQ0NPVU5UPSckUlBNRE1BQ0NPVU5UJwpNRE1fTkFNRVNQQUNFPVJQCk1EU0RfRU5WSVJPTk1FTlQ9JyRNRFNERU5WSVJPTk1FTlQnClJQX0ZFQVRVUkVTPSckUlBGRUFUVVJFUycKUlBJTUFHRT0nJFJQSU1BR0UnCkFST19JTlNUQUxMX1ZJQV9ISVZFPSckQ0xVU1RFUlNJTlNUQUxMVklBSElWRScKQVJPX0hJVkVfREVGQVVMVF9JTlNUQUxMRVJfUFVMTFNQRUM9JyRDTFVTVEVSREVGQVVMVElOU1RBTExFUlBVTExTUEVDJwpBUk9fQURPUFRfQllfSElWRT0nJENMVVNURVJTQURPUFRCWUhJVkUnClVTRV9DSEVDS0FDQ0VTUz0nJFVTRUNIRUNLQUNDRVNTJyIKCiAgICB3cml0ZV9maWxlIGFyb19ycF9jb25mX2ZpbGVuYW1lIGFyb19ycF9jb25mX2ZpbGUKCiAgICBsb2NhbCAtciBhcm9fcnBfc2VydmljZV9maWxlbmFtZT0nL2V0Yy9zeXN0ZW1kL3N5c3RlbS9hcm8tcnAuc2VydmljZScKICAgIGxvY2FsIC1yIGFyb19ycF9zZXJ2aWNlX2ZpbGU9IltVbml0XQpBZnRlcj1uZXR3b3JrLW9ubGluZS50YXJnZXQKV2FudHM9bmV0d29yay1vbmxpbmUudGFyZ2V0CgpbU2VydmljZV0KRW52aXJvbm1lbnRGaWxlPS9ldGMvc3lzY29uZmlnL2Fyby1ycApFeGVjU3RhcnRQcmU9LS91c3IvYmluL2RvY2tlciBybSAtZiAlTgpFeGVjU3RhcnQ9L3Vzci9iaW4vZG9ja2VyIHJ1biBcCiAgLS1ob3N0bmFtZSAlSCBcCiAgLS1uYW1lICVOIFwKICAtLXJtIFwKICAtLWNhcC1kcm9wIG5ldF9yYXcgXAogIC1lIEFDUl9SRVNPVVJDRV9JRCBcCiAgLWUgQURNSU5fQVBJX0NMSUVOVF9DRVJUX0NPTU1PTl9OQU1FIFwKICAtZSBBUk1fQVBJX0NMSUVOVF9DRVJUX0NPTU1PTl9OQU1FIFwKICAtZSBBWlVSRV9BUk1fQ0xJRU5UX0lEIFwKICAtZSBBWlVSRV9GUF9DTElFTlRfSUQgXAogIC1lIEJJTExJTkdfRTJFX1NUT1JBR0VfQUNDT1VOVF9JRCBcCiAgLWUgQ0xVU1RFUl9NRE1fQUNDT1VOVCBcCiAgLWUgQ0xVU1RFUl9NRE1fTkFNRVNQQUNFIFwKICAtZSBDTFVTVEVSX01EU0RfQUNDT1VOVCBcCiAgLWUgQ0xVU1RFUl9NRFNEX0NPTkZJR19WRVJTSU9OIFwKICAtZSBDTFVTVEVSX01EU0RfTkFNRVNQQUNFIFwKICAtZSBEQVRBQkFTRV9BQ0NPVU5UX05BTUUgXAogIC1lIERPTUFJTl9OQU1FIFwKICAtZSBHQVRFV0FZX0RPTUFJTlMgXAogIC1lIEdBVEVXQVlfUkVTT1VSQ0VHUk9VUCBcCiAgLWUgS0VZVkFVTFRfUFJFRklYIFwKICAtZSBNRE1fQUNDT1VOVCBcCiAgLWUgTURNX05BTUVTUEFDRSBcCiAgLWUgTURTRF9FTlZJUk9OTUVOVCBcCiAgLWUgUlBfRkVBVFVSRVMgXAogIC1lIEFST19JTlNUQUxMX1ZJQV9ISVZFIFwKICAtZSBBUk9fSElWRV9ERUZBVUxUX0lOU1RBTExFUl9QVUxMU1BFQyBcCiAgLWUgQVJPX0FET1BUX0JZX0hJVkUgXAogIC1lIFVTRV9DSEVDS0FDQ0VTUyBcCiAgLW0gMmcgXAogIC1wIDQ0Mzo4NDQzIFwKICAtdiAvZXRjL2Fyby1ycDovZXRjL2Fyby1ycCBcCiAgLXYgL3J1bi9zeXN0ZW1kL2pvdXJuYWw6L3J1bi9zeXN0ZW1kL2pvdXJuYWwgXAogIC12IC92YXIvZXR3Oi92YXIvZXR3OnogXAogICRSUElNQUdFIFwKICBycApFeGVjU3RvcD0vdXNyL2Jpbi9kb2NrZXIgc3RvcCAtdCAzNjAwICVOClRpbWVvdXRTdG9wU2VjPTM2MDAKUmVzdGFydD1hbHdheXMKUmVzdGFydFNlYz0xClN0YXJ0TGltaXRJbnRlcnZhbD0wCgpbSW5zdGFsbF0KV2FudGVkQnk9bXVsdGktdXNlci50YXJnZXQiCgogICAgd3JpdGVfZmlsZSBhcm9fcnBfc2VydmljZV9maWxlbmFtZSBhcm9fcnBfY29uZl9maWxlCn0KCiMgY29uZmlndXJlX3NlcnZpY2VfYXJvX2RidG9rZW4KY29uZmlndXJlX3NlcnZpY2VfYXJvX2RidG9rZW4oKSB7CiAgICBsb2NhbCAtciBhcm9fZGJ0b2tlbl9zZXJ2aWNlX2NvbmZfZmlsZW5hbWU9Jy9ldGMvc3lzY29uZmlnL2Fyby1kYnRva2VuJwogICAgbG9jYWwgLXIgYXJvX2RidG9rZW5fc2VydmljZV9jb25mX2ZpbGU9IkRBVEFCQVNFX0FDQ09VTlRfTkFNRT0nJERBVEFCQVNFQUNDT1VOVE5BTUUnCkFaVVJFX0RCVE9LRU5fQ0xJRU5UX0lEPSckREJUT0tFTkNMSUVOVElEJwpBWlVSRV9HQVRFV0FZX1NFUlZJQ0VfUFJJTkNJUEFMX0lEPSckR0FURVdBWVNFUlZJQ0VQUklOQ0lQQUxJRCcKS0VZVkFVTFRfUFJFRklYPSckS0VZVkFVTFRQUkVGSVgnCk1ETV9BQ0NPVU5UPSckUlBNRE1BQ0NPVU5UJwpNRE1fTkFNRVNQQUNFPURCVG9rZW4KUlBJTUFHRT0nJFJQSU1BR0UnIgoKICAgIHdyaXRlX2ZpbGUgYXJvX2RidG9rZW5fc2VydmljZV9jb25mX2ZpbGVuYW1lIGFyb19kYnRva2VuX3NlcnZpY2VfY29uZl9maWxlCgogICAgbG9jYWwgLXIgYXJvX2RidG9rZW5fc2VydmljZV9maWxlbmFtZT0nL2V0Yy9zeXN0ZW1kL3N5c3RlbS9hcm8tZGJ0b2tlbi5zZXJ2aWNlJwogICAgbG9jYWwgLXIgYXJvX2RidG9rZW5fc2VydmljZV9maWxlPSJbVW5pdF0KQWZ0ZXI9bmV0d29yay1vbmxpbmUudGFyZ2V0CldhbnRzPW5ldHdvcmstb25saW5lLnRhcmdldAoKW1NlcnZpY2VdCkVudmlyb25tZW50RmlsZT0vZXRjL3N5c2NvbmZpZy9hcm8tZGJ0b2tlbgpFeGVjU3RhcnRQcmU9LS91c3IvYmluL2RvY2tlciBybSAtZiAlTgpFeGVjU3RhcnQ9L3Vzci9iaW4vZG9ja2VyIHJ1biBcCiAgLS1ob3N0bmFtZSAlSCBcCiAgLS1uYW1lICVOIFwKICAtLXJtIFwKICAtLWNhcC1kcm9wIG5ldF9yYXcgXAogIC1lIEFaVVJFX0dBVEVXQVlfU0VSVklDRV9QUklOQ0lQQUxfSUQgXAogIC1lIERBVEFCQVNFX0FDQ09VTlRfTkFNRSBcCiAgLWUgQVpVUkVfREJUT0tFTl9DTElFTlRfSUQgXAogIC1lIEtFWVZBVUxUX1BSRUZJWCBcCiAgLWUgTURNX0FDQ09VTlQgXAogIC1lIE1ETV9OQU1FU1BBQ0UgXAogIC1tIDJnIFwKICAtcCA0NDU6ODQ0NSBcCiAgLXYgL3J1bi9zeXN0ZW1kL2pvdXJuYWw6L3J1bi9zeXN0ZW1kL2pvdXJuYWwgXAogIC12IC92YXIvZXR3Oi92YXIvZXR3OnogXAogICRSUElNQUdFIFwKICBkYnRva2VuCkV4ZWNTdG9wPS91c3IvYmluL2RvY2tlciBzdG9wIC10IDM2MDAgJU4KVGltZW91dFN0b3BTZWM9MzYwMApSZXN0YXJ0PWFsd2F5cwpSZXN0YXJ0U2VjPTEKU3RhcnRMaW1pdEludGVydmFsPTAKCltJbnN0YWxsXQpXYW50ZWRCeT1tdWx0aS11c2VyLnRhcmdldCIKCiAgICB3cml0ZV9maWxlIGFyb19kYnRva2VuX3NlcnZpY2VfZmlsZW5hbWUgYXJvX2RidG9rZW5fc2VydmljZV9maWxlCn0KCiMgY29uZmlndXJlX3NlcnZpY2VfYXJvX21vbml0b3IKY29uZmlndXJlX3NlcnZpY2VfYXJvX21vbml0b3IoKSB7CiAgICBsb2cgImNvbmZpZ3VyaW5nIGFyby1tb25pdG9yIHNlcnZpY2UiCiAgICAjIERPTUFJTl9OQU1FLCBDTFVTVEVSX01EU0RfQUNDT1VOVCwgQ0xVU1RFUl9NRFNEX0NPTkZJR19WRVJTSU9OLCBHQVRFV0FZX0RPTUFJTlMsIEdBVEVXQVlfUkVTT1VSQ0VHUk9VUCwgTURTRF9FTlZJUk9OTUVOVCBDTFVTVEVSX01EU0RfTkFNRVNQQUNFCiAgICAjIGFyZSBub3QgdXNlZCwgYnV0IGNhbid0IGVhc2lseSBiZSByZWZhY3RvcmVkIG91dC4gU2hvdWxkIGJlIHJldmlzaXRlZCBpbiB0aGUgZnV0dXJlLgogICAgbG9jYWwgLXIgYXJvX21vbml0b3Jfc2VydmljZV9jb25mX2ZpbGVuYW1lPScvZXRjL3N5c2NvbmZpZy9hcm8tbW9uaXRvcicKICAgIGxvY2FsIC1yIGFyb19tb25pdG9yX3NlcnZpY2VfY29uZl9maWxlPSJBWlVSRV9GUF9DTElFTlRfSUQ9JyRGUENMSUVOVElEJwpET01BSU5fTkFNRT0nJExPQ0FUSU9OLiRDTFVTVEVSUEFSRU5URE9NQUlOTkFNRScKQ0xVU1RFUl9NRFNEX0FDQ09VTlQ9JyRDTFVTVEVSTURTREFDQ09VTlQnCkNMVVNURVJfTURTRF9DT05GSUdfVkVSU0lPTj0nJENMVVNURVJNRFNEQ09ORklHVkVSU0lPTicKR0FURVdBWV9ET01BSU5TPSckR0FURVdBWURPTUFJTlMnCkdBVEVXQVlfUkVTT1VSQ0VHUk9VUD0nJEdBVEVXQVlSRVNPVVJDRUdST1VQTkFNRScKTURTRF9FTlZJUk9OTUVOVD0nJE1EU0RFTlZJUk9OTUVOVCcKQ0xVU1RFUl9NRFNEX05BTUVTUEFDRT0nJENMVVNURVJNRFNETkFNRVNQQUNFJwpDTFVTVEVSX01ETV9BQ0NPVU5UPSckQ0xVU1RFUk1ETUFDQ09VTlQnCkNMVVNURVJfTURNX05BTUVTUEFDRT1CQk0KREFUQUJBU0VfQUNDT1VOVF9OQU1FPSckREFUQUJBU0VBQ0NPVU5UTkFNRScKS0VZVkFVTFRfUFJFRklYPSckS0VZVkFVTFRQUkVGSVgnCk1ETV9BQ0NPVU5UPSckUlBNRE1BQ0NPVU5UJwpNRE1fTkFNRVNQQUNFPUJCTQpSUElNQUdFPSckUlBJTUFHRSciCgogICAgd3JpdGVfZmlsZSBhcm9fbW9uaXRvcl9zZXJ2aWNlX2NvbmZfZmlsZW5hbWUgYXJvX21vbml0b3Jfc2VydmljZV9jb25mX2ZpbGUKCiAgICBsb2NhbCAtciBhcm9fbW9uaXRvcl9zZXJ2aWNlX2ZpbGVuYW1lPScvZXRjL3N5c3RlbWQvc3lzdGVtL2Fyby1tb25pdG9yLnNlcnZpY2UnCiAgICBsb2NhbCAtciBhcm9fbW9uaXRvcl9zZXJ2aWNlX2ZpbGU9IltVbml0XQpBZnRlcj1uZXR3b3JrLW9ubGluZS50YXJnZXQKV2FudHM9bmV0d29yay1vbmxpbmUudGFyZ2V0CgpbU2VydmljZV0KRW52aXJvbm1lbnRGaWxlPS9ldGMvc3lzY29uZmlnL2Fyby1tb25pdG9yCkV4ZWNTdGFydFByZT0tL3Vzci9iaW4vZG9ja2VyIHJtIC1mICVOCkV4ZWNTdGFydD0vdXNyL2Jpbi9kb2NrZXIgcnVuIFwKICAtLWhvc3RuYW1lICVIIFwKICAtLW5hbWUgJU4gXAogIC0tcm0gXAogIC0tY2FwLWRyb3AgbmV0X3JhdyBcCiAgLWUgQVpVUkVfRlBfQ0xJRU5UX0lEIFwKICAtZSBET01BSU5fTkFNRSBcCiAgLWUgQ0xVU1RFUl9NRFNEX0FDQ09VTlQgXAogIC1lIENMVVNURVJfTURTRF9DT05GSUdfVkVSU0lPTiBcCiAgLWUgR0FURVdBWV9ET01BSU5TIFwKICAtZSBHQVRFV0FZX1JFU09VUkNFR1JPVVAgXAogIC1lIE1EU0RfRU5WSVJPTk1FTlQgXAogIC1lIENMVVNURVJfTURTRF9OQU1FU1BBQ0UgXAogIC1lIENMVVNURVJfTURNX0FDQ09VTlQgXAogIC1lIENMVVNURVJfTURNX05BTUVTUEFDRSBcCiAgLWUgREFUQUJBU0VfQUNDT1VOVF9OQU1FIFwKICAtZSBLRVlWQVVMVF9QUkVGSVggXAogIC1lIE1ETV9BQ0NPVU5UIFwKICAtZSBNRE1fTkFNRVNQQUNFIFwKICAtbSAyLjVnIFwKICAtdiAvcnVuL3N5c3RlbWQvam91cm5hbDovcnVuL3N5c3RlbWQvam91cm5hbCBcCiAgLXYgL3Zhci9ldHc6L3Zhci9ldHc6eiBcCiAgJFJQSU1BR0UgXAogIG1vbml0b3IKUmVzdGFydD1hbHdheXMKUmVzdGFydFNlYz0xClN0YXJ0TGltaXRJbnRlcnZhbD0wCgpbSW5zdGFsbF0KV2FudGVkQnk9bXVsdGktdXNlci50YXJnZXQiCgogICAgd3JpdGVfZmlsZSBhcm9fbW9uaXRvcl9zZXJ2aWNlX2ZpbGVuYW1lIGFyb19tb25pdG9yX3NlcnZpY2VfZmlsZQp9CgojIGNvbmZpZ3VyZV9zZXJ2aWNlX2Fyb19wb3J0YWwKY29uZmlndXJlX3NlcnZpY2VfYXJvX3BvcnRhbCgpIHsKICAgIGxvY2FsIC1yIGFyb19wb3J0YWxfc2VydmljZV9jb25mX2ZpbGVuYW1lPScvZXRjL3N5c2NvbmZpZy9hcm8tcG9ydGFsJwogICAgbG9jYWwgLXIgYXJvX3BvcnRhbF9zZXJ2aWNlX2NvbmZfZmlsZT0iQVpVUkVfUE9SVEFMX0FDQ0VTU19HUk9VUF9JRFM9JyRQT1JUQUxBQ0NFU1NHUk9VUElEUycKQVpVUkVfUE9SVEFMX0NMSUVOVF9JRD0nJFBPUlRBTENMSUVOVElEJwpBWlVSRV9QT1JUQUxfRUxFVkFURURfR1JPVVBfSURTPSckUE9SVEFMRUxFVkFURURHUk9VUElEUycKREFUQUJBU0VfQUNDT1VOVF9OQU1FPSckREFUQUJBU0VBQ0NPVU5UTkFNRScKS0VZVkFVTFRfUFJFRklYPSckS0VZVkFVTFRQUkVGSVgnCk1ETV9BQ0NPVU5UPSckUlBNRE1BQ0NPVU5UJwpNRE1fTkFNRVNQQUNFPVBvcnRhbApQT1JUQUxfSE9TVE5BTUU9JyRMT0NBVElPTi5hZG1pbi4kUlBQQVJFTlRET01BSU5OQU1FJwpSUElNQUdFPSckUlBJTUFHRSciCgogICAgd3JpdGVfZmlsZSBhcm9fcG9ydGFsX3NlcnZpY2VfY29uZl9maWxlbmFtZSBhcm9fcG9ydGFsX3NlcnZpY2VfY29uZl9maWxlCgogICAgbG9jYWwgLXIgYXJvX3BvcnRhbF9zZXJ2aWNlX2ZpbGVuYW1lPScvZXRjL3N5c3RlbWQvc3lzdGVtL2Fyby1wb3J0YWwuc2VydmljZScKICAgIGxvY2FsIC1yIGFyb19wb3J0YWxfc2VydmljZV9maWxlPSJbVW5pdF0KQWZ0ZXI9bmV0d29yay1vbmxpbmUudGFyZ2V0CldhbnRzPW5ldHdvcmstb25saW5lLnRhcmdldApTdGFydExpbWl0SW50ZXJ2YWw9MAoKW1NlcnZpY2VdCkVudmlyb25tZW50RmlsZT0vZXRjL3N5c2NvbmZpZy9hcm8tcG9ydGFsCkV4ZWNTdGFydFByZT0tL3Vzci9iaW4vZG9ja2VyIHJtIC1mICVOCkV4ZWNTdGFydD0vdXNyL2Jpbi9kb2NrZXIgcnVuIFwKICAtLWhvc3RuYW1lICVIIFwKICAtLW5hbWUgJU4gXAogIC0tcm0gXAogIC0tY2FwLWRyb3AgbmV0X3JhdyBcCiAgLWUgQVpVUkVfUE9SVEFMX0FDQ0VTU19HUk9VUF9JRFMgXAogIC1lIEFaVVJFX1BPUlRBTF9DTElFTlRfSUQgXAogIC1lIEFaVVJFX1BPUlRBTF9FTEVWQVRFRF9HUk9VUF9JRFMgXAogIC1lIERBVEFCQVNFX0FDQ09VTlRfTkFNRSBcCiAgLWUgS0VZVkFVTFRfUFJFRklYIFwKICAtZSBNRE1fQUNDT1VOVCBcCiAgLWUgTURNX05BTUVTUEFDRSBcCiAgLWUgUE9SVEFMX0hPU1ROQU1FIFwKICAtbSAyZyBcCiAgLXAgNDQ0Ojg0NDQgXAogIC1wIDIyMjI6MjIyMiBcCiAgLXYgL3J1bi9zeXN0ZW1kL2pvdXJuYWw6L3J1bi9zeXN0ZW1kL2pvdXJuYWwgXAogIC12IC92YXIvZXR3Oi92YXIvZXR3OnogXAogICRSUElNQUdFIFwKICBwb3J0YWwKUmVzdGFydD1hbHdheXMKUmVzdGFydFNlYz0xCgpbSW5zdGFsbF0KV2FudGVkQnk9bXVsdGktdXNlci50YXJnZXQiCgogICAgd3JpdGVfZmlsZSBhcm9fcG9ydGFsX3NlcnZpY2VfY29uZl9maWxlbmFtZSBhcm9fcG9ydGFsX3NlcnZpY2VfY29uZl9maWxlCn0KCiMgY29uZmlndXJlX3NlcnZpY2VfbWRzZApjb25maWd1cmVfc2VydmljZV9tZHNkKCkgewogICAgbG9jYWwgLXIgbWRzZF9zZXJ2aWNlX2Rpcj0iL2V0Yy9zeXN0ZW1kL3N5c3RlbS9tZHNkLnNlcnZpY2UuZCIKICAgIG1rZGlyICIkbWRzZF9zZXJ2aWNlX2RpciIKCiAgICBsb2NhbCAtciBtZHNkX292ZXJyaWRlX2NvbmZfZmlsZW5hbWU9IiRtZHNkX3NlcnZpY2VfZGlyL292ZXJyaWRlLmNvbmYiCiAgICBsb2NhbCAtciBtZHNkX292ZXJyaWRlX2NvbmZfZmlsZT0iW1VuaXRdCkFmdGVyPW5ldHdvcmstb25saW5lLnRhcmdldCIKCiAgICB3cml0ZV9maWxlIG1kc2Rfb3ZlcnJpZGVfY29uZl9maWxlbmFtZSBtZHNkX292ZXJyaWRlX2NvbmZfZmlsZQoKICAgIGxvY2FsIC1yIGRlZmF1bHRfbWRzZF9maWxlbmFtZT0iL2V0Yy9kZWZhdWx0L21kc2QiCiAgICBsb2NhbCAtciBkZWZhdWx0X21kc2RfZmlsZT0iTURTRF9ST0xFX1BSRUZJWD0vdmFyL3J1bi9tZHNkL2RlZmF1bHQKTURTRF9PUFRJT05TPVwiLUEgLWQgLXIgXCRNRFNEX1JPTEVfUFJFRklYXCIKCmV4cG9ydCBNT05JVE9SSU5HX0dDU19FTlZJUk9OTUVOVD0nJE1EU0RFTlZJUk9OTUVOVCcKZXhwb3J0IE1PTklUT1JJTkdfR0NTX0FDQ09VTlQ9JyRSUE1EU0RBQ0NPVU5UJwpleHBvcnQgTU9OSVRPUklOR19HQ1NfUkVHSU9OPSckTE9DQVRJT04nCmV4cG9ydCBNT05JVE9SSU5HX0dDU19BVVRIX0lEX1RZUEU9QXV0aEtleVZhdWx0CmV4cG9ydCBNT05JVE9SSU5HX0dDU19BVVRIX0lEPSckTURTRENFUlRJRklDQVRFU0FOJwpleHBvcnQgTU9OSVRPUklOR19HQ1NfTkFNRVNQQUNFPSckUlBNRFNETkFNRVNQQUNFJwpleHBvcnQgTU9OSVRPUklOR19DT05GSUdfVkVSU0lPTj0nJFJQTURTRENPTkZJR1ZFUlNJT04nCmV4cG9ydCBNT05JVE9SSU5HX1VTRV9HRU5FVkFfQ09ORklHX1NFUlZJQ0U9dHJ1ZQoKZXhwb3J0IE1PTklUT1JJTkdfVEVOQU5UPSckTE9DQVRJT04nCmV4cG9ydCBNT05JVE9SSU5HX1JPTEU9cnAKZXhwb3J0IE1PTklUT1JJTkdfUk9MRV9JTlNUQU5DRT1cIiQoaG9zdG5hbWUpXCIKCmV4cG9ydCBNRFNEX01TR1BBQ0tfU09SVF9DT0xVTU5TPTFcIiIKCiAgICB3cml0ZV9maWxlIGRlZmF1bHRfbWRzZF9maWxlbmFtZSBkZWZhdWx0X21kc2RfZmlsZQoKfQoKIyBydW5fYXpzZWNkX2NvbmZpZ19zY2FuCnJ1bl9henNlY2RfY29uZmlnX3NjYW4oKSB7CiAgICBsb2NhbCAtYXIgY29uZmlncz0oCiAgICAgICAgImJhc2VsaW5lIgogICAgICAgICJjbGFtYXYiCiAgICAgICAgInNvZnR3YXJlIgogICAgKQoKICAgIGxvZyAiU2Nhbm5pbmcgY29uZmlndXJhdGlvbiBmaWxlcyAke2NvbmZpZ3NbKl19IgogICAgIyBzaGVsbGNoZWNrIGRpc2FibGU9U0MyMDY4CiAgICBmb3Igc2NhbiBpbiAke2NvbmZpZ3NbQF19OyBkbwogICAgICAgIGxvZyAiU2Nhbm5pbmcgY29uZmlnIGZpbGUgJHNjYW4gbm93IgogICAgICAgIC91c3IvbG9jYWwvYmluL2F6c2VjZCBjb25maWcgLXMgIiRzY2FuIiAtZCBQMUQKICAgIGRvbmUKfQoKIyB3cml0ZV9maWxlCiMgQXJncwojIDEpIGZpbGVuYW1lIC0gc3RyaW5nCiMgMikgZmlsZV9jb250ZW50cyAtIHN0cmluZwojIDMpIGNsb2JiZXIgLSBib29sZWFuOyBvcHRpb25hbCAtIGRlZmF1bHRzIHRvIGZhbHNlCndyaXRlX2ZpbGUoKSB7CiAgICBsb2NhbCAtbiBmaWxlbmFtZT0iJDEiCiAgICBsb2NhbCAtbiBmaWxlX2NvbnRlbnRzPSIkMiIKICAgIGxvY2FsIC1yIGNsb2JiZXI9IiR7MzotZmFsc2V9IgoKICAgIGlmICRjbG9iYmVyOyB0aGVuCiAgICAgICAgbG9nICJPdmVyd3JpdGluZyBmaWxlICRmaWxlbmFtZSIKICAgICAgICBlY2hvICIkZmlsZV9jb250ZW50cyIgPiAiJGZpbGVuYW1lIgogICAgZWxzZQogICAgICAgIGxvZyAiQXBwZW5kaW5nIHRvICRmaWxlbmFtZSIKICAgICAgICBlY2hvICIkZmlsZV9jb250ZW50cyIgPj4gIiRmaWxlbmFtZSIKICAgIGZpCn0KCiMgcmVib290X3ZtIHJlc3RvcmVzIGFsbCBzZWxpbnV4IGZpbGUgY29udGV4dHMsIHdhaXRzIDMwIHNlY29uZHMgdGhlbiByZWJvb3RzCnJlYm9vdF92bSgpIHsKICAgIGNvbmZpZ3VyZV9zZWxpbnV4ICJ0cnVlIgogICAgKHNsZWVwIDMwICYmIGxvZyAicmVib290aW5nIHZtIG5vdyI7IHJlYm9vdCkgJgp9CgojIGxvZyBpcyBhIHdyYXBwZXIgZm9yIGVjaG8gdGhhdCBpbmNsdWRlcyB0aGUgZnVuY3Rpb24gbmFtZQpsb2coKSB7CiAgICBsb2NhbCAtciBtc2c9IiR7MTotImxvZyBtZXNzYWdlIGlzIGVtcHR5In0iCiAgICBsb2NhbCAtciBzdGFja19sZXZlbD0iJHsyOi0xfSIKICAgIGVjaG8gIiR7RlVOQ05BTUVbJHtzdGFja19sZXZlbH1dfTogJHttc2d9Igp9CgojIGFib3J0IGlzIGEgd3JhcHBlciBmb3IgbG9nIHRoYXQgZXhpdHMgd2l0aCBhbiBlcnJvciBjb2RlCmFib3J0KCkgewogICAgbG9jYWwgLXJpIG9yaWdpbl9zdGFja2xldmVsPTIKICAgIGxvZyAiJHsxfSIgIiRvcmlnaW5fc3RhY2tsZXZlbCIKICAgIGV4aXQgMQp9CgpleHBvcnQgQVpVUkVfQ0xPVURfTkFNRT0iJHtBWlVSRUNMT1VETkFNRTo/IkZhaWxlZCB0byBjYXJyeSBvdmVyIHZhcmlhYmxlcyJ9IgoKbWFpbgo=')))]" } } } diff --git a/pkg/deploy/generator/scripts/gatewayVMSS.sh b/pkg/deploy/generator/scripts/gatewayVMSS.sh index 4034eed3675..613adc8d5e3 100644 --- a/pkg/deploy/generator/scripts/gatewayVMSS.sh +++ b/pkg/deploy/generator/scripts/gatewayVMSS.sh @@ -148,7 +148,8 @@ mkdir -p /etc/containers/ touch /etc/containers/nodocker mkdir -p /root/.docker -REGISTRY_AUTH_FILE=/root/.docker/config.json az acr login --name "$(sed -e 's|.*/||' <<<"$ACRRESOURCEID")" +REGISTRY_AUTH_FILE="/root/.docker/config.json" +az acr login --name "$(sed -e 's|.*/||' <<<"$ACRRESOURCEID")" MDMIMAGE="${RPIMAGE%%/*}/${MDMIMAGE##*/}" docker pull "$MDMIMAGE" diff --git a/pkg/deploy/generator/scripts/rpVMSS.sh b/pkg/deploy/generator/scripts/rpVMSS.sh index 0677589931f..a2704b10406 100644 --- a/pkg/deploy/generator/scripts/rpVMSS.sh +++ b/pkg/deploy/generator/scripts/rpVMSS.sh @@ -1,7 +1,7 @@ #!/bin/bash set -o errexit \ - -o nounset \ + -o nounset trap 'catch' ERR @@ -11,9 +11,10 @@ main() { configure_disk_partitions configure_logrotate configure_selinux - journal_dir="/var/log/journal" - mkdir -p "$journal_dir" + + mkdir -p /var/log/journal mkdir -p /var/lib/waagent/Microsoft.Azure.KeyVault.Store + configure_firewalld_rules pull_container_images configure_system_services @@ -134,10 +135,8 @@ configure_disk_partitions() { # configure_logrotate clobbers /etc/logrotate.conf configure_logrotate() { - local logrotate_conf_file="/etc/logrotate.conf" - log "Writing over $logrotate_conf_file" -cat >"$logrotate_conf_file" <<'EOF' -# see "man logrotate" for details + local -r logrotate_conf_filename='/etc/logrotate.conf' + local -r logrotate_conf_file='# see "man logrotate" for details # rotate log files weekly weekly @@ -156,7 +155,7 @@ compress # RPM packages drop log rotation information into this directory include /etc/logrotate.d -# no packages own wtmp and btmp -- we'll rotate them here +# no packages own wtmp and btmp -- we will rotate them here /var/log/wtmp { monthly create 0664 root utmp @@ -169,16 +168,15 @@ include /etc/logrotate.d monthly create 0600 root utmp rotate 1 -} -EOF +}' + + write_file logrotate_conf_filename logrotate_conf_file true } # create_azure_rpm_repos creates /etc/yum.repos.d/azure.repo repository file create_azure_rpm_repos() { - local azure_repo_file="/etc/yum.repos.d/azure.repo" - log "Writing $azure_repo_file" -cat >"$azure_repo_file" <<'EOF' -[azure-cli] + local -r azure_repo_filename='/etc/yum.repos.d/azure.repo' + local -r azure_repo_file='[azure-cli] name=azure-cli baseurl=https://packages.microsoft.com/yumrepos/azure-cli enabled=yes @@ -188,8 +186,9 @@ gpgcheck=yes name=azurecore baseurl=https://packages.microsoft.com/yumrepos/azurecore enabled=yes -gpgcheck=no -EOF +gpgcheck=no' + + write_file azure_repo_filename azure_repo_file } # configure_selinux @@ -215,11 +214,11 @@ cat >"$diable_accept_ra_conf" <<'EOF' net.ipv6.conf.all.accept_ra=0 EOF - local -r disable_core="$prefix/01-disable-core.conf" - log "Writing $disable_core" -cat >"$disable_core" <<'EOF' -kernel.core_pattern = |/bin/true -EOF + local -r disable_core_filename="$prefix/01-disable-core.conf" + local -r disable_core_file="kernel.core_pattern = |/bin/true + " + write_file disable_core_filename disable_core_file + sysctl --system enable_ports=( @@ -248,7 +247,9 @@ pull_container_images() { touch /etc/containers/nodocker mkdir -p /root/.docker - REGISTRY_AUTH_FILE=/root/.docker/config.json az acr login --name "$(sed -e 's|.*/||' <<<"$ACRRESOURCEID")" + local -r REGISTRY_AUTH_FILE="/root/.docker/config.json" + + az acr login --name "$(sed -e 's|.*/||' <<<"$ACRRESOURCEID")" MDMIMAGE="${RPIMAGE%%/*}/${MDMIMAGE##*/}" docker pull "$MDMIMAGE" @@ -307,12 +308,12 @@ configure_service_fluentbit() { mkdir -p /etc/fluentbit/ mkdir -p /var/lib/fluent -cat >/etc/fluentbit/fluentbit.conf <<'EOF' -[INPUT] - Name systemd - Tag journald - Systemd_Filter _COMM=aro - DB /var/lib/fluent/journaldb + local -r fluentbit_conf_filename='/etc/fluentbit/fluentbit.conf' + local -r fluentbit_conf_file="[INPUT] +Name systemd +Tag journald +Systemd_Filter _COMM=aro +DB /var/lib/fluent/journaldb [FILTER] Name modify @@ -340,17 +341,18 @@ cat >/etc/fluentbit/fluentbit.conf <<'EOF' [OUTPUT] Name forward Match * - Port 29230 -EOF + Port 29230" + + write_file fluentbit_conf_filename fluentbit_conf_file + + local -r sysconfig_fluentbit_filename='/etc/sysconfig/fluentbit' + local -r sysconfig_fluentbit_file="FLUENTBITIMAGE=$FLUENTBITIMAGE" + + write_file sysconfig_fluentbit_filename sysconfig_fluentbit_file - local -r sysconfig_fluentbit="/etc/sysconfig/fluentbit" - log "Writing value FLUENTBITIMAGE=$FLUENTBITIMAGE to $sysconfig_fluentbit" - echo "FLUENTBITIMAGE=$FLUENTBITIMAGE" >"$sysconfig_fluentbit" + local -r fluentbit_service_filename='/etc/systemd/system/fluentbit.service' - fluentbit_service_file="/etc/systemd/system/fluentbit.service" - log "Writing $fluentbit_service_file now" -cat >"$fluentbit_service_file" <<'EOF' -[Unit] + local -r fluentbit_service_file="[Unit] After=network-online.target Wants=network-online.target StartLimitIntervalSec=0 @@ -380,8 +382,9 @@ RestartSec=5 StartLimitInterval=0 [Install] -WantedBy=multi-user.target -EOF +WantedBy=multi-user.target" + + write_file fluentbit_conf_filename fluentbit_conf_file } # configure_certs @@ -396,45 +399,41 @@ configure_certs() { # setting MONITORING_GCS_AUTH_ID_TYPE=AuthKeyVault seems to have caused mdsd not # to honour SSL_CERT_FILE any more, heaven only knows why. mkdir -p /usr/lib/ssl/certs - csplit -f /usr/lib/ssl/certs/cert- -b %03d.pem /etc/pki/tls/certs/ca-bundle.crt /^$/1 {*} >/dev/null + csplit -f /usr/lib/ssl/certs/cert- -b %03d.pem /etc/pki/tls/certs/ca-bundle.crt /^$/1 "{*}" >/dev/null c_rehash /usr/lib/ssl/certs # we leave clientId blank as long as only 1 managed identity assigned to vmss # if we have more than 1, we will need to populate with clientId used for off-node scanning - nodescan_agent_file="/etc/default/vsa-nodescan-agent.config" - log "Writing $nodescan_agent_file" -cat >"$nodescan_agent_file" <"$sysconfig_mdm_file" <"$mdm_service_file"<<'EOF' -[Unit] + local -r mdm_service_filename="/etc/systemd/system/mdm.service" + local -r mdm_service_file="[Unit] After=network-online.target Wants=network-online.target @@ -465,28 +464,26 @@ RestartSec=1 StartLimitInterval=0 [Install] -WantedBy=multi-user.target -EOF +WantedBy=multi-user.target" + + write_file mdm_service_filename mdm_service_file } # configure_timers_mdm_mdsd configure_timers_mdm_mdsd() { for var in "mdsd" "mdm"; do - download_creds_service_file="/etc/systemd/system/download-$var-credentials.service" - log "Writing $download_creds_service_file" -cat >"$download_creds_service_file" <"$download_creds_timer_file"<"$download_creds_script_file" <"$watch_mdm_creds_service_file" <"$watch_mdm_creds_path_file" <"$arp_rp_config_file"<"$aro_rp_service_file" <<'EOF' -[Unit] + local -r aro_rp_service_filename='/etc/systemd/system/aro-rp.service' + local -r aro_rp_service_file="[Unit] After=network-online.target Wants=network-online.target @@ -694,28 +690,26 @@ RestartSec=1 StartLimitInterval=0 [Install] -WantedBy=multi-user.target -EOF +WantedBy=multi-user.target" + + write_file aro_rp_service_filename aro_rp_conf_file } # configure_service_aro_dbtoken configure_service_aro_dbtoken() { - local -r aro_dbtoken_service_config_file="/etc/sysconfig/aro-dbtoken" - log "Writing $aro_dbtoken_service_file" -cat >"$aro_dbtoken_service_file" <"$aro_dbtoken_service_config_file" <<'EOF' -[Unit] + local -r aro_dbtoken_service_filename='/etc/systemd/system/aro-dbtoken.service' + local -r aro_dbtoken_service_file="[Unit] After=network-online.target Wants=network-online.target @@ -746,18 +740,18 @@ RestartSec=1 StartLimitInterval=0 [Install] -WantedBy=multi-user.target -EOF +WantedBy=multi-user.target" + + write_file aro_dbtoken_service_filename aro_dbtoken_service_file } # configure_service_aro_monitor configure_service_aro_monitor() { - local -r aro_monitor_service_config="/etc/sysconfig/aro-monitor" log "configuring aro-monitor service" -# DOMAIN_NAME, CLUSTER_MDSD_ACCOUNT, CLUSTER_MDSD_CONFIG_VERSION, GATEWAY_DOMAINS, GATEWAY_RESOURCEGROUP, MDSD_ENVIRONMENT CLUSTER_MDSD_NAMESPACE -# are not used, but can't easily be refactored out. Should be revisited in the future. -cat >"$aro_monitor_service_config" <"$aro_monitor_service_file" <<'EOF' -[Unit] + local -r aro_monitor_service_filename='/etc/systemd/system/aro-monitor.service' + local -r aro_monitor_service_file="[Unit] After=network-online.target Wants=network-online.target @@ -813,16 +806,15 @@ RestartSec=1 StartLimitInterval=0 [Install] -WantedBy=multi-user.target -EOF +WantedBy=multi-user.target" + + write_file aro_monitor_service_filename aro_monitor_service_file } # configure_service_aro_portal configure_service_aro_portal() { - local -r aro_portal_service_config="/etc/sysconfig/aro-portal" - log "Writing $aro_portal_service_config" -cat >"$aro_portal_service_config" <"$aro_portal_service_file" <<'EOF' -[Unit] + write_file aro_portal_service_conf_filename aro_portal_service_conf_file + + local -r aro_portal_service_filename='/etc/systemd/system/aro-portal.service' + local -r aro_portal_service_file="[Unit] After=network-online.target Wants=network-online.target StartLimitInterval=0 @@ -868,27 +859,25 @@ Restart=always RestartSec=1 [Install] -WantedBy=multi-user.target -EOF +WantedBy=multi-user.target" + + write_file aro_portal_service_conf_filename aro_portal_service_conf_file } # configure_service_mdsd configure_service_mdsd() { local -r mdsd_service_dir="/etc/systemd/system/mdsd.service.d" - log "Creating $mdsd_service_dir" mkdir "$mdsd_service_dir" - local -r mdsd_override_conf="$mdsd_service_dir/override.conf" - log "Writing $mdsd_override_conf" -cat >"$mdsd_override_conf" <<'EOF' -[Unit] -After=network-online.target -EOF - default_mdsd_file="/etc/default/mdsd" - log "Writing $default_mdsd_file" -cat >"$default_mdsd_file" < "$filename" + else + log "Appending to $filename" + echo "$file_contents" >> "$filename" + fi +} + # reboot_vm restores all selinux file contexts, waits 30 seconds then reboots reboot_vm() { configure_selinux "true" From 1e35003594dfdafba999fbb614af6b2bd3ef5419 Mon Sep 17 00:00:00 2001 From: Steven Fairchild Date: Thu, 11 Apr 2024 14:39:53 -0400 Subject: [PATCH 05/38] move packages to install and rpm keys to import into arrays This will make adding new packages and keys easier --- pkg/deploy/generator/scripts/rpVMSS.sh | 53 +++++++++++++++----------- 1 file changed, 31 insertions(+), 22 deletions(-) diff --git a/pkg/deploy/generator/scripts/rpVMSS.sh b/pkg/deploy/generator/scripts/rpVMSS.sh index a2704b10406..45c11634ad5 100644 --- a/pkg/deploy/generator/scripts/rpVMSS.sh +++ b/pkg/deploy/generator/scripts/rpVMSS.sh @@ -58,8 +58,8 @@ configure_rhui_repo() { # dnf_update_pkgs dnf_update_pkgs() { - log "running dnf update" for attempt in {1..5}; do + log "running dnf update attempt #${attempt}" dnf -y \ -x WALinuxAgent \ -x WALinuxAgent-udev \ @@ -68,47 +68,56 @@ dnf_update_pkgs() { if [[ ${attempt} -lt 5 ]]; then sleep 10 else - return 1 + abort "Failed to update packages after ${attempt} attempts" fi done } # dnf_install_pkgs dnf_install_pkgs() { - log "importing rpm repositories" - rpm --import https://dl.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-8 - rpm --import https://packages.microsoft.com/keys/microsoft.asc + local -ra repo_keys=( + https://dl.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-8 + https://packages.microsoft.com/keys/microsoft.asc + ) + # shellcheck disable=SC2068 for attempt in {1..5}; do - dnf -y \ - install https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm \ - && break + for key in ${repo_keys[@]}; do + log "importing rpm repository key $key attempt #$attempt" + rpm --import "$key" + done if [[ ${attempt} -lt 5 ]]; then sleep 10 else - return 1 + abort "Failed to import rpm repository key $key after $attempt attempts" fi done + local -ra install_pkgs=( + install + clamav + azsec-clamav + azsec-monitor + azure-cli + azure-mdsd + azure-security + podman + podman-docker + openssl-perl + # hack - we are installing python3 on hosts due to an issue with Azure Linux Extensions https://github.com/Azure/azure-linux-extensions/pull/1505 + python3 + https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm + ) + for attempt in {1..5}; do + log "Installing packages ${install_pkgs[*]} attempt #$attempt" dnf -y \ - install \ - clamav \ - azsec-clamav \ - azsec-monitor \ - azure-cli \ - azure-mdsd \ - azure-security \ - podman \ - podman-docker \ - openssl-perl \ - python3 \ + "${install_pkgs[@]}" \ && break - # hack - we are installing python3 on hosts due to an issue with Azure Linux Extensions https://github.com/Azure/azure-linux-extensions/pull/1505 if [[ ${attempt} -lt 5 ]]; then sleep 10 else - abort "failed to install required packages" + abort "Failed to install packages ${install_pkgs[*]} after $attempt attempts" fi done } From eb62848828bd95874737673b41687b9f61a3e607 Mon Sep 17 00:00:00 2001 From: Steven Fairchild Date: Thu, 11 Apr 2024 15:50:31 -0400 Subject: [PATCH 06/38] Add retry loop for rpm repo key imports, remove erroneous package from install_pkgs array --- pkg/deploy/generator/scripts/rpVMSS.sh | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/pkg/deploy/generator/scripts/rpVMSS.sh b/pkg/deploy/generator/scripts/rpVMSS.sh index 45c11634ad5..8eaecbb8d69 100644 --- a/pkg/deploy/generator/scripts/rpVMSS.sh +++ b/pkg/deploy/generator/scripts/rpVMSS.sh @@ -84,7 +84,10 @@ dnf_install_pkgs() { for attempt in {1..5}; do for key in ${repo_keys[@]}; do log "importing rpm repository key $key attempt #$attempt" - rpm --import "$key" + rpm --import \ + -v \ + "$key" \ + && break done if [[ ${attempt} -lt 5 ]]; then sleep 10 @@ -94,7 +97,6 @@ dnf_install_pkgs() { done local -ra install_pkgs=( - install clamav azsec-clamav azsec-monitor @@ -111,7 +113,8 @@ dnf_install_pkgs() { for attempt in {1..5}; do log "Installing packages ${install_pkgs[*]} attempt #$attempt" - dnf -y \ + dnf install \ + -y \ "${install_pkgs[@]}" \ && break if [[ ${attempt} -lt 5 ]]; then From 104bb2ec980861f9126a23d9b4234b13d69c1835 Mon Sep 17 00:00:00 2001 From: Steven Fairchild Date: Thu, 11 Apr 2024 16:40:20 -0400 Subject: [PATCH 07/38] Pass dnf packages and rpm keys to function calls via nameref to allow reuse Editing the packages and keys passed will allow for easier modification later. This also allows for function reuse. --- pkg/deploy/generator/scripts/rpVMSS.sh | 132 ++++++++++++++----------- 1 file changed, 74 insertions(+), 58 deletions(-) diff --git a/pkg/deploy/generator/scripts/rpVMSS.sh b/pkg/deploy/generator/scripts/rpVMSS.sh index 8eaecbb8d69..c08656c2995 100644 --- a/pkg/deploy/generator/scripts/rpVMSS.sh +++ b/pkg/deploy/generator/scripts/rpVMSS.sh @@ -35,7 +35,34 @@ configure_and_install_dnf_pkgs_repos() { configure_rhui_repo create_azure_rpm_repos dnf_update_pkgs - dnf_install_pkgs + + local -ra rpm_keys=( + https://dl.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-8 + https://packages.microsoft.com/keys/microsoft.asc + ) + + rpm_import_keys rpm_keys + + local -ra repo_rpm_pkgs=( + https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm + ) + + local -ra install_pkgs=( + clamav + azsec-clamav + azsec-monitor + azure-cli + azure-mdsd + azure-security + podman + podman-docker + openssl-perl + # hack - we are installing python3 on hosts due to an issue with Azure Linux Extensions https://github.com/Azure/azure-linux-extensions/pull/1505 + python3 + ) + + dnf_install_pkgs repo_rpm_pkgs + dnf_install_pkgs install_pkgs } # configure_rhui_repo @@ -75,54 +102,43 @@ dnf_update_pkgs() { # dnf_install_pkgs dnf_install_pkgs() { - local -ra repo_keys=( - https://dl.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-8 - https://packages.microsoft.com/keys/microsoft.asc - ) + local -n pkgs="$1" + for attempt in {1..5}; do + log "Installing packages ${pkgs[*]} attempt #$attempt" + dnf -y \ + install \ + "${install_pkgs[@]}" \ + && break + if [[ ${attempt} -lt 5 ]]; then + sleep 10 + else + abort "Failed to install packages ${pkgs[*]} after $attempt attempts" + fi + done +} +# rpm_import_keys +rpm_import_keys() { + local -n keys="$1" # shellcheck disable=SC2068 - for attempt in {1..5}; do - for key in ${repo_keys[@]}; do + for key in ${keys[@]}; do + if [ ${#keys[@]} -eq 0 ]; then + break + fi + for attempt in {1..5}; do log "importing rpm repository key $key attempt #$attempt" rpm --import \ -v \ "$key" \ + && unset key \ && break done - if [[ ${attempt} -lt 5 ]]; then + if [ -z ${key+x} ] && [[ ${attempt} -lt 5 ]]; then sleep 10 else abort "Failed to import rpm repository key $key after $attempt attempts" fi done - - local -ra install_pkgs=( - clamav - azsec-clamav - azsec-monitor - azure-cli - azure-mdsd - azure-security - podman - podman-docker - openssl-perl - # hack - we are installing python3 on hosts due to an issue with Azure Linux Extensions https://github.com/Azure/azure-linux-extensions/pull/1505 - python3 - https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm - ) - - for attempt in {1..5}; do - log "Installing packages ${install_pkgs[*]} attempt #$attempt" - dnf install \ - -y \ - "${install_pkgs[@]}" \ - && break - if [[ ${attempt} -lt 5 ]]; then - sleep 10 - else - abort "Failed to install packages ${install_pkgs[*]} after $attempt attempts" - fi - done } # configure_disk_partitions @@ -229,7 +245,7 @@ EOF local -r disable_core_filename="$prefix/01-disable-core.conf" local -r disable_core_file="kernel.core_pattern = |/bin/true " - write_file disable_core_filename disable_core_file + write_file disable_core_filename disable_core_file true sysctl --system @@ -355,12 +371,12 @@ DB /var/lib/fluent/journaldb Match * Port 29230" - write_file fluentbit_conf_filename fluentbit_conf_file + write_file fluentbit_conf_filename fluentbit_conf_file true local -r sysconfig_fluentbit_filename='/etc/sysconfig/fluentbit' local -r sysconfig_fluentbit_file="FLUENTBITIMAGE=$FLUENTBITIMAGE" - write_file sysconfig_fluentbit_filename sysconfig_fluentbit_file + write_file sysconfig_fluentbit_filename sysconfig_fluentbit_file true local -r fluentbit_service_filename='/etc/systemd/system/fluentbit.service' @@ -396,7 +412,7 @@ StartLimitInterval=0 [Install] WantedBy=multi-user.target" - write_file fluentbit_conf_filename fluentbit_conf_file + write_file fluentbit_conf_filename fluentbit_conf_file true } # configure_certs @@ -427,7 +443,7 @@ configure_certs() { \"CommandDelay\": 0 }" - write_file nodescan_agent_filename nodescan_agent_file + write_file nodescan_agent_filename nodescan_agent_file true } # configure_service_mdm @@ -441,7 +457,7 @@ MDMSOURCEENVIRONMENT='$LOCATION' MDMSOURCEROLE=rp MDMSOURCEROLEINSTANCE=\"$(hostname)\"" - write_file sysconfig_mdm_filename sysconfig_mdm_file + write_file sysconfig_mdm_filename sysconfig_mdm_file true mkdir -p /var/etw local -r mdm_service_filename="/etc/systemd/system/mdm.service" @@ -478,7 +494,7 @@ StartLimitInterval=0 [Install] WantedBy=multi-user.target" - write_file mdm_service_filename mdm_service_file + write_file mdm_service_filename mdm_service_file true } # configure_timers_mdm_mdsd @@ -492,7 +508,7 @@ Description=Periodic $var credentials refresh Type=oneshot ExecStart=/usr/local/bin/download-credentials.sh $var" - write_file download_creds_service_filename download_creds_service_file + write_file download_creds_service_filename download_creds_service_file true local download_creds_timer_filename="/etc/systemd/system/download-$var-credentials.timer" local download_creds_timer_file="[Unit] @@ -508,7 +524,7 @@ AccuracySec=5s [Install] WantedBy=timers.target" - write_file download_creds_timer_filename download_creds_timer_file + write_file download_creds_timer_filename download_creds_timer_file true done local -r download_creds_script_filename="/usr/local/bin/download-credentials.sh" @@ -581,7 +597,7 @@ else echo Failed to refresh certificate for \$COMPONENT && exit 1 fi" - write_file download_creds_script_filename download_creds_script_file + write_file download_creds_script_filename download_creds_script_file true chmod u+x /usr/local/bin/download-credentials.sh @@ -603,7 +619,7 @@ ExecStart=/usr/bin/systemctl restart mdm.service [Install] WantedBy=multi-user.target" - write_file watch_mdm_creds_service_filename watch_mdm_creds_service_file + write_file watch_mdm_creds_service_filename watch_mdm_creds_service_file true local -r watch_mdm_creds_path_filename='/etc/systemd/system/watch-mdm-credentials.path' local -r watch_mdm_creds_path_file='[Path] @@ -612,7 +628,7 @@ PathModified=/etc/mdm.pem [Install] WantedBy=multi-user.target' - write_file watch_mdm_creds_path_filename watch_mdm_creds_path_file + write_file watch_mdm_creds_path_filename watch_mdm_creds_path_file true local -r watch_mdm_creds='watch-mdm-credentials.path' systemctl enable "$watch_mdm_creds" || abort "failed to enable $watch_mdm_creds" @@ -649,7 +665,7 @@ ARO_HIVE_DEFAULT_INSTALLER_PULLSPEC='$CLUSTERDEFAULTINSTALLERPULLSPEC' ARO_ADOPT_BY_HIVE='$CLUSTERSADOPTBYHIVE' USE_CHECKACCESS='$USECHECKACCESS'" - write_file aro_rp_conf_filename aro_rp_conf_file + write_file aro_rp_conf_filename aro_rp_conf_file true local -r aro_rp_service_filename='/etc/systemd/system/aro-rp.service' local -r aro_rp_service_file="[Unit] @@ -704,7 +720,7 @@ StartLimitInterval=0 [Install] WantedBy=multi-user.target" - write_file aro_rp_service_filename aro_rp_conf_file + write_file aro_rp_service_filename aro_rp_conf_file true } # configure_service_aro_dbtoken @@ -718,7 +734,7 @@ MDM_ACCOUNT='$RPMDMACCOUNT' MDM_NAMESPACE=DBToken RPIMAGE='$RPIMAGE'" - write_file aro_dbtoken_service_conf_filename aro_dbtoken_service_conf_file + write_file aro_dbtoken_service_conf_filename aro_dbtoken_service_conf_file true local -r aro_dbtoken_service_filename='/etc/systemd/system/aro-dbtoken.service' local -r aro_dbtoken_service_file="[Unit] @@ -754,7 +770,7 @@ StartLimitInterval=0 [Install] WantedBy=multi-user.target" - write_file aro_dbtoken_service_filename aro_dbtoken_service_file + write_file aro_dbtoken_service_filename aro_dbtoken_service_file true } # configure_service_aro_monitor @@ -779,7 +795,7 @@ MDM_ACCOUNT='$RPMDMACCOUNT' MDM_NAMESPACE=BBM RPIMAGE='$RPIMAGE'" - write_file aro_monitor_service_conf_filename aro_monitor_service_conf_file + write_file aro_monitor_service_conf_filename aro_monitor_service_conf_file true local -r aro_monitor_service_filename='/etc/systemd/system/aro-monitor.service' local -r aro_monitor_service_file="[Unit] @@ -820,7 +836,7 @@ StartLimitInterval=0 [Install] WantedBy=multi-user.target" - write_file aro_monitor_service_filename aro_monitor_service_file + write_file aro_monitor_service_filename aro_monitor_service_file true } # configure_service_aro_portal @@ -836,7 +852,7 @@ MDM_NAMESPACE=Portal PORTAL_HOSTNAME='$LOCATION.admin.$RPPARENTDOMAINNAME' RPIMAGE='$RPIMAGE'" - write_file aro_portal_service_conf_filename aro_portal_service_conf_file + write_file aro_portal_service_conf_filename aro_portal_service_conf_file true local -r aro_portal_service_filename='/etc/systemd/system/aro-portal.service' local -r aro_portal_service_file="[Unit] @@ -873,7 +889,7 @@ RestartSec=1 [Install] WantedBy=multi-user.target" - write_file aro_portal_service_conf_filename aro_portal_service_conf_file + write_file aro_portal_service_conf_filename aro_portal_service_conf_file true } # configure_service_mdsd @@ -885,7 +901,7 @@ configure_service_mdsd() { local -r mdsd_override_conf_file="[Unit] After=network-online.target" - write_file mdsd_override_conf_filename mdsd_override_conf_file + write_file mdsd_override_conf_filename mdsd_override_conf_file true local -r default_mdsd_filename="/etc/default/mdsd" local -r default_mdsd_file="MDSD_ROLE_PREFIX=/var/run/mdsd/default @@ -906,7 +922,7 @@ export MONITORING_ROLE_INSTANCE=\"$(hostname)\" export MDSD_MSGPACK_SORT_COLUMNS=1\"" - write_file default_mdsd_filename default_mdsd_file + write_file default_mdsd_filename default_mdsd_file true } From 3643a06648d448f76ac6f90c9e54eacf49e7895f Mon Sep 17 00:00:00 2001 From: Steven Fairchild Date: Fri, 12 Apr 2024 07:44:34 -0400 Subject: [PATCH 08/38] Add wait for all rpm related transactions to avoid rpm database corruption Add starting log message for each function call rpm database corruption has been seen in testing, and Prod deployments due to concurrent rpm database operations between rpm and dnf. wait is needed due to this. remove ERR trap, we aren't attempting to trap any specific errors yet. --- pkg/deploy/generator/scripts/rpVMSS.sh | 93 ++++++++++++++++++++------ 1 file changed, 74 insertions(+), 19 deletions(-) diff --git a/pkg/deploy/generator/scripts/rpVMSS.sh b/pkg/deploy/generator/scripts/rpVMSS.sh index c08656c2995..e2ba4c71ee7 100644 --- a/pkg/deploy/generator/scripts/rpVMSS.sh +++ b/pkg/deploy/generator/scripts/rpVMSS.sh @@ -3,8 +3,6 @@ set -o errexit \ -o nounset -trap 'catch' ERR - main() { configure_sshd configure_and_install_dnf_pkgs_repos @@ -23,6 +21,7 @@ main() { # We need to configure PasswordAuthentication to yes in order for the VMSS Access JIT to work configure_sshd() { + log "starting" log "setting ssh password authentication" sed -i 's/PasswordAuthentication no/PasswordAuthentication yes/g' /etc/ssh/sshd_config @@ -32,9 +31,16 @@ configure_sshd() { # configure_and_install_dnf_pkgs_repos configure_and_install_dnf_pkgs_repos() { + log "starting" configure_rhui_repo create_azure_rpm_repos - dnf_update_pkgs + + local -ar exclude_pkgs=( + "-x WALinuxAgent" + "-x WALinuxAgent-udev" + ) + + dnf_update_pkgs exclude_pkgs local -ra rpm_keys=( https://dl.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-8 @@ -67,35 +73,44 @@ configure_and_install_dnf_pkgs_repos() { # configure_rhui_repo configure_rhui_repo() { + log "starting" log "running RHUI package updates" + #Adding retry logic to yum commands in order to avoid stalling out on resource locks for attempt in {1..5}; do + log "attempt #${attempt} - running dnf update" dnf update \ -y \ --disablerepo='*' \ - --enablerepo='rhui-microsoft-azure*' \ - && break + --enablerepo='rhui-microsoft-azure*' & + + wait $! && break if [[ ${attempt} -lt 5 ]]; then sleep 10 else - abort "failed to run dnf update" + abort "attempt #${attempt} - Failed to update packages" fi done } # dnf_update_pkgs dnf_update_pkgs() { + local -n excludes="$1" + log "starting" + for attempt in {1..5}; do - log "running dnf update attempt #${attempt}" + log "attempt #${attempt} - running dnf update" + # shellcheck disable=SC2068 dnf -y \ - -x WALinuxAgent \ - -x WALinuxAgent-udev \ - update --allowerasing \ - && break + ${excludes[@]} \ + update \ + --allowerasing & + + wait $! && break if [[ ${attempt} -lt 5 ]]; then sleep 10 else - abort "Failed to update packages after ${attempt} attempts" + abort "attempt #${attempt} - Failed to update packages" fi done } @@ -103,16 +118,19 @@ dnf_update_pkgs() { # dnf_install_pkgs dnf_install_pkgs() { local -n pkgs="$1" + log "starting" + for attempt in {1..5}; do - log "Installing packages ${pkgs[*]} attempt #$attempt" + log "attempt #$attempt - Installing packages ${pkgs[*]}" dnf -y \ install \ - "${install_pkgs[@]}" \ - && break + "${pkgs[@]}" & + + wait $! && break if [[ ${attempt} -lt 5 ]]; then sleep 10 else - abort "Failed to install packages ${pkgs[*]} after $attempt attempts" + abort "attempt #${attempt} - Failed to install packages ${pkgs[*]}" fi done } @@ -120,13 +138,15 @@ dnf_install_pkgs() { # rpm_import_keys rpm_import_keys() { local -n keys="$1" + log "starting" + # shellcheck disable=SC2068 for key in ${keys[@]}; do if [ ${#keys[@]} -eq 0 ]; then break fi for attempt in {1..5}; do - log "importing rpm repository key $key attempt #$attempt" + log "attempt #$attempt - importing rpm repository key $key" rpm --import \ -v \ "$key" \ @@ -136,14 +156,16 @@ rpm_import_keys() { if [ -z ${key+x} ] && [[ ${attempt} -lt 5 ]]; then sleep 10 else - abort "Failed to import rpm repository key $key after $attempt attempts" + abort "attempt #${attempt} - Failed to import rpm repository key $key" fi done } # configure_disk_partitions configure_disk_partitions() { + log "starting" log "extending partition table" + # Linux block devices are inconsistently named # it's difficult to tie the lvm pv to the physical disk using /dev/disk files, which is why lvs is used here physicalDisk="$(lvs -o devices -a | head -n2 | tail -n1 | cut -d ' ' -f 3 | cut -d \( -f 1 | tr -d '[:digit:]')" @@ -163,6 +185,8 @@ configure_disk_partitions() { # configure_logrotate clobbers /etc/logrotate.conf configure_logrotate() { + log "starting" + local -r logrotate_conf_filename='/etc/logrotate.conf' local -r logrotate_conf_file='# see "man logrotate" for details # rotate log files weekly @@ -203,6 +227,8 @@ include /etc/logrotate.d # create_azure_rpm_repos creates /etc/yum.repos.d/azure.repo repository file create_azure_rpm_repos() { + log "starting" + local -r azure_repo_filename='/etc/yum.repos.d/azure.repo' local -r azure_repo_file='[azure-cli] name=azure-cli @@ -216,11 +242,13 @@ baseurl=https://packages.microsoft.com/yumrepos/azurecore enabled=yes gpgcheck=no' - write_file azure_repo_filename azure_repo_file + write_file azure_repo_filename azure_repo_file true } # configure_selinux configure_selinux() { + log "starting" + local -r relabel="${1:-false}" already_defined_ignore_error="File context for /var/log/journal(/.*)? already defined" @@ -234,6 +262,8 @@ configure_selinux() { # configure_firewalld_rules configure_firewalld_rules() { + log "starting" + # https://access.redhat.com/security/cve/cve-2020-13401 local -r prefix="/etc/sysctl.d" local -r diable_accept_ra_conf="$prefix/02-disable-accept-ra.conf" @@ -267,6 +297,8 @@ EOF # pull_container_images pull_container_images() { + log "starting" + echo "logging into prod acr" az login -i --allow-no-subscriptions @@ -309,6 +341,8 @@ configure_system_services() { # enable_aro_services enables all services required for aro rp enable_aro_services() { + log "starting" + local -ra aro_services=( "aro-dbtoken" "aro-monitor" @@ -332,7 +366,9 @@ enable_aro_services() { # configure_service_fluentbit configure_service_fluentbit() { + log "starting" log "configuring fluentbit service" + mkdir -p /etc/fluentbit/ mkdir -p /var/lib/fluent @@ -417,6 +453,8 @@ WantedBy=multi-user.target" # configure_certs configure_certs() { + log "starting" + mkdir /etc/aro-rp base64 -d <<<"$ADMINAPICABUNDLE" >/etc/aro-rp/admin-ca-bundle.pem if [[ -n "$ARMAPICABUNDLE" ]]; then @@ -448,6 +486,7 @@ configure_certs() { # configure_service_mdm configure_service_mdm() { + log "starting" log "configuring mdm service" local -r sysconfig_mdm_filename="/etc/sysconfig/mdm" @@ -499,6 +538,8 @@ WantedBy=multi-user.target" # configure_timers_mdm_mdsd configure_timers_mdm_mdsd() { + log "starting" + for var in "mdsd" "mdm"; do local download_creds_service_filename="/etc/systemd/system/download-$var-credentials.service" local download_creds_service_file="[Unit] @@ -637,6 +678,8 @@ WantedBy=multi-user.target' # configure_service_aro_rp configure_service_aro_rp() { + log "starting" + local -r aro_rp_conf_filename='/etc/sysconfig/aro-rp' local -r aro_rp_conf_file="ACR_RESOURCE_ID='$ACRRESOURCEID' ADMIN_API_CLIENT_CERT_COMMON_NAME='$ADMINAPICLIENTCERTCOMMONNAME' @@ -725,6 +768,8 @@ WantedBy=multi-user.target" # configure_service_aro_dbtoken configure_service_aro_dbtoken() { + log "starting" + local -r aro_dbtoken_service_conf_filename='/etc/sysconfig/aro-dbtoken' local -r aro_dbtoken_service_conf_file="DATABASE_ACCOUNT_NAME='$DATABASEACCOUNTNAME' AZURE_DBTOKEN_CLIENT_ID='$DBTOKENCLIENTID' @@ -775,7 +820,9 @@ WantedBy=multi-user.target" # configure_service_aro_monitor configure_service_aro_monitor() { + log "starting" log "configuring aro-monitor service" + # DOMAIN_NAME, CLUSTER_MDSD_ACCOUNT, CLUSTER_MDSD_CONFIG_VERSION, GATEWAY_DOMAINS, GATEWAY_RESOURCEGROUP, MDSD_ENVIRONMENT CLUSTER_MDSD_NAMESPACE # are not used, but can't easily be refactored out. Should be revisited in the future. local -r aro_monitor_service_conf_filename='/etc/sysconfig/aro-monitor' @@ -841,6 +888,8 @@ WantedBy=multi-user.target" # configure_service_aro_portal configure_service_aro_portal() { + log "starting" + local -r aro_portal_service_conf_filename='/etc/sysconfig/aro-portal' local -r aro_portal_service_conf_file="AZURE_PORTAL_ACCESS_GROUP_IDS='$PORTALACCESSGROUPIDS' AZURE_PORTAL_CLIENT_ID='$PORTALCLIENTID' @@ -894,6 +943,8 @@ WantedBy=multi-user.target" # configure_service_mdsd configure_service_mdsd() { + log "starting" + local -r mdsd_service_dir="/etc/systemd/system/mdsd.service.d" mkdir "$mdsd_service_dir" @@ -928,6 +979,8 @@ export MDSD_MSGPACK_SORT_COLUMNS=1\"" # run_azsecd_config_scan run_azsecd_config_scan() { + log "starting" + local -ar configs=( "baseline" "clamav" @@ -963,6 +1016,8 @@ write_file() { # reboot_vm restores all selinux file contexts, waits 30 seconds then reboots reboot_vm() { + log "starting" + configure_selinux "true" (sleep 30 && log "rebooting vm now"; reboot) & } From 23f1a336c9034cbd08a9db9d1411e58730bc698f Mon Sep 17 00:00:00 2001 From: Steven Fairchild Date: Mon, 15 Apr 2024 10:25:41 -0400 Subject: [PATCH 09/38] Increase dnf & rpm retry time to 1 minute, 5 minutes total Pass wait time as a nameref variable to allow easier modification --- pkg/deploy/generator/scripts/rpVMSS.sh | 28 +++++++++++++++++--------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/pkg/deploy/generator/scripts/rpVMSS.sh b/pkg/deploy/generator/scripts/rpVMSS.sh index e2ba4c71ee7..dc536ba6f5c 100644 --- a/pkg/deploy/generator/scripts/rpVMSS.sh +++ b/pkg/deploy/generator/scripts/rpVMSS.sh @@ -32,8 +32,11 @@ configure_sshd() { # configure_and_install_dnf_pkgs_repos configure_and_install_dnf_pkgs_repos() { log "starting" - configure_rhui_repo - create_azure_rpm_repos + + # transaction attempt retry time in seconds + local -ri retry_wait_time=60 + configure_rhui_repo retry_wait_time + create_azure_rpm_repos retry_wait_time local -ar exclude_pkgs=( "-x WALinuxAgent" @@ -67,12 +70,13 @@ configure_and_install_dnf_pkgs_repos() { python3 ) - dnf_install_pkgs repo_rpm_pkgs - dnf_install_pkgs install_pkgs + dnf_install_pkgs repo_rpm_pkgs retry_wait_time + dnf_install_pkgs install_pkgs retry_wait_time } # configure_rhui_repo configure_rhui_repo() { + local -n wait_time="$1" log "starting" log "running RHUI package updates" @@ -86,7 +90,7 @@ configure_rhui_repo() { wait $! && break if [[ ${attempt} -lt 5 ]]; then - sleep 10 + sleep "$wait_time" else abort "attempt #${attempt} - Failed to update packages" fi @@ -96,6 +100,7 @@ configure_rhui_repo() { # dnf_update_pkgs dnf_update_pkgs() { local -n excludes="$1" + local -n wait_time="$2" log "starting" for attempt in {1..5}; do @@ -108,7 +113,7 @@ dnf_update_pkgs() { wait $! && break if [[ ${attempt} -lt 5 ]]; then - sleep 10 + sleep "$wait_time" else abort "attempt #${attempt} - Failed to update packages" fi @@ -118,6 +123,7 @@ dnf_update_pkgs() { # dnf_install_pkgs dnf_install_pkgs() { local -n pkgs="$1" + local -n wait_time="$2" log "starting" for attempt in {1..5}; do @@ -128,7 +134,7 @@ dnf_install_pkgs() { wait $! && break if [[ ${attempt} -lt 5 ]]; then - sleep 10 + sleep "$wait_time" else abort "attempt #${attempt} - Failed to install packages ${pkgs[*]}" fi @@ -138,6 +144,7 @@ dnf_install_pkgs() { # rpm_import_keys rpm_import_keys() { local -n keys="$1" + local -n wait_time="$2" log "starting" # shellcheck disable=SC2068 @@ -150,11 +157,12 @@ rpm_import_keys() { rpm --import \ -v \ "$key" \ - && unset key \ - && break + && unset key + + wait $! && break done if [ -z ${key+x} ] && [[ ${attempt} -lt 5 ]]; then - sleep 10 + sleep "$wait_time" else abort "attempt #${attempt} - Failed to import rpm repository key $key" fi From 0b8104f9b514e79dd53c7f9015b34e57104831a3 Mon Sep 17 00:00:00 2001 From: Steven Fairchild Date: Mon, 15 Apr 2024 11:54:06 -0400 Subject: [PATCH 10/38] Add parse_run_options to run individual steps for testing --- pkg/deploy/generator/scripts/rpVMSS.sh | 67 ++++++++++++++++++++++++-- 1 file changed, 64 insertions(+), 3 deletions(-) diff --git a/pkg/deploy/generator/scripts/rpVMSS.sh b/pkg/deploy/generator/scripts/rpVMSS.sh index dc536ba6f5c..d854c93a5fd 100644 --- a/pkg/deploy/generator/scripts/rpVMSS.sh +++ b/pkg/deploy/generator/scripts/rpVMSS.sh @@ -3,7 +3,14 @@ set -o errexit \ -o nounset +if [ "${DEBUG:-false}" == true ]; then + set -x +fi + main() { + parse_run_options "$@" + + configure_sshd configure_and_install_dnf_pkgs_repos configure_disk_partitions @@ -19,6 +26,59 @@ main() { reboot_vm } +parse_run_options() { + local -a options=("$1") + if [ "${#options[@]}" -eq 0 ]; then + log "Running all steps" + return 0 + fi + + local OPTIND + + while getopts "dplsrfui" options; do + case "${options}" in + d) + log "Running step configure_disk_partitions" + configure_disk_partitions + ;; + p) + log "Running step configure_and_install_dnf_pkgs_repos" + configure_and_install_dnf_pkgs_repos + ;; + l) + log "Running configure_logrotate" + configure_logrotate + ;; + s) + log "Running configure_selinux" + configure_selinux + ;; + r) + log "Running configure_sshd" + configure_sshd + ;; + f) + log "Running configure_firewalld_rules" + configure_firewalld_rules + ;; + u) + log "Running pull_container_images & configure_system_services" + pull_container_images + configure_system_services + ;; + i) + log "Running pull_container_images" + pull_container_images + ;; + *) + abort "Unkown option" + ;; + esac + done + + exit 0 +} + # We need to configure PasswordAuthentication to yes in order for the VMSS Access JIT to work configure_sshd() { log "starting" @@ -43,14 +103,14 @@ configure_and_install_dnf_pkgs_repos() { "-x WALinuxAgent-udev" ) - dnf_update_pkgs exclude_pkgs + dnf_update_pkgs exclude_pkgs retry_wait_time local -ra rpm_keys=( https://dl.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-8 https://packages.microsoft.com/keys/microsoft.asc ) - rpm_import_keys rpm_keys + rpm_import_keys rpm_keys retry_wait_time local -ra repo_rpm_pkgs=( https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm @@ -1041,9 +1101,10 @@ log() { abort() { local -ri origin_stacklevel=2 log "${1}" "$origin_stacklevel" + log "Exiting" exit 1 } export AZURE_CLOUD_NAME="${AZURECLOUDNAME:?"Failed to carry over variables"}" -main +main "$@" From fd6b96e4a5a55c3713fb5d93fc0e44ce07d300b1 Mon Sep 17 00:00:00 2001 From: Steven Fairchild Date: Mon, 15 Apr 2024 12:17:06 -0400 Subject: [PATCH 11/38] Add usage statement --- pkg/deploy/generator/scripts/rpVMSS.sh | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/pkg/deploy/generator/scripts/rpVMSS.sh b/pkg/deploy/generator/scripts/rpVMSS.sh index d854c93a5fd..4965a17393a 100644 --- a/pkg/deploy/generator/scripts/rpVMSS.sh +++ b/pkg/deploy/generator/scripts/rpVMSS.sh @@ -26,6 +26,23 @@ main() { reboot_vm } +usage() { + log "$(basename "$0") [-dplsrfui] + -d Configure Disk Partitions + -p Configure rpm repositories, import required rpm keys, update & install packages with dnf + -l Configure logrotate.conf + -s Make selinux modifications required for ARO RP + -r Configure sshd - Allow password authenticaiton + -f Configure firewalld default zone rules + -u Pull container images and configure systemd unit files for ARO RP + -i Pull container images + " +} + +# parse_run_options takes all arguements passed to main and parses them +# allowing individual step(s) to be ran, rather than all steps +# +# This is useful for local testing, or possibly modifying the bootstrap execution via environment variables in the deployment pipeline parse_run_options() { local -a options=("$1") if [ "${#options[@]}" -eq 0 ]; then @@ -71,7 +88,8 @@ parse_run_options() { pull_container_images ;; *) - abort "Unkown option" + usage + abort "Unkown option provided" ;; esac done From 051f6335e7b33d78e74f9fa3ccc682446eef51b3 Mon Sep 17 00:00:00 2001 From: Steven Fairchild Date: Mon, 15 Apr 2024 14:18:34 -0400 Subject: [PATCH 12/38] Add az login -i comment found in gatewayVMSS.sh, change variable syntex to snake case for consistency --- pkg/deploy/generator/scripts/rpVMSS.sh | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/pkg/deploy/generator/scripts/rpVMSS.sh b/pkg/deploy/generator/scripts/rpVMSS.sh index 4965a17393a..2198ae2103c 100644 --- a/pkg/deploy/generator/scripts/rpVMSS.sh +++ b/pkg/deploy/generator/scripts/rpVMSS.sh @@ -254,8 +254,8 @@ configure_disk_partitions() { # Linux block devices are inconsistently named # it's difficult to tie the lvm pv to the physical disk using /dev/disk files, which is why lvs is used here - physicalDisk="$(lvs -o devices -a | head -n2 | tail -n1 | cut -d ' ' -f 3 | cut -d \( -f 1 | tr -d '[:digit:]')" - growpart "$physicalDisk" 2 + physical_disk="$(lvs -o devices -a | head -n2 | tail -n1 | cut -d ' ' -f 3 | cut -d \( -f 1 | tr -d '[:digit:]')" + growpart "$physical_disk" 2 log "extending filesystems" log "extending root lvm" @@ -386,6 +386,13 @@ pull_container_images() { log "starting" echo "logging into prod acr" + + # The managed identity that the VM runs as only has a single roleassignment. + # This role assignment is ACRPull which is not necessarily present in the + # subscription we're deploying into. If the identity does not have any + # role assignments scoped on the subscription we're deploying into, it will + # not show on az login -i, which is why the below line is commented. + # az account set -s "$SUBSCRIPTIONID" az login -i --allow-no-subscriptions # Suppress emulation output for podman instead of docker for az acr compatability From 15f71f9d42e6898a100a6115fcc0e851f75a01d3 Mon Sep 17 00:00:00 2001 From: Steven Fairchild Date: Mon, 15 Apr 2024 14:19:49 -0400 Subject: [PATCH 13/38] Port changes made in rpVMSS.sh to gatewayVMSS.sh Make gateway log directory to be passed in to functions where it is needed, this allows the value to be set in one location. Move retry steps into a single retry function call This is to reduce code duplication Move configure_fiewall_rules file creation to use write_file Correct accept_ra_conf variable name spelling --- pkg/deploy/generator/scripts/gatewayVMSS.sh | 1028 ++++++++++++++----- pkg/deploy/generator/scripts/rpVMSS.sh | 112 +- 2 files changed, 814 insertions(+), 326 deletions(-) diff --git a/pkg/deploy/generator/scripts/gatewayVMSS.sh b/pkg/deploy/generator/scripts/gatewayVMSS.sh index 613adc8d5e3..3751446891e 100644 --- a/pkg/deploy/generator/scripts/gatewayVMSS.sh +++ b/pkg/deploy/generator/scripts/gatewayVMSS.sh @@ -1,52 +1,276 @@ #!/bin/bash -echo "setting ssh password authentication" -# We need to manually set PasswordAuthentication to true in order for the VMSS Access JIT to work -sed -i 's/PasswordAuthentication no/PasswordAuthentication yes/g' /etc/ssh/sshd_config -systemctl reload sshd.service +set -o errexit \ + -o nounset -#Adding retry logic to yum commands in order to avoid stalling out on resource locks -echo "running RHUI fix" -for attempt in {1..5}; do - yum update -y --disablerepo='*' --enablerepo='rhui-microsoft-azure*' && break - if [[ ${attempt} -lt 5 ]]; then sleep 10; else exit 1; fi -done +if [ "${DEBUG:-false}" == true ]; then + set -x +fi -echo "running yum update" -for attempt in {1..5}; do - yum -y -x WALinuxAgent -x WALinuxAgent-udev update --allowerasing && break - if [[ ${attempt} -lt 5 ]]; then sleep 10; else exit 1; fi -done +main() { + local -r gateway_logdir='/var/log/aro-gateway' + parse_run_options "$@" gateway_logdir -echo "extending partition table" -# Linux block devices are inconsistently named -# it's difficult to tie the lvm pv to the physical disk using /dev/disk files, which is why lvs is used here -physical_disk="$(lvs -o devices -a | head -n2 | tail -n1 | cut -d ' ' -f 3 | cut -d \( -f 1 | tr -d '[:digit:]')" -growpart "$physical_disk" 2 -echo "extending filesystems" -lvextend -l +20%FREE /dev/rootvg/rootlv -xfs_growfs / + configure_sshd + configure_and_install_dnf_pkgs_repos + configure_disk_partitions + configure_logrotate gateway_logdir + configure_selinux -lvextend -l +100%FREE /dev/rootvg/varlv -xfs_growfs /var + mkdir -p /var/log/journal + mkdir -p /var/lib/waagent/Microsoft.Azure.KeyVault.Store -rpm --import https://dl.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-8 -rpm --import https://packages.microsoft.com/keys/microsoft.asc + configure_firewalld_rules + pull_container_images + configure_system_services gateway_logdir + reboot_vm +} -for attempt in {1..5}; do - yum -y install https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm && break - if [[ ${attempt} -lt 5 ]]; then sleep 10; else exit 1; fi -done +usage() { + log "$(basename "$0") [-dplsrfui] + -d Configure Disk Partitions + -p Configure rpm repositories, import required rpm keys, update & install packages with dnf + -l Configure logrotate.conf + -s Make selinux modifications required for ARO RP + -r Configure sshd - Allow password authenticaiton + -f Configure firewalld default zone rules + -u Pull container images and configure systemd unit files for ARO RP + -i Pull container images + " +} + +# parse_run_options takes all arguements passed to main and parses them +# allowing individual step(s) to be ran, rather than all steps +# +# This is useful for local testing, or possibly modifying the bootstrap execution via environment variables in the deployment pipeline +parse_run_options() { + local -a options=("$1") + if [ "${#options[@]}" -eq 0 ]; then + log "Running all steps" + return 0 + fi + + local OPTIND + + while getopts "dplsrfui" options; do + case "${options}" in + d) + log "Running step configure_disk_partitions" + configure_disk_partitions + ;; + p) + log "Running step configure_and_install_dnf_pkgs_repos" + configure_and_install_dnf_pkgs_repos + ;; + l) + log "Running configure_logrotate" + configure_logrotate "$2" + ;; + s) + log "Running configure_selinux" + configure_selinux + ;; + r) + log "Running configure_sshd" + configure_sshd + ;; + f) + log "Running configure_firewalld_rules" + configure_firewalld_rules + ;; + u) + log "Running pull_container_images & configure_system_services" + configure_system_services "$2" + ;; + i) + log "Running pull_container_images" + pull_container_images + ;; + *) + usage + abort "Unkown option provided" + ;; + esac + done + + exit 0 +} + +# We need to configure PasswordAuthentication to yes in order for the VMSS Access JIT to work +configure_sshd() { + log "starting" + log "setting ssh password authentication" + sed -i 's/PasswordAuthentication no/PasswordAuthentication yes/g' /etc/ssh/sshd_config + + systemctl reload sshd.service + systemctl is-active --quiet sshd || abort "sshd failed to reload" +} + +# configure_and_install_dnf_pkgs_repos +configure_and_install_dnf_pkgs_repos() { + log "starting" + + # transaction attempt retry time in seconds + local -ri retry_wait_time=60 + configure_rhui_repo retry_wait_time + create_azure_rpm_repos retry_wait_time + + local -ar exclude_pkgs=( + "-x WALinuxAgent" + "-x WALinuxAgent-udev" + ) + + dnf_update_pkgs exclude_pkgs retry_wait_time + + local -ra rpm_keys=( + https://dl.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-8 + https://packages.microsoft.com/keys/microsoft.asc + ) + + rpm_import_keys rpm_keys retry_wait_time + + local -ra repo_rpm_pkgs=( + https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm + ) + + local -ra install_pkgs=( + clamav + azsec-clamav + azsec-monitor + azure-cli + azure-mdsd + azure-security + podman + podman-docker + openssl-perl + # hack - we are installing python3 on hosts due to an issue with Azure Linux Extensions https://github.com/Azure/azure-linux-extensions/pull/1505 + python3 + ) + + dnf_install_pkgs repo_rpm_pkgs retry_wait_time + dnf_install_pkgs install_pkgs retry_wait_time +} + +# configure_rhui_repo +configure_rhui_repo() { + log "starting" + + local -ra cmd=( + dnf + update + -y + --disablerepo='*' + --enablerepo='rhui-microsoft-azure*' + ) + + log "running RHUI package updates" + retry cmd "$1" +} + +# retry Adding retry logic to yum commands in order to avoid stalling out on resource locks +retry() { + local -n cmd_retry="$1" + local -n wait_time="$2" + + for attempt in {1..5}; do + log "attempt #${attempt} - ${FUNCNAME[2]}" + ${cmd_retry[@]} & + + wait $! && break + if [[ ${attempt} -lt 5 ]]; then + sleep "$wait_time" + else + abort "attempt #${attempt} - Failed to update packages" + fi + done +} + +# dnf_update_pkgs +dnf_update_pkgs() { + local -n excludes="$1" + log "starting" + + local -ra cmd=( + dnf + -y + ${excludes[@]} + update + --allowerasing + ) + + log "Updating all packages" + retry cmd "$2" +} + +# dnf_install_pkgs +dnf_install_pkgs() { + local -n pkgs="$1" + log "starting" + + local -ra cmd=( + dnf + -y + install + ${pkgs[@]} + ) + + log "Attempting to install packages: ${pkgs[*]}" + retry cmd "$2" +} + +# rpm_import_keys +rpm_import_keys() { + local -n keys="$1" + log "starting" + + + # shellcheck disable=SC2068 + for key in ${keys[@]}; do + if [ ${#keys[@]} -eq 0 ]; then + break + fi + local -a cmd=( + rpm + --import + -v + "$key" + ) + + log "attempt #$attempt - importing rpm repository key $key" + retry cmd "$2" && unset key + done +} -echo "configuring logrotate" +# configure_disk_partitions +configure_disk_partitions() { + log "starting" + log "extending partition table" + + # Linux block devices are inconsistently named + # it's difficult to tie the lvm pv to the physical disk using /dev/disk files, which is why lvs is used here + physical_disk="$(lvs -o devices -a | head -n2 | tail -n1 | cut -d ' ' -f 3 | cut -d \( -f 1 | tr -d '[:digit:]')" + growpart "$physical_disk" 2 + + log "extending filesystems" + log "extending root lvm" + lvextend -l +20%FREE /dev/rootvg/rootlv + log "growing root filesystem" + xfs_growfs / + + log "extending var lvm" + lvextend -l +100%FREE /dev/rootvg/varlv + log "growing var filesystem" + xfs_growfs /var +} -# gateway_logdir is a readonly variable that specifies the host path mount point for the gateway container log file -# for the purpose of rotating the gateway logs -declare -r gateway_logdir='/var/log/aro-gateway' +# configure_logrotate clobbers /etc/logrotate.conf +configure_logrotate() { + local -n log_dir="$1" + log "starting" -cat >/etc/logrotate.conf </etc/yum.repos.d/azure.repo <<'EOF' -[azure-cli] +# create_azure_rpm_repos creates /etc/yum.repos.d/azure.repo repository file +create_azure_rpm_repos() { + log "starting" + + local -r azure_repo_filename='/etc/yum.repos.d/azure.repo' + local -r azure_repo_file='[azure-cli] name=azure-cli baseurl=https://packages.microsoft.com/yumrepos/azure-cli enabled=yes @@ -105,69 +334,144 @@ gpgcheck=yes name=azurecore baseurl=https://packages.microsoft.com/yumrepos/azurecore enabled=yes -gpgcheck=no -EOF +gpgcheck=no' -semanage fcontext -a -t var_log_t "/var/log/journal(/.*)?" -mkdir -p /var/log/journal + write_file azure_repo_filename azure_repo_file true +} -for attempt in {1..5}; do - yum -y install clamav azsec-clamav azsec-monitor azure-cli azure-mdsd azure-security podman-docker openssl-perl python3 && break - # hack - we are installing python3 on hosts due to an issue with Azure Linux Extensions https://github.com/Azure/azure-linux-extensions/pull/1505 - if [[ ${attempt} -lt 5 ]]; then sleep 10; else exit 1; fi -done +# configure_selinux +configure_selinux() { + log "starting" + + local -r relabel="${1:-false}" + + already_defined_ignore_error="File context for /var/log/journal(/.*)? already defined" + semanage fcontext -a -t var_log_t "/var/log/journal(/.*)?" || log "$already_defined_ignore_error" + chcon -R system_u:object_r:var_log_t:s0 /var/opt/microsoft/linuxmonagent + + if "$relabel"; then + restorecon -RF /var/log/* || log "$already_defined_ignore_error" + fi +} + +# configure_firewalld_rules +configure_firewalld_rules() { + log "starting" + + # https://access.redhat.com/security/cve/cve-2020-13401 + local -r prefix="/etc/sysctl.d" + local -r disable_accept_ra_conf_filename="$prefix/02-disable-accept-ra.conf" + local -r disable_accept_ra_conf_file="net.ipv6.conf.all.accept_ra=0" + + write_file disable_accept_ra_conf_filename disable_accept_ra_conf_file true + + local -r disable_core_filename="$prefix/01-disable-core.conf" + local -r disable_core_file="kernel.core_pattern = |/bin/true + " + write_file disable_core_filename disable_core_file true + + sysctl --system + + enable_ports=( + "443/tcp" + "444/tcp" + "445/tcp" + "2222/tcp" + ) + log "Enabling ports ${enable_ports[*]} on default firewalld zone" + # shellcheck disable=SC2068 + for port in ${enable_ports[@]}; do + log "Enabling port $port now" + firewall-cmd "--add-port=$port" + done + + firewall-cmd --runtime-to-permanent +} + +# pull_container_images +pull_container_images() { + log "starting" + + echo "logging into prod acr" -echo "applying firewall rules" -# https://access.redhat.com/security/cve/cve-2020-13401 -cat >/etc/sysctl.d/02-disable-accept-ra.conf <<'EOF' -net.ipv6.conf.all.accept_ra=0 -EOF - -cat >/etc/sysctl.d/01-disable-core.conf <<'EOF' -kernel.core_pattern = |/bin/true -EOF -sysctl --system - -firewall-cmd --add-port=80/tcp --permanent -firewall-cmd --add-port=8081/tcp --permanent -firewall-cmd --add-port=443/tcp --permanent - -echo "logging into prod acr" -export AZURE_CLOUD_NAME=$AZURECLOUDNAME -az login -i --allow-no-subscriptions - -# The managed identity that the VM runs as only has a single roleassignment. -# This role assignment is ACRPull which is not necessarily present in the -# subscription we're deploying into. If the identity does not have any -# role assignments scoped on the subscription we're deploying into, it will -# not show on az login -i, which is why the below line is commented. -# az account set -s "$SUBSCRIPTIONID" - -# Suppress emulation output for podman instead of docker for az acr compatability -mkdir -p /etc/containers/ -touch /etc/containers/nodocker - -mkdir -p /root/.docker -REGISTRY_AUTH_FILE="/root/.docker/config.json" -az acr login --name "$(sed -e 's|.*/||' <<<"$ACRRESOURCEID")" - -MDMIMAGE="${RPIMAGE%%/*}/${MDMIMAGE##*/}" -docker pull "$MDMIMAGE" -docker pull "$RPIMAGE" -docker pull "$FLUENTBITIMAGE" - -az logout - -echo "configuring fluentbit service" -mkdir -p /etc/fluentbit/ -mkdir -p /var/lib/fluent - -cat >/etc/fluentbit/fluentbit.conf <<'EOF' -[INPUT] - Name systemd - Tag journald - Systemd_Filter _COMM=aro - DB /var/lib/fluent/journaldb + # The managed identity that the VM runs as only has a single roleassignment. + # This role assignment is ACRPull which is not necessarily present in the + # subscription we're deploying into. If the identity does not have any + # role assignments scoped on the subscription we're deploying into, it will + # not show on az login -i, which is why the below line is commented. + # az account set -s "$SUBSCRIPTIONID" + az login -i --allow-no-subscriptions + + # Suppress emulation output for podman instead of docker for az acr compatability + mkdir -p /etc/containers/ + touch /etc/containers/nodocker + + mkdir -p /root/.docker + local -r REGISTRY_AUTH_FILE="/root/.docker/config.json" + + az acr login --name "$(sed -e 's|.*/||' <<<"$ACRRESOURCEID")" + + MDMIMAGE="${RPIMAGE%%/*}/${MDMIMAGE##*/}" + docker pull "$MDMIMAGE" + docker pull "$RPIMAGE" + docker pull "$FLUENTBITIMAGE" + + az logout +} + +# configure_system_services creates, configures, and enables the following systemd services and timers +# services +# fluentbit +# mdm +# mdsd +# arp-rp +# aro-dbtoken +# aro-monitor +# aro-portal +configure_system_services() { + configure_service_fluentbit + configure_service_mdm + configure_timers_mdm_mdsd + configure_service_aro_gateway "$1" + configure_service_mdsd +} + +# enable_aro_services enables all services required for aro rp +enable_aro_services() { + log "starting" + + local -ra aro_services=( + aro-gateway + auoms + azsecd + azsecmond + mdsd + mdm + chronyd + fluentbit + ) + log "enabling gateway services ${aro_services[*]}" + # shellcheck disable=SC2068 + for service in ${aro_services[@]}; do + log "Enabling $service now" + systemctl enable "$service.service" + done +} + +# configure_service_fluentbit +configure_service_fluentbit() { + log "starting" + log "configuring fluentbit service" + + mkdir -p /etc/fluentbit/ + mkdir -p /var/lib/fluent + + local -r fluentbit_conf_filename='/etc/fluentbit/fluentbit.conf' + local -r fluentbit_conf_file="[INPUT] +Name systemd +Tag journald +Systemd_Filter _COMM=aro +DB /var/lib/fluent/journaldb [FILTER] Name modify @@ -178,13 +482,18 @@ cat >/etc/fluentbit/fluentbit.conf <<'EOF' [OUTPUT] Name forward Match * - Port 29230 -EOF + Port 29230" + + write_file fluentbit_conf_filename fluentbit_conf_file true + + local -r sysconfig_fluentbit_filename='/etc/sysconfig/fluentbit' + local -r sysconfig_fluentbit_file="FLUENTBITIMAGE=$FLUENTBITIMAGE" + + write_file sysconfig_fluentbit_filename sysconfig_fluentbit_file true -echo "FLUENTBITIMAGE=$FLUENTBITIMAGE" >/etc/sysconfig/fluentbit + local -r fluentbit_service_filename='/etc/systemd/system/fluentbit.service' -cat >/etc/systemd/system/fluentbit.service <<'EOF' -[Unit] + local -r fluentbit_service_file="[Unit] After=network-online.target Wants=network-online.target StartLimitIntervalSec=0 @@ -214,21 +523,61 @@ RestartSec=5 StartLimitInterval=0 [Install] -WantedBy=multi-user.target -EOF +WantedBy=multi-user.target" + + write_file fluentbit_conf_filename fluentbit_conf_file true +} + +# configure_certs +configure_certs() { + log "starting" + + mkdir /etc/aro-rp + base64 -d <<<"$ADMINAPICABUNDLE" >/etc/aro-rp/admin-ca-bundle.pem + if [[ -n "$ARMAPICABUNDLE" ]]; then + base64 -d <<<"$ARMAPICABUNDLE" >/etc/aro-rp/arm-ca-bundle.pem + fi + chown -R 1000:1000 /etc/aro-rp + + # setting MONITORING_GCS_AUTH_ID_TYPE=AuthKeyVault seems to have caused mdsd not + # to honour SSL_CERT_FILE any more, heaven only knows why. + mkdir -p /usr/lib/ssl/certs + csplit -f /usr/lib/ssl/certs/cert- -b %03d.pem /etc/pki/tls/certs/ca-bundle.crt /^$/1 "{*}" >/dev/null + c_rehash /usr/lib/ssl/certs + +# we leave clientId blank as long as only 1 managed identity assigned to vmss +# if we have more than 1, we will need to populate with clientId used for off-node scanning + local -r nodescan_agent_filename="/etc/default/vsa-nodescan-agent.config" + local -r nodescan_agent_file="{ + \"Nice\": 19, + \"Timeout\": 10800, + \"ClientId\": \"\", + \"TenantId\": $AZURESECPACKVSATENANTID, + \"QualysStoreBaseUrl\": $AZURESECPACKQUALYSURL, + \"ProcessTimeout\": 300, + \"CommandDelay\": 0 + }" + + write_file nodescan_agent_filename nodescan_agent_file true +} + +# configure_service_mdm +configure_service_mdm() { + log "starting" + log "configuring mdm service" -echo "configuring mdm service" -cat >/etc/sysconfig/mdm </etc/systemd/system/mdm.service <<'EOF' -[Unit] + write_file sysconfig_mdm_filename sysconfig_mdm_file true + + mkdir -p /var/etw + local -r mdm_service_filename="/etc/systemd/system/mdm.service" + local -r mdm_service_file="[Unit] After=network-online.target Wants=network-online.target @@ -259,80 +608,28 @@ RestartSec=1 StartLimitInterval=0 [Install] -WantedBy=multi-user.target -EOF - -echo "configuring aro-gateway service" -cat >/etc/sysconfig/aro-gateway </etc/systemd/system/aro-gateway.service </etc/systemd/system/download-$var-credentials.service </etc/systemd/system/download-$var-credentials.timer </usr/local/bin/download-credentials.sh </etc/systemd/system/watch-mdm-credentials.service </etc/systemd/system/watch-mdm-credentials.path </etc/systemd/system/mdsd.service.d/override.conf <<'EOF' -[Unit] + local -r aro_dbtoken_service_filename='/etc/systemd/system/aro-dbtoken.service' + local -r aro_dbtoken_service_file="[Unit] After=network-online.target -EOF +Wants=network-online.target + +[Service] +EnvironmentFile=/etc/sysconfig/aro-gateway +ExecStartPre=-/usr/bin/docker rm -f %N +ExecStartPre=/usr/bin/mkdir -p ${gateway_logdir} +ExecStart=/usr/bin/docker run \ + --hostname %H \ + --name %N \ + --rm \ + --cap-drop net_raw \ + -e ACR_RESOURCE_ID \ + -e DATABASE_ACCOUNT_NAME \ + -e AZURE_DBTOKEN_CLIENT_ID \ + -e DBTOKEN_URL \ + -e GATEWAY_DOMAINS \ + -e GATEWAY_FEATURES \ + -e MDM_ACCOUNT \ + -e MDM_NAMESPACE \ + -m 2g \ + -p 80:8080 \ + -p 8081:8081 \ + -p 443:8443 \ + -v /run/systemd/journal:/run/systemd/journal \ + -v /var/etw:/var/etw:z \ + -v ${gateway_logdir}:/ctr.log:z \ + \$RPIMAGE \ + gateway +ExecStop=/usr/bin/docker stop -t 3600 %N +TimeoutStopSec=3600 +Restart=always +RestartSec=1 +StartLimitInterval=0 + +[Install] +WantedBy=multi-user.target" + + write_file aro_dbtoken_service_filename aro_dbtoken_service_file true +} + +# configure_service_mdsd +configure_service_mdsd() { + log "starting" + + local -r mdsd_service_dir="/etc/systemd/system/mdsd.service.d" + mkdir "$mdsd_service_dir" + + local -r mdsd_override_conf_filename="$mdsd_service_dir/override.conf" + local -r mdsd_override_conf_file="[Unit] +After=network-online.target" -cat >/etc/default/mdsd </dev/null -c_rehash /usr/lib/ssl/certs + write_file default_mdsd_filename default_mdsd_file true -# we leave clientId blank as long as only 1 managed identity assigned to vmss -# if we have more than 1, we will need to populate with clientId used for off-node scanning -cat >/etc/default/vsa-nodescan-agent.config < "$filename" + else + log "Appending to $filename" + echo "$file_contents" >> "$filename" + fi +} + +# reboot_vm restores all selinux file contexts, waits 30 seconds then reboots +reboot_vm() { + log "starting" + + configure_selinux "true" + (sleep 30 && log "rebooting vm now"; reboot) & +} + +# log is a wrapper for echo that includes the function name +log() { + local -r msg="${1:-"log message is empty"}" + local -r stack_level="${2:-1}" + echo "${FUNCNAME[${stack_level}]}: ${msg}" +} + +# abort is a wrapper for log that exits with an error code +abort() { + local -ri origin_stacklevel=2 + log "${1}" "$origin_stacklevel" + log "Exiting" + exit 1 +} + +export AZURE_CLOUD_NAME="${AZURECLOUDNAME:?"Failed to carry over variables"}" -echo "rebooting" -restorecon -RF /var/log/* -(sleep 30; reboot) & +main "$@" diff --git a/pkg/deploy/generator/scripts/rpVMSS.sh b/pkg/deploy/generator/scripts/rpVMSS.sh index 2198ae2103c..f978ef2e00a 100644 --- a/pkg/deploy/generator/scripts/rpVMSS.sh +++ b/pkg/deploy/generator/scripts/rpVMSS.sh @@ -154,19 +154,30 @@ configure_and_install_dnf_pkgs_repos() { # configure_rhui_repo configure_rhui_repo() { - local -n wait_time="$1" log "starting" + + local -ra cmd=( + dnf + update + -y + --disablerepo='*' + --enablerepo='rhui-microsoft-azure*' + ) + log "running RHUI package updates" + retry cmd "$1" +} + +# retry Adding retry logic to yum commands in order to avoid stalling out on resource locks +retry() { + local -n cmd_retry="$1" + local -n wait_time="$2" - #Adding retry logic to yum commands in order to avoid stalling out on resource locks for attempt in {1..5}; do - log "attempt #${attempt} - running dnf update" - dnf update \ - -y \ - --disablerepo='*' \ - --enablerepo='rhui-microsoft-azure*' & + log "attempt #${attempt} - ${FUNCNAME[2]}" + ${cmd_retry[@]} & - wait $! && break + wait $! && break if [[ ${attempt} -lt 5 ]]; then sleep "$wait_time" else @@ -178,72 +189,56 @@ configure_rhui_repo() { # dnf_update_pkgs dnf_update_pkgs() { local -n excludes="$1" - local -n wait_time="$2" log "starting" - for attempt in {1..5}; do - log "attempt #${attempt} - running dnf update" - # shellcheck disable=SC2068 - dnf -y \ - ${excludes[@]} \ - update \ - --allowerasing & - - wait $! && break - if [[ ${attempt} -lt 5 ]]; then - sleep "$wait_time" - else - abort "attempt #${attempt} - Failed to update packages" - fi - done + local -ra cmd=( + dnf + -y + ${excludes[@]} + update + --allowerasing + ) + + log "Updating all packages" + retry cmd "$2" } # dnf_install_pkgs dnf_install_pkgs() { local -n pkgs="$1" - local -n wait_time="$2" log "starting" - for attempt in {1..5}; do - log "attempt #$attempt - Installing packages ${pkgs[*]}" - dnf -y \ - install \ - "${pkgs[@]}" & + local -ra cmd=( + dnf + -y + install + ${pkgs[@]} + ) - wait $! && break - if [[ ${attempt} -lt 5 ]]; then - sleep "$wait_time" - else - abort "attempt #${attempt} - Failed to install packages ${pkgs[*]}" - fi - done + log "Attempting to install packages: ${pkgs[*]}" + retry cmd "$2" } # rpm_import_keys rpm_import_keys() { local -n keys="$1" - local -n wait_time="$2" log "starting" + # shellcheck disable=SC2068 for key in ${keys[@]}; do - if [ ${#keys[@]} -eq 0 ]; then - break - fi - for attempt in {1..5}; do - log "attempt #$attempt - importing rpm repository key $key" - rpm --import \ - -v \ - "$key" \ - && unset key - - wait $! && break - done - if [ -z ${key+x} ] && [[ ${attempt} -lt 5 ]]; then - sleep "$wait_time" - else - abort "attempt #${attempt} - Failed to import rpm repository key $key" + if [ ${#keys[@]} -eq 0 ]; then + break fi + local -a cmd=( + rpm + --import + -v + "$key" + ) + + log "attempt #$attempt - importing rpm repository key $key" + retry cmd "$2" && unset key done } @@ -352,11 +347,10 @@ configure_firewalld_rules() { # https://access.redhat.com/security/cve/cve-2020-13401 local -r prefix="/etc/sysctl.d" - local -r diable_accept_ra_conf="$prefix/02-disable-accept-ra.conf" - log "Writing $diable_accept_ra_conf" -cat >"$diable_accept_ra_conf" <<'EOF' -net.ipv6.conf.all.accept_ra=0 -EOF + local -r disable_accept_ra_conf_filename="$prefix/02-disable-accept-ra.conf" + local -r disable_accept_ra_conf_file="net.ipv6.conf.all.accept_ra=0" + + write_file disable_accept_ra_conf_filename disable_accept_ra_conf_file true local -r disable_core_filename="$prefix/01-disable-core.conf" local -r disable_core_file="kernel.core_pattern = |/bin/true From e899ae17e575b1cac17e750161a078a18c398af7 Mon Sep 17 00:00:00 2001 From: Steven Fairchild Date: Mon, 15 Apr 2024 15:53:38 -0400 Subject: [PATCH 14/38] Pass usage options via nameref variable that is also used by getops Move docker file creation to more logical location --- pkg/deploy/generator/scripts/gatewayVMSS.sh | 30 ++++++++++++--------- pkg/deploy/generator/scripts/rpVMSS.sh | 26 ++++++++++-------- 2 files changed, 32 insertions(+), 24 deletions(-) diff --git a/pkg/deploy/generator/scripts/gatewayVMSS.sh b/pkg/deploy/generator/scripts/gatewayVMSS.sh index 3751446891e..64b4232309f 100644 --- a/pkg/deploy/generator/scripts/gatewayVMSS.sh +++ b/pkg/deploy/generator/scripts/gatewayVMSS.sh @@ -28,15 +28,18 @@ main() { } usage() { - log "$(basename "$0") [-dplsrfui] + local -n options="$1" + log "$(basename "$0") [$options] -d Configure Disk Partitions -p Configure rpm repositories, import required rpm keys, update & install packages with dnf -l Configure logrotate.conf -s Make selinux modifications required for ARO RP -r Configure sshd - Allow password authenticaiton -f Configure firewalld default zone rules - -u Pull container images and configure systemd unit files for ARO RP + -u Configure systemd unit files for ARO RP -i Pull container images + + Note: steps will be executed in the order that flags are provided " } @@ -45,15 +48,16 @@ usage() { # # This is useful for local testing, or possibly modifying the bootstrap execution via environment variables in the deployment pipeline parse_run_options() { - local -a options=("$1") + # shellcheck disable=SC2206 + local -a options=(${1:-}) if [ "${#options[@]}" -eq 0 ]; then log "Running all steps" return 0 fi local OPTIND - - while getopts "dplsrfui" options; do + local -r allowed_options="dplsrfui" + while getopts ${allowed_options} options; do case "${options}" in d) log "Running step configure_disk_partitions" @@ -88,7 +92,7 @@ parse_run_options() { pull_container_images ;; *) - usage + usage allowed_options abort "Unkown option provided" ;; esac @@ -372,12 +376,12 @@ configure_firewalld_rules() { sysctl --system - enable_ports=( + local -ra enable_ports=( + "80/tcp" + "8081/tcp" "443/tcp" - "444/tcp" - "445/tcp" - "2222/tcp" ) + log "Enabling ports ${enable_ports[*]} on default firewalld zone" # shellcheck disable=SC2068 for port in ${enable_ports[@]}; do @@ -392,8 +396,6 @@ configure_firewalld_rules() { pull_container_images() { log "starting" - echo "logging into prod acr" - # The managed identity that the VM runs as only has a single roleassignment. # This role assignment is ACRPull which is not necessarily present in the # subscription we're deploying into. If the identity does not have any @@ -404,11 +406,13 @@ pull_container_images() { # Suppress emulation output for podman instead of docker for az acr compatability mkdir -p /etc/containers/ + mkdir -p /root/.docker touch /etc/containers/nodocker - mkdir -p /root/.docker + # This name is used in the case that az acr login searches for this in it's environment local -r REGISTRY_AUTH_FILE="/root/.docker/config.json" + log "logging into prod acr" az acr login --name "$(sed -e 's|.*/||' <<<"$ACRRESOURCEID")" MDMIMAGE="${RPIMAGE%%/*}/${MDMIMAGE##*/}" diff --git a/pkg/deploy/generator/scripts/rpVMSS.sh b/pkg/deploy/generator/scripts/rpVMSS.sh index f978ef2e00a..3c00da1185c 100644 --- a/pkg/deploy/generator/scripts/rpVMSS.sh +++ b/pkg/deploy/generator/scripts/rpVMSS.sh @@ -27,15 +27,18 @@ main() { } usage() { - log "$(basename "$0") [-dplsrfui] + local -n options="$1" + log "$(basename "$0") [$options] -d Configure Disk Partitions -p Configure rpm repositories, import required rpm keys, update & install packages with dnf -l Configure logrotate.conf -s Make selinux modifications required for ARO RP -r Configure sshd - Allow password authenticaiton -f Configure firewalld default zone rules - -u Pull container images and configure systemd unit files for ARO RP + -u Configure systemd unit files for ARO RP -i Pull container images + + Note: steps will be executed in the order that flags are provided " } @@ -44,15 +47,16 @@ usage() { # # This is useful for local testing, or possibly modifying the bootstrap execution via environment variables in the deployment pipeline parse_run_options() { - local -a options=("$1") + # shellcheck disable=SC2206 + local -a options=(${1:-}) if [ "${#options[@]}" -eq 0 ]; then log "Running all steps" return 0 fi local OPTIND - - while getopts "dplsrfui" options; do + local -r allowed_options="dplsrfui" + while getopts ${allowed_options} options; do case "${options}" in d) log "Running step configure_disk_partitions" @@ -80,7 +84,6 @@ parse_run_options() { ;; u) log "Running pull_container_images & configure_system_services" - pull_container_images configure_system_services ;; i) @@ -88,7 +91,7 @@ parse_run_options() { pull_container_images ;; *) - usage + usage allowed_options abort "Unkown option provided" ;; esac @@ -359,12 +362,13 @@ configure_firewalld_rules() { sysctl --system - enable_ports=( + local -ra enable_ports=( "443/tcp" "444/tcp" "445/tcp" "2222/tcp" ) + log "Enabling ports ${enable_ports[*]} on default firewalld zone" # shellcheck disable=SC2068 for port in ${enable_ports[@]}; do @@ -379,8 +383,6 @@ configure_firewalld_rules() { pull_container_images() { log "starting" - echo "logging into prod acr" - # The managed identity that the VM runs as only has a single roleassignment. # This role assignment is ACRPull which is not necessarily present in the # subscription we're deploying into. If the identity does not have any @@ -391,11 +393,13 @@ pull_container_images() { # Suppress emulation output for podman instead of docker for az acr compatability mkdir -p /etc/containers/ + mkdir -p /root/.docker touch /etc/containers/nodocker - mkdir -p /root/.docker + # This name is used in the case that az acr login searches for this in it's environment local -r REGISTRY_AUTH_FILE="/root/.docker/config.json" + log "logging into prod acr" az acr login --name "$(sed -e 's|.*/||' <<<"$ACRRESOURCEID")" MDMIMAGE="${RPIMAGE%%/*}/${MDMIMAGE##*/}" From df11d619c872a45a80ce83b3b25552e37164ebc0 Mon Sep 17 00:00:00 2001 From: Steven Fairchild Date: Mon, 15 Apr 2024 15:54:12 -0400 Subject: [PATCH 15/38] Port changes to devProxyVMSS.sh --- pkg/deploy/assets/env-development.json | 2 +- pkg/deploy/assets/gateway-production.json | 2 +- pkg/deploy/assets/rp-production.json | 2 +- pkg/deploy/generator/scripts/devProxyVMSS.sh | 440 ++++++++++++++++--- 4 files changed, 378 insertions(+), 68 deletions(-) diff --git a/pkg/deploy/assets/env-development.json b/pkg/deploy/assets/env-development.json index 10057c04528..1da1cb9fb5b 100644 --- a/pkg/deploy/assets/env-development.json +++ b/pkg/deploy/assets/env-development.json @@ -296,7 +296,7 @@ "autoUpgradeMinorVersion": true, "settings": {}, "protectedSettings": { - "script": "[base64(concat(base64ToString('c2V0IC1leAoK'),'PROXYIMAGE=$(base64 -d \u003c\u003c\u003c''',base64(parameters('proxyImage')),''')\n','PROXYIMAGEAUTH=$(base64 -d \u003c\u003c\u003c''',base64(parameters('proxyImageAuth')),''')\n','PROXYCERT=''',parameters('proxyCert'),'''\n','PROXYCLIENTCERT=''',parameters('proxyClientCert'),'''\n','PROXYKEY=''',parameters('proxyKey'),'''\n','\n',base64ToString('I0FkZGluZyByZXRyeSBsb2dpYyB0byB5dW0gY29tbWFuZHMgaW4gb3JkZXIgdG8gYXZvaWQgc3RhbGxpbmcgb3V0IG9uIHJlc291cmNlIGxvY2tzCmVjaG8gInJ1bm5pbmcgUkhVSSBmaXgiCmZvciBhdHRlbXB0IGluIHsxLi41fTsgZG8KICB5dW0gdXBkYXRlIC15IC0tZGlzYWJsZXJlcG89JyonIC0tZW5hYmxlcmVwbz0ncmh1aS1taWNyb3NvZnQtYXp1cmUqJyAmJiBicmVhawogIGlmIFtbICR7YXR0ZW1wdH0gLWx0IDUgXV07IHRoZW4gc2xlZXAgMTA7IGVsc2UgZXhpdCAxOyBmaQpkb25lCgplY2hvICJydW5uaW5nIHl1bSB1cGRhdGUiCmZvciBhdHRlbXB0IGluIHsxLi41fTsgZG8KICB5dW0gLXkgLXggV0FMaW51eEFnZW50IC14IFdBTGludXhBZ2VudC11ZGV2IHVwZGF0ZSAtLWFsbG93ZXJhc2luZyAmJiBicmVhawogIGlmIFtbICR7YXR0ZW1wdH0gLWx0IDUgXV07IHRoZW4gc2xlZXAgMTA7IGVsc2UgZXhpdCAxOyBmaQpkb25lCgplY2hvICJpbnN0YWxsaW5nIHBvZG1hbi1kb2NrZXIiCmZvciBhdHRlbXB0IGluIHsxLi41fTsgZG8KICB5dW0gLXkgaW5zdGFsbCBwb2RtYW4tZG9ja2VyICYmIGJyZWFrCiAgaWYgW1sgJHthdHRlbXB0fSAtbHQgNSBdXTsgdGhlbiBzbGVlcCAxMDsgZWxzZSBleGl0IDE7IGZpCmRvbmUKCmZpcmV3YWxsLWNtZCAtLWFkZC1wb3J0PTQ0My90Y3AgLS1wZXJtYW5lbnQKCm1rZGlyIC9yb290Ly5kb2NrZXIKY2F0ID4vcm9vdC8uZG9ja2VyL2NvbmZpZy5qc29uIDw8RU9GCnsKCSJhdXRocyI6IHsKCQkiJHtQUk9YWUlNQUdFJSUvKn0iOiB7CgkJCSJhdXRoIjogIiRQUk9YWUlNQUdFQVVUSCIKCQl9Cgl9Cn0KRU9GCgpta2RpciAtcCAvZXRjL2NvbnRhaW5lcnMvCnRvdWNoIC9ldGMvY29udGFpbmVycy9ub2RvY2tlcgoKZG9ja2VyIHB1bGwgIiRQUk9YWUlNQUdFIgoKbWtkaXIgL2V0Yy9wcm94eQpiYXNlNjQgLWQgPDw8IiRQUk9YWUNFUlQiID4vZXRjL3Byb3h5L3Byb3h5LmNydApiYXNlNjQgLWQgPDw8IiRQUk9YWUtFWSIgPi9ldGMvcHJveHkvcHJveHkua2V5CmJhc2U2NCAtZCA8PDwiJFBST1hZQ0xJRU5UQ0VSVCIgPi9ldGMvcHJveHkvcHJveHktY2xpZW50LmNydApjaG93biAtUiAxMDAwOjEwMDAgL2V0Yy9wcm94eQpjaG1vZCAwNjAwIC9ldGMvcHJveHkvcHJveHkua2V5CgpjYXQgPi9ldGMvc3lzY29uZmlnL3Byb3h5IDw8RU9GClBST1hZX0lNQUdFPSckUFJPWFlJTUFHRScKRU9GCgpjYXQgPi9ldGMvc3lzdGVtZC9zeXN0ZW0vcHJveHkuc2VydmljZSA8PCdFT0YnCltVbml0XQpBZnRlcj1uZXR3b3JrLW9ubGluZS50YXJnZXQKV2FudHM9bmV0d29yay1vbmxpbmUudGFyZ2V0CgpbU2VydmljZV0KRW52aXJvbm1lbnRGaWxlPS9ldGMvc3lzY29uZmlnL3Byb3h5CkV4ZWNTdGFydFByZT0tL3Vzci9iaW4vZG9ja2VyIHJtIC1mICVuCkV4ZWNTdGFydD0vdXNyL2Jpbi9kb2NrZXIgcnVuIC0tcm0gLS1uYW1lICVuIC1wIDQ0Mzo4NDQzIC12IC9ldGMvcHJveHk6L3NlY3JldHMgJFBST1hZX0lNQUdFCkV4ZWNTdG9wPS91c3IvYmluL2RvY2tlciBzdG9wICVuClJlc3RhcnQ9YWx3YXlzClJlc3RhcnRTZWM9MQpTdGFydExpbWl0SW50ZXJ2YWw9MAoKW0luc3RhbGxdCldhbnRlZEJ5PW11bHRpLXVzZXIudGFyZ2V0CkVPRgoKc3lzdGVtY3RsIGVuYWJsZSBwcm94eS5zZXJ2aWNlCgpjYXQgPi9ldGMvY3Jvbi53ZWVrbHkvcHVsbC1pbWFnZSA8PCdFT0YnCiMhL2Jpbi9iYXNoCgpkb2NrZXIgcHVsbCAkUFJPWFlJTUFHRQpzeXN0ZW1jdGwgcmVzdGFydCBwcm94eS5zZXJ2aWNlCkVPRgpjaG1vZCAreCAvZXRjL2Nyb24ud2Vla2x5L3B1bGwtaW1hZ2UKCmNhdCA+L2V0Yy9jcm9uLndlZWtseS95dW11cGRhdGUgPDwnRU9GJwojIS9iaW4vYmFzaAoKeXVtIHVwZGF0ZSAteQpFT0YKY2htb2QgK3ggL2V0Yy9jcm9uLndlZWtseS95dW11cGRhdGUKCmNhdCA+L2V0Yy9jcm9uLmRhaWx5L3Jlc3RhcnQtcHJveHkgPDwnRU9GJwojIS9iaW4vYmFzaAoKc3lzdGVtY3RsIHJlc3RhcnQgcHJveHkuc2VydmljZQpFT0YKY2htb2QgK3ggL2V0Yy9jcm9uLmRhaWx5L3Jlc3RhcnQtcHJveHkKCigKCXNsZWVwIDMwCglyZWJvb3QKKSAmCg==')))]" + "script": "[base64(concat(base64ToString('c2V0IC1leAoK'),'PROXYIMAGE=$(base64 -d \u003c\u003c\u003c''',base64(parameters('proxyImage')),''')\n','PROXYIMAGEAUTH=$(base64 -d \u003c\u003c\u003c''',base64(parameters('proxyImageAuth')),''')\n','PROXYCERT=''',parameters('proxyCert'),'''\n','PROXYCLIENTCERT=''',parameters('proxyClientCert'),'''\n','PROXYKEY=''',parameters('proxyKey'),'''\n','\n',base64ToString('IyEvYmluL2Jhc2gKCnNldCAtbyBlcnJleGl0IFwKICAgIC1vIG5vdW5zZXQKCmlmIFsgIiR7REVCVUc6LWZhbHNlfSIgPT0gdHJ1ZSBdOyB0aGVuCiAgICBzZXQgLXgKZmkKCm1haW4oKSB7CiAgICBwYXJzZV9ydW5fb3B0aW9ucyAiJEAiCgogICAgY29uZmlndXJlX2FuZF9pbnN0YWxsX2RuZl9wa2dzX3JlcG9zCgogICAgY29uZmlndXJlX2ZpcmV3YWxsZF9ydWxlcwogICAgcHVsbF9jb250YWluZXJfaW1hZ2VzCiAgICBjb25maWd1cmVfc3lzdGVtX3NlcnZpY2VzCiAgICByZWJvb3Rfdm0KfQoKdXNhZ2UoKSB7CiAgICBsb2NhbCAtbiBvcHRpb25zPSIkMSIKICAgIGxvZyAiJChiYXNlbmFtZSAiJDAiKSBbJG9wdGlvbnNdCiAgICAgICAgLXAgQ29uZmlndXJlIHJwbSByZXBvc2l0b3JpZXMsIGltcG9ydCByZXF1aXJlZCBycG0ga2V5cywgdXBkYXRlICYgaW5zdGFsbCBwYWNrYWdlcyB3aXRoIGRuZgogICAgICAgIC1mIENvbmZpZ3VyZSBmaXJld2FsbGQgZGVmYXVsdCB6b25lIHJ1bGVzCiAgICAgICAgLXUgQ29uZmlndXJlIHN5c3RlbWQgdW5pdCBmaWxlcyBmb3IgQVJPIFJQCiAgICAgICAgLWkgUHVsbCBjb250YWluZXIgaW1hZ2VzCgogICAgICAgIE5vdGU6IHN0ZXBzIHdpbGwgYmUgZXhlY3V0ZWQgaW4gdGhlIG9yZGVyIHRoYXQgZmxhZ3MgYXJlIHByb3ZpZGVkCiAgICAiCn0KCiMgcGFyc2VfcnVuX29wdGlvbnMgdGFrZXMgYWxsIGFyZ3VlbWVudHMgcGFzc2VkIHRvIG1haW4gYW5kIHBhcnNlcyB0aGVtCiMgYWxsb3dpbmcgaW5kaXZpZHVhbCBzdGVwKHMpIHRvIGJlIHJhbiwgcmF0aGVyIHRoYW4gYWxsIHN0ZXBzCiMKIyBUaGlzIGlzIHVzZWZ1bCBmb3IgbG9jYWwgdGVzdGluZywgb3IgcG9zc2libHkgbW9kaWZ5aW5nIHRoZSBib290c3RyYXAgZXhlY3V0aW9uIHZpYSBlbnZpcm9ubWVudCB2YXJpYWJsZXMgaW4gdGhlIGRlcGxveW1lbnQgcGlwZWxpbmUKcGFyc2VfcnVuX29wdGlvbnMoKSB7CiAgICAjIHNoZWxsY2hlY2sgZGlzYWJsZT1TQzIyMDYKICAgIGxvY2FsIC1hIG9wdGlvbnM9KCR7MTotfSkKICAgIGlmIFsgIiR7I29wdGlvbnNbQF19IiAtZXEgMCBdOyB0aGVuCiAgICAgICAgbG9nICJSdW5uaW5nIGFsbCBzdGVwcyIKICAgICAgICByZXR1cm4gMAogICAgZmkKCiAgICBsb2NhbCBPUFRJTkQKCWxvY2FsIC1yIGFsbG93ZWRfb3B0aW9ucz0icGZ1aSIKICAgIHdoaWxlIGdldG9wdHMgJHthbGxvd2VkX29wdGlvbnN9IG9wdGlvbnM7IGRvCiAgICAgICAgY2FzZSAiJHtvcHRpb25zfSIgaW4KICAgICAgICAgICAgcCkKICAgICAgICAgICAgICAgIGxvZyAiUnVubmluZyBzdGVwIGNvbmZpZ3VyZV9hbmRfaW5zdGFsbF9kbmZfcGtnc19yZXBvcyIKICAgICAgICAgICAgICAgIGNvbmZpZ3VyZV9hbmRfaW5zdGFsbF9kbmZfcGtnc19yZXBvcwogICAgICAgICAgICAgICAgOzsKICAgICAgICAgICAgZikKICAgICAgICAgICAgICAgIGxvZyAiUnVubmluZyBjb25maWd1cmVfZmlyZXdhbGxkX3J1bGVzIgogICAgICAgICAgICAgICAgY29uZmlndXJlX2ZpcmV3YWxsZF9ydWxlcwogICAgICAgICAgICAgICAgOzsKICAgICAgICAgICAgdSkKICAgICAgICAgICAgICAgIGxvZyAiUnVubmluZyBwdWxsX2NvbnRhaW5lcl9pbWFnZXMgJiBjb25maWd1cmVfc3lzdGVtX3NlcnZpY2VzIgogICAgICAgICAgICAgICAgY29uZmlndXJlX3N5c3RlbV9zZXJ2aWNlcwogICAgICAgICAgICAgICAgOzsKICAgICAgICAgICAgaSkKICAgICAgICAgICAgICAgIGxvZyAiUnVubmluZyBwdWxsX2NvbnRhaW5lcl9pbWFnZXMiCiAgICAgICAgICAgICAgICBwdWxsX2NvbnRhaW5lcl9pbWFnZXMgCiAgICAgICAgICAgICAgICA7OwogICAgICAgICAgICAqKQogICAgICAgICAgICAgICAgdXNhZ2UgYWxsb3dlZF9vcHRpb25zCiAgICAgICAgICAgICAgICBhYm9ydCAiVW5rb3duIG9wdGlvbiBwcm92aWRlZCIKICAgICAgICAgICAgICAgIDs7CiAgICAgICAgZXNhYwogICAgZG9uZQogICAgCiAgICBleGl0IDAKfQoKIyBjb25maWd1cmVfYW5kX2luc3RhbGxfZG5mX3BrZ3NfcmVwb3MKY29uZmlndXJlX2FuZF9pbnN0YWxsX2RuZl9wa2dzX3JlcG9zKCkgewogICAgbG9nICJzdGFydGluZyIKCiAgICAjIHRyYW5zYWN0aW9uIGF0dGVtcHQgcmV0cnkgdGltZSBpbiBzZWNvbmRzCiAgICBsb2NhbCAtcmkgcmV0cnlfd2FpdF90aW1lPTYwCiAgICBjb25maWd1cmVfcmh1aV9yZXBvIHJldHJ5X3dhaXRfdGltZQoKICAgIGxvY2FsIC1hciBleGNsdWRlX3BrZ3M9KAogICAgICAgICIteCBXQUxpbnV4QWdlbnQiCiAgICAgICAgIi14IFdBTGludXhBZ2VudC11ZGV2IgogICAgKQoKICAgIGRuZl91cGRhdGVfcGtncyBleGNsdWRlX3BrZ3MgcmV0cnlfd2FpdF90aW1lCgogICAgbG9jYWwgLXJhIHJlcG9fcnBtX3BrZ3M9KAogICAgICAgIGh0dHBzOi8vZGwuZmVkb3JhcHJvamVjdC5vcmcvcHViL2VwZWwvZXBlbC1yZWxlYXNlLWxhdGVzdC04Lm5vYXJjaC5ycG0KICAgICkKCiAgICBsb2NhbCAtcmEgaW5zdGFsbF9wa2dzPSgKICAgICAgICBwb2RtYW4KICAgICAgICBwb2RtYW4tZG9ja2VyCiAgICApCgogICAgZG5mX2luc3RhbGxfcGtncyByZXBvX3JwbV9wa2dzIHJldHJ5X3dhaXRfdGltZQogICAgZG5mX2luc3RhbGxfcGtncyBpbnN0YWxsX3BrZ3MgcmV0cnlfd2FpdF90aW1lCgoJbG9jYWwgLXIgY3Jvbl93ZWVrbHlfZG5mX3VwZGF0ZV9maWxlbmFtZT0nL2V0Yy9jcm9uLndlZWtseS9kbmZ1cGRhdGUnCglsb2NhbCAtciBjcm9uX3dlZWtseV9kbmZfdXBkYXRlX2ZpbGU9IiMhL2Jpbi9iYXNoCmRuZiB1cGRhdGUgLXkiCgoJd3JpdGVfZmlsZSBjcm9uX3dlZWtseV9kbmZfdXBkYXRlX2ZpbGVuYW1lIGNyb25fd2Vla2x5X2RuZl91cGRhdGVfZmlsZSB0cnVlCgljaG1vZCAreCAiJGNyb25fd2Vla2x5X2RuZl91cGRhdGVfZmlsZW5hbWUiCn0KCiMgY29uZmlndXJlX3JodWlfcmVwbwpjb25maWd1cmVfcmh1aV9yZXBvKCkgewogICAgbG9nICJzdGFydGluZyIKCiAgICBsb2NhbCAtcmEgY21kPSgKICAgICAgICBkbmYKICAgICAgICB1cGRhdGUKICAgICAgICAteQogICAgICAgIC0tZGlzYWJsZXJlcG89JyonCiAgICAgICAgLS1lbmFibGVyZXBvPSdyaHVpLW1pY3Jvc29mdC1henVyZSonCiAgICApCgogICAgbG9nICJydW5uaW5nIFJIVUkgcGFja2FnZSB1cGRhdGVzIgogICAgcmV0cnkgY21kICIkMSIKfQoKIyByZXRyeSBBZGRpbmcgcmV0cnkgbG9naWMgdG8geXVtIGNvbW1hbmRzIGluIG9yZGVyIHRvIGF2b2lkIHN0YWxsaW5nIG91dCBvbiByZXNvdXJjZSBsb2NrcwpyZXRyeSgpIHsKICAgIGxvY2FsIC1uIGNtZF9yZXRyeT0iJDEiCiAgICBsb2NhbCAtbiB3YWl0X3RpbWU9IiQyIgoKICAgIGZvciBhdHRlbXB0IGluIHsxLi41fTsgZG8KICAgICAgICBsb2cgImF0dGVtcHQgIyR7YXR0ZW1wdH0gLSAke0ZVTkNOQU1FWzJdfSIKICAgICAgICAke2NtZF9yZXRyeVtAXX0gJgoKICAgICAgICB3YWl0ICQhICYmIGJyZWFrCiAgICAgICAgaWYgW1sgJHthdHRlbXB0fSAtbHQgNSBdXTsgdGhlbgogICAgICAgICAgICBzbGVlcCAiJHdhaXRfdGltZSIKICAgICAgICBlbHNlCiAgICAgICAgICAgIGFib3J0ICJhdHRlbXB0ICMke2F0dGVtcHR9IC0gRmFpbGVkIHRvIHVwZGF0ZSBwYWNrYWdlcyIKICAgICAgICBmaQogICAgZG9uZQp9CgojIGRuZl91cGRhdGVfcGtncwpkbmZfdXBkYXRlX3BrZ3MoKSB7CiAgICBsb2NhbCAtbiBleGNsdWRlcz0iJDEiCiAgICBsb2cgInN0YXJ0aW5nIgoKICAgIGxvY2FsIC1yYSBjbWQ9KAogICAgICAgIGRuZgogICAgICAgIC15CiAgICAgICAgJHtleGNsdWRlc1tAXX0KICAgICAgICB1cGRhdGUKICAgICAgICAtLWFsbG93ZXJhc2luZwogICAgKQoKICAgIGxvZyAiVXBkYXRpbmcgYWxsIHBhY2thZ2VzIgogICAgcmV0cnkgY21kICIkMiIKfQoKIyBkbmZfaW5zdGFsbF9wa2dzCmRuZl9pbnN0YWxsX3BrZ3MoKSB7CiAgICBsb2NhbCAtbiBwa2dzPSIkMSIKICAgIGxvZyAic3RhcnRpbmciCgogICAgbG9jYWwgLXJhIGNtZD0oCiAgICAgICAgZG5mCiAgICAgICAgLXkKICAgICAgICBpbnN0YWxsCiAgICAgICAgJHtwa2dzW0BdfQogICAgKQoKICAgIGxvZyAiQXR0ZW1wdGluZyB0byBpbnN0YWxsIHBhY2thZ2VzOiAke3BrZ3NbKl19IgogICAgcmV0cnkgY21kICIkMiIKfQoKIyBjb25maWd1cmVfbG9ncm90YXRlIGNsb2JiZXJzIC9ldGMvbG9ncm90YXRlLmNvbmYKY29uZmlndXJlX2xvZ3JvdGF0ZSgpIHsKICAgIGxvZyAic3RhcnRpbmciCgogICAgbG9jYWwgLXIgbG9ncm90YXRlX2NvbmZfZmlsZW5hbWU9Jy9ldGMvbG9ncm90YXRlLmNvbmYnCiAgICBsb2NhbCAtciBsb2dyb3RhdGVfY29uZl9maWxlPScjIHNlZSAibWFuIGxvZ3JvdGF0ZSIgZm9yIGRldGFpbHMKIyByb3RhdGUgbG9nIGZpbGVzIHdlZWtseQp3ZWVrbHkKCiMga2VlcCAyIHdlZWtzIHdvcnRoIG9mIGJhY2tsb2dzCnJvdGF0ZSAyCgojIGNyZWF0ZSBuZXcgKGVtcHR5KSBsb2cgZmlsZXMgYWZ0ZXIgcm90YXRpbmcgb2xkIG9uZXMKY3JlYXRlCgojIHVzZSBkYXRlIGFzIGEgc3VmZml4IG9mIHRoZSByb3RhdGVkIGZpbGUKZGF0ZWV4dAoKIyB1bmNvbW1lbnQgdGhpcyBpZiB5b3Ugd2FudCB5b3VyIGxvZyBmaWxlcyBjb21wcmVzc2VkCmNvbXByZXNzCgojIFJQTSBwYWNrYWdlcyBkcm9wIGxvZyByb3RhdGlvbiBpbmZvcm1hdGlvbiBpbnRvIHRoaXMgZGlyZWN0b3J5CmluY2x1ZGUgL2V0Yy9sb2dyb3RhdGUuZAoKIyBubyBwYWNrYWdlcyBvd24gd3RtcCBhbmQgYnRtcCAtLSB3ZSB3aWxsIHJvdGF0ZSB0aGVtIGhlcmUKL3Zhci9sb2cvd3RtcCB7CiAgICBtb250aGx5CiAgICBjcmVhdGUgMDY2NCByb290IHV0bXAKICAgICAgICBtaW5zaXplIDFNCiAgICByb3RhdGUgMQp9CgovdmFyL2xvZy9idG1wIHsKICAgIG1pc3NpbmdvawogICAgbW9udGhseQogICAgY3JlYXRlIDA2MDAgcm9vdCB1dG1wCiAgICByb3RhdGUgMQp9JwoKICAgIHdyaXRlX2ZpbGUgbG9ncm90YXRlX2NvbmZfZmlsZW5hbWUgbG9ncm90YXRlX2NvbmZfZmlsZSB0cnVlCn0KCiMgY29uZmlndXJlX2ZpcmV3YWxsZF9ydWxlcwpjb25maWd1cmVfZmlyZXdhbGxkX3J1bGVzKCkgewogICAgbG9nICJzdGFydGluZyIKCiAgICAjIGh0dHBzOi8vYWNjZXNzLnJlZGhhdC5jb20vc2VjdXJpdHkvY3ZlL2N2ZS0yMDIwLTEzNDAxCiAgICBsb2NhbCAtciBwcmVmaXg9Ii9ldGMvc3lzY3RsLmQiCiAgICBsb2NhbCAtciBkaXNhYmxlX2FjY2VwdF9yYV9jb25mX2ZpbGVuYW1lPSIkcHJlZml4LzAyLWRpc2FibGUtYWNjZXB0LXJhLmNvbmYiCiAgICBsb2NhbCAtciBkaXNhYmxlX2FjY2VwdF9yYV9jb25mX2ZpbGU9Im5ldC5pcHY2LmNvbmYuYWxsLmFjY2VwdF9yYT0wIgoKICAgIHdyaXRlX2ZpbGUgZGlzYWJsZV9hY2NlcHRfcmFfY29uZl9maWxlbmFtZSBkaXNhYmxlX2FjY2VwdF9yYV9jb25mX2ZpbGUgdHJ1ZQoKICAgIGxvY2FsIC1yIGRpc2FibGVfY29yZV9maWxlbmFtZT0iJHByZWZpeC8wMS1kaXNhYmxlLWNvcmUuY29uZiIKICAgIGxvY2FsIC1yIGRpc2FibGVfY29yZV9maWxlPSJrZXJuZWwuY29yZV9wYXR0ZXJuID0gfC9iaW4vdHJ1ZQogICAgIgogICAgd3JpdGVfZmlsZSBkaXNhYmxlX2NvcmVfZmlsZW5hbWUgZGlzYWJsZV9jb3JlX2ZpbGUgdHJ1ZQoKICAgIHN5c2N0bCAtLXN5c3RlbQoKICAgIGxvY2FsIC1yYSBlbmFibGVfcG9ydHM9KAogICAgICAgICI0NDMvdGNwIgogICAgKQoKICAgIGxvZyAiRW5hYmxpbmcgcG9ydHMgJHtlbmFibGVfcG9ydHNbKl19IG9uIGRlZmF1bHQgZmlyZXdhbGxkIHpvbmUiCiAgICAjIHNoZWxsY2hlY2sgZGlzYWJsZT1TQzIwNjgKICAgIGZvciBwb3J0IGluICR7ZW5hYmxlX3BvcnRzW0BdfTsgZG8KICAgICAgICBsb2cgIkVuYWJsaW5nIHBvcnQgJHBvcnQgbm93IgogICAgICAgIGZpcmV3YWxsLWNtZCAiLS1hZGQtcG9ydD0kcG9ydCIKICAgIGRvbmUKCiAgICBmaXJld2FsbC1jbWQgLS1ydW50aW1lLXRvLXBlcm1hbmVudAp9CgojIHB1bGxfY29udGFpbmVyX2ltYWdlcwpwdWxsX2NvbnRhaW5lcl9pbWFnZXMoKSB7CiAgICBsb2cgInN0YXJ0aW5nIgoKICAgICMgVGhlIG1hbmFnZWQgaWRlbnRpdHkgdGhhdCB0aGUgVk0gcnVucyBhcyBvbmx5IGhhcyBhIHNpbmdsZSByb2xlYXNzaWdubWVudC4KICAgICMgVGhpcyByb2xlIGFzc2lnbm1lbnQgaXMgQUNSUHVsbCB3aGljaCBpcyBub3QgbmVjZXNzYXJpbHkgcHJlc2VudCBpbiB0aGUKICAgICMgc3Vic2NyaXB0aW9uIHdlJ3JlIGRlcGxveWluZyBpbnRvLiAgSWYgdGhlIGlkZW50aXR5IGRvZXMgbm90IGhhdmUgYW55CiAgICAjIHJvbGUgYXNzaWdubWVudHMgc2NvcGVkIG9uIHRoZSBzdWJzY3JpcHRpb24gd2UncmUgZGVwbG95aW5nIGludG8sIGl0IHdpbGwKICAgICMgbm90IHNob3cgb24gYXogbG9naW4gLWksIHdoaWNoIGlzIHdoeSB0aGUgYmVsb3cgbGluZSBpcyBjb21tZW50ZWQuCiAgICAjIGF6IGFjY291bnQgc2V0IC1zICIkU1VCU0NSSVBUSU9OSUQiCiAgICBheiBsb2dpbiAtaSAtLWFsbG93LW5vLXN1YnNjcmlwdGlvbnMKCiAgICAjIFN1cHByZXNzIGVtdWxhdGlvbiBvdXRwdXQgZm9yIHBvZG1hbiBpbnN0ZWFkIG9mIGRvY2tlciBmb3IgYXogYWNyIGNvbXBhdGFiaWxpdHkKICAgIG1rZGlyIC1wIC9ldGMvY29udGFpbmVycy8KICAgIG1rZGlyIC1wIC9yb290Ly5kb2NrZXIKICAgIHRvdWNoIC9ldGMvY29udGFpbmVycy9ub2RvY2tlcgoKCSMgVGhpcyBuYW1lIGlzIHVzZWQgaW4gdGhlIGNhc2UgdGhhdCBheiBhY3IgbG9naW4gc2VhcmNoZXMgZm9yIHRoaXMgaW4gaXQncyBlbnZpcm9ubWVudAogICAgbG9jYWwgLXIgUkVHSVNUUllfQVVUSF9GSUxFPSIvcm9vdC8uZG9ja2VyL2NvbmZpZy5qc29uIgoJbG9jYWwgLXIgcmVnaXN0cnlfY29uZmlnX2ZpbGU9InsKCSJhdXRocyI6IHsKCQlcIiR7UFJPWFlJTUFHRSUlLyp9XCI6IHsKCQkJXCJhdXRoXCI6IFwiJFBST1hZSU1BR0VBVVRIXCIKCQl9Cgl9IgoKCXdyaXRlX2ZpbGUgUkVHSVNUUllfQVVUSF9GSUxFIHJlZ2lzdHJ5X2NvbmZpZ19maWxlIHRydWUKCiAgICBsb2cgImxvZ2dpbmcgaW50byBwcm9kIGFjciIKCiAgICBheiBhY3IgbG9naW4gLS1uYW1lICIkKHNlZCAtZSAnc3wuKi98fCcgPDw8IiRBQ1JSRVNPVVJDRUlEIikiCgogICAgZG9ja2VyIHB1bGwgIiRQUk9YWUlNQUdFIgoKICAgIGF6IGxvZ291dAp9CgojIGNvbmZpZ3VyZV9zeXN0ZW1fc2VydmljZXMgY3JlYXRlcywgY29uZmlndXJlcywgYW5kIGVuYWJsZXMgdGhlIGZvbGxvd2luZyBzeXN0ZW1kIHNlcnZpY2VzIGFuZCB0aW1lcnMKIyBzZXJ2aWNlcwojCXByb3h5CmNvbmZpZ3VyZV9zeXN0ZW1fc2VydmljZXMoKSB7Cgljb25maWd1cmVfc2VydmljZV9wcm94eQp9CgojIGVuYWJsZV9hcm9fc2VydmljZXMgZW5hYmxlcyBhbGwgc2VydmljZXMgcmVxdWlyZWQgZm9yIGFybyBycAplbmFibGVfYXJvX3NlcnZpY2VzKCkgewogICAgbG9nICJzdGFydGluZyIKCiAgICBsb2NhbCAtcmEgYXJvX3NlcnZpY2VzPSgKCQlwcm94eQogICAgKQogICAgbG9nICJlbmFibGluZyBhcm8gc2VydmljZXMgJHthcm9fc2VydmljZXNbKl19IgogICAgIyBzaGVsbGNoZWNrIGRpc2FibGU9U0MyMDY4CiAgICBmb3Igc2VydmljZSBpbiAke2Fyb19zZXJ2aWNlc1tAXX07IGRvCiAgICAgICAgbG9nICJFbmFibGluZyAkc2VydmljZSBub3ciCiAgICAgICAgc3lzdGVtY3RsIGVuYWJsZSAiJHNlcnZpY2Uuc2VydmljZSIKICAgIGRvbmUKfQoKIyBjb25maWd1cmVfY2VydHMKY29uZmlndXJlX2NlcnRzKCkgewogICAgbG9nICJzdGFydGluZyIKCgliYXNlNjQgLWQgPDw8IiRQUk9YWUNFUlQiID4vZXRjL3Byb3h5L3Byb3h5LmNydAoJYmFzZTY0IC1kIDw8PCIkUFJPWFlLRVkiID4vZXRjL3Byb3h5L3Byb3h5LmtleQoJYmFzZTY0IC1kIDw8PCIkUFJPWFlDTElFTlRDRVJUIiA+L2V0Yy9wcm94eS9wcm94eS1jbGllbnQuY3J0CgljaG93biAtUiAxMDAwOjEwMDAgL2V0Yy9wcm94eQoJY2htb2QgMDYwMCAvZXRjL3Byb3h5L3Byb3h5LmtleQp9Cgpjb25maWd1cmVfc2VydmljZV9wcm94eSgpIHsKCWxvY2FsIC1yIHN5c2NvbmZpZ19wcm94eV9maWxlbmFtZT0nL2V0Yy9zeXNjb25maWcvcHJveHknCglsb2NhbCAtciBzeXNjb25maWdfcHJveHlfZmlsZT0iUFJPWFlfSU1BR0U9JyRQUk9YWUlNQUdFJyIKCgl3cml0ZV9maWxlIHN5c2NvbmZpZ19wcm94eV9maWxlbmFtZSBzeXNjb25maWdfcHJveHlfZmlsZSB0cnVlCgoJbG9jYWwgLXIgcHJveHlfc2VydmljZV9maWxlbmFtZT0nL2V0Yy9zeXN0ZW1kL3N5c3RlbS9wcm94eS5zZXJ2aWNlJwoJbG9jYWwgLXIgcHJveHlfc2VydmljZV9maWxlPSJbVW5pdF0KQWZ0ZXI9bmV0d29yay1vbmxpbmUudGFyZ2V0CldhbnRzPW5ldHdvcmstb25saW5lLnRhcmdldAoKW1NlcnZpY2VdCkVudmlyb25tZW50RmlsZT0vZXRjL3N5c2NvbmZpZy9wcm94eQpFeGVjU3RhcnRQcmU9LS91c3IvYmluL2RvY2tlciBybSAtZiAlbgpFeGVjU3RhcnQ9L3Vzci9iaW4vZG9ja2VyIHJ1biAtLXJtIC0tbmFtZSAlbiAtcCA0NDM6ODQ0MyAtdiAvZXRjL3Byb3h5Oi9zZWNyZXRzICRQUk9YWV9JTUFHRQpFeGVjU3RvcD0vdXNyL2Jpbi9kb2NrZXIgc3RvcCAlbgpSZXN0YXJ0PWFsd2F5cwpSZXN0YXJ0U2VjPTEKU3RhcnRMaW1pdEludGVydmFsPTAKCltJbnN0YWxsXQpXYW50ZWRCeT1tdWx0aS11c2VyLnRhcmdldCIKCglsb2NhbCAtciBjcm9uX3dlZWtseV9wdWxsX2ltYWdlX2ZpbGVuYW1lPScvZXRjL2Nyb24ud2Vla2x5L3B1bGwtaW1hZ2UnCglsb2NhbCAtciBjcm9uX3dlZWtseV9wdWxsX2ltYWdlX2ZpbGU9IiMhL2Jpbi9iYXNoCmRvY2tlciBwdWxsICRQUk9YWUlNQUdFCnN5c3RlbWN0bCByZXN0YXJ0IHByb3h5LnNlcnZpY2UiCgkKCXdyaXRlX2ZpbGUgY3Jvbl93ZWVrbHlfcHVsbF9pbWFnZV9maWxlbmFtZSBjcm9uX3dlZWtseV9wdWxsX2ltYWdlX2ZpbGUgdHJ1ZQoJY2htb2QgK3ggIiRjcm9uX3dlZWtseV9wdWxsX2ltYWdlX2ZpbGVuYW1lIgoKCWxvY2FsIC1yIGNyb25fZGFpbHlfcmVzdGFydF9wcm94eV9maWxlbmFtZT0nL2V0Yy9jcm9uLmRhaWx5L3Jlc3RhcnQtcHJveHknCglsb2NhbCAtciBjcm9uX2RhaWx5X3Jlc3RhcnRfcHJveHlfZmlsZT0iIyEvYmluL2Jhc2gKc3lzdGVtY3RsIHJlc3RhcnQgcHJveHkuc2VydmljZSIKCQoJd3JpdGVfZmlsZSBjcm9uX2RhaWx5X3Jlc3RhcnRfcHJveHlfZmlsZW5hbWUgY3Jvbl9kYWlseV9yZXN0YXJ0X3Byb3h5X2ZpbGUKCWNobW9kICt4ICIkY3Jvbl9kYWlseV9yZXN0YXJ0X3Byb3h5X2ZpbGVuYW1lIgp9CgojIHdyaXRlX2ZpbGUKIyBBcmdzCiMgMSkgZmlsZW5hbWUgLSBzdHJpbmcKIyAyKSBmaWxlX2NvbnRlbnRzIC0gc3RyaW5nCiMgMykgY2xvYmJlciAtIGJvb2xlYW47IG9wdGlvbmFsIC0gZGVmYXVsdHMgdG8gZmFsc2UKd3JpdGVfZmlsZSgpIHsKICAgIGxvY2FsIC1uIGZpbGVuYW1lPSIkMSIKICAgIGxvY2FsIC1uIGZpbGVfY29udGVudHM9IiQyIgogICAgbG9jYWwgLXIgY2xvYmJlcj0iJHszOi1mYWxzZX0iCgogICAgaWYgJGNsb2JiZXI7IHRoZW4KICAgICAgICBsb2cgIk92ZXJ3cml0aW5nIGZpbGUgJGZpbGVuYW1lIgogICAgICAgIGVjaG8gIiRmaWxlX2NvbnRlbnRzIiA+ICIkZmlsZW5hbWUiCiAgICBlbHNlCiAgICAgICAgbG9nICJBcHBlbmRpbmcgdG8gJGZpbGVuYW1lIgogICAgICAgIGVjaG8gIiRmaWxlX2NvbnRlbnRzIiA+PiAiJGZpbGVuYW1lIgogICAgZmkKfQoKIyByZWJvb3Rfdm0gcmVzdG9yZXMgYWxsIHNlbGludXggZmlsZSBjb250ZXh0cywgd2FpdHMgMzAgc2Vjb25kcyB0aGVuIHJlYm9vdHMKcmVib290X3ZtKCkgewogICAgbG9nICJzdGFydGluZyIKCiAgICBjb25maWd1cmVfc2VsaW51eCAidHJ1ZSIKICAgIChzbGVlcCAzMCAmJiBsb2cgInJlYm9vdGluZyB2bSBub3ciOyByZWJvb3QpICYKfQoKIyBsb2cgaXMgYSB3cmFwcGVyIGZvciBlY2hvIHRoYXQgaW5jbHVkZXMgdGhlIGZ1bmN0aW9uIG5hbWUKbG9nKCkgewogICAgbG9jYWwgLXIgbXNnPSIkezE6LSJsb2cgbWVzc2FnZSBpcyBlbXB0eSJ9IgogICAgbG9jYWwgLXIgc3RhY2tfbGV2ZWw9IiR7MjotMX0iCiAgICBlY2hvICIke0ZVTkNOQU1FWyR7c3RhY2tfbGV2ZWx9XX06ICR7bXNnfSIKfQoKIyBhYm9ydCBpcyBhIHdyYXBwZXIgZm9yIGxvZyB0aGF0IGV4aXRzIHdpdGggYW4gZXJyb3IgY29kZQphYm9ydCgpIHsKICAgIGxvY2FsIC1yaSBvcmlnaW5fc3RhY2tsZXZlbD0yCiAgICBsb2cgIiR7MX0iICIkb3JpZ2luX3N0YWNrbGV2ZWwiCiAgICBsb2cgIkV4aXRpbmciCiAgICBleGl0IDEKfQoKZXhwb3J0IEFaVVJFX0NMT1VEX05BTUU9IiR7QVpVUkVDTE9VRE5BTUU6PyJGYWlsZWQgdG8gY2Fycnkgb3ZlciB2YXJpYWJsZXMifSIKCm1haW4gIiRAIgo=')))]" }, "provisionAfterExtensions": [ "Microsoft.Azure.Monitor.AzureMonitorLinuxAgent", diff --git a/pkg/deploy/assets/gateway-production.json b/pkg/deploy/assets/gateway-production.json index e539ddfd02a..ecbbe148c12 100644 --- a/pkg/deploy/assets/gateway-production.json +++ b/pkg/deploy/assets/gateway-production.json @@ -309,7 +309,7 @@ "autoUpgradeMinorVersion": true, "settings": {}, "protectedSettings": { - "script": "[base64(concat(base64ToString('c2V0IC1leAoK'),'ACRRESOURCEID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('acrResourceId')),''')\n','AZURECLOUDNAME=$(base64 -d \u003c\u003c\u003c''',base64(parameters('azureCloudName')),''')\n','AZURESECPACKQUALYSURL=$(base64 -d \u003c\u003c\u003c''',base64(parameters('azureSecPackQualysUrl')),''')\n','AZURESECPACKVSATENANTID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('azureSecPackVSATenantId')),''')\n','DATABASEACCOUNTNAME=$(base64 -d \u003c\u003c\u003c''',base64(parameters('databaseAccountName')),''')\n','DBTOKENCLIENTID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('dbtokenClientId')),''')\n','DBTOKENURL=$(base64 -d \u003c\u003c\u003c''',base64(parameters('dbtokenUrl')),''')\n','MDMFRONTENDURL=$(base64 -d \u003c\u003c\u003c''',base64(parameters('mdmFrontendUrl')),''')\n','MDSDENVIRONMENT=$(base64 -d \u003c\u003c\u003c''',base64(parameters('mdsdEnvironment')),''')\n','FLUENTBITIMAGE=$(base64 -d \u003c\u003c\u003c''',base64(parameters('fluentbitImage')),''')\n','GATEWAYMDSDCONFIGVERSION=$(base64 -d \u003c\u003c\u003c''',base64(parameters('gatewayMdsdConfigVersion')),''')\n','GATEWAYDOMAINS=$(base64 -d \u003c\u003c\u003c''',base64(parameters('gatewayDomains')),''')\n','GATEWAYFEATURES=$(base64 -d \u003c\u003c\u003c''',base64(parameters('gatewayFeatures')),''')\n','KEYVAULTDNSSUFFIX=$(base64 -d \u003c\u003c\u003c''',base64(parameters('keyvaultDNSSuffix')),''')\n','KEYVAULTPREFIX=$(base64 -d \u003c\u003c\u003c''',base64(parameters('keyvaultPrefix')),''')\n','RPIMAGE=$(base64 -d \u003c\u003c\u003c''',base64(parameters('rpImage')),''')\n','RPMDMACCOUNT=$(base64 -d \u003c\u003c\u003c''',base64(parameters('rpMdmAccount')),''')\n','RPMDSDACCOUNT=$(base64 -d \u003c\u003c\u003c''',base64(parameters('rpMdsdAccount')),''')\n','RPMDSDNAMESPACE=$(base64 -d \u003c\u003c\u003c''',base64(parameters('rpMdsdNamespace')),''')\n','MDMIMAGE=''/genevamdm:2.2024.328.1744-c5fb79-20240328t1935''\n','LOCATION=$(base64 -d \u003c\u003c\u003c''',base64(resourceGroup().location),''')\n','SUBSCRIPTIONID=$(base64 -d \u003c\u003c\u003c''',base64(subscription().subscriptionId),''')\n','RESOURCEGROUPNAME=$(base64 -d \u003c\u003c\u003c''',base64(resourceGroup().name),''')\n','\n',base64ToString('IyEvYmluL2Jhc2gKCmVjaG8gInNldHRpbmcgc3NoIHBhc3N3b3JkIGF1dGhlbnRpY2F0aW9uIgojIFdlIG5lZWQgdG8gbWFudWFsbHkgc2V0IFBhc3N3b3JkQXV0aGVudGljYXRpb24gdG8gdHJ1ZSBpbiBvcmRlciBmb3IgdGhlIFZNU1MgQWNjZXNzIEpJVCB0byB3b3JrCnNlZCAtaSAncy9QYXNzd29yZEF1dGhlbnRpY2F0aW9uIG5vL1Bhc3N3b3JkQXV0aGVudGljYXRpb24geWVzL2cnIC9ldGMvc3NoL3NzaGRfY29uZmlnCnN5c3RlbWN0bCByZWxvYWQgc3NoZC5zZXJ2aWNlCgojQWRkaW5nIHJldHJ5IGxvZ2ljIHRvIHl1bSBjb21tYW5kcyBpbiBvcmRlciB0byBhdm9pZCBzdGFsbGluZyBvdXQgb24gcmVzb3VyY2UgbG9ja3MKZWNobyAicnVubmluZyBSSFVJIGZpeCIKZm9yIGF0dGVtcHQgaW4gezEuLjV9OyBkbwogIHl1bSB1cGRhdGUgLXkgLS1kaXNhYmxlcmVwbz0nKicgLS1lbmFibGVyZXBvPSdyaHVpLW1pY3Jvc29mdC1henVyZSonICYmIGJyZWFrCiAgaWYgW1sgJHthdHRlbXB0fSAtbHQgNSBdXTsgdGhlbiBzbGVlcCAxMDsgZWxzZSBleGl0IDE7IGZpCmRvbmUKCmVjaG8gInJ1bm5pbmcgeXVtIHVwZGF0ZSIKZm9yIGF0dGVtcHQgaW4gezEuLjV9OyBkbwogIHl1bSAteSAteCBXQUxpbnV4QWdlbnQgLXggV0FMaW51eEFnZW50LXVkZXYgdXBkYXRlIC0tYWxsb3dlcmFzaW5nICYmIGJyZWFrCiAgaWYgW1sgJHthdHRlbXB0fSAtbHQgNSBdXTsgdGhlbiBzbGVlcCAxMDsgZWxzZSBleGl0IDE7IGZpCmRvbmUKCmVjaG8gImV4dGVuZGluZyBwYXJ0aXRpb24gdGFibGUiCiMgTGludXggYmxvY2sgZGV2aWNlcyBhcmUgaW5jb25zaXN0ZW50bHkgbmFtZWQKIyBpdCdzIGRpZmZpY3VsdCB0byB0aWUgdGhlIGx2bSBwdiB0byB0aGUgcGh5c2ljYWwgZGlzayB1c2luZyAvZGV2L2Rpc2sgZmlsZXMsIHdoaWNoIGlzIHdoeSBsdnMgaXMgdXNlZCBoZXJlCnBoeXNpY2FsX2Rpc2s9IiQobHZzIC1vIGRldmljZXMgLWEgfCBoZWFkIC1uMiB8IHRhaWwgLW4xIHwgY3V0IC1kICcgJyAtZiAzIHwgY3V0IC1kIFwoIC1mIDEgfCB0ciAtZCAnWzpkaWdpdDpdJykiCmdyb3dwYXJ0ICIkcGh5c2ljYWxfZGlzayIgMgoKZWNobyAiZXh0ZW5kaW5nIGZpbGVzeXN0ZW1zIgpsdmV4dGVuZCAtbCArMjAlRlJFRSAvZGV2L3Jvb3R2Zy9yb290bHYKeGZzX2dyb3dmcyAvCgpsdmV4dGVuZCAtbCArMTAwJUZSRUUgL2Rldi9yb290dmcvdmFybHYKeGZzX2dyb3dmcyAvdmFyCgpycG0gLS1pbXBvcnQgaHR0cHM6Ly9kbC5mZWRvcmFwcm9qZWN0Lm9yZy9wdWIvZXBlbC9SUE0tR1BHLUtFWS1FUEVMLTgKcnBtIC0taW1wb3J0IGh0dHBzOi8vcGFja2FnZXMubWljcm9zb2Z0LmNvbS9rZXlzL21pY3Jvc29mdC5hc2MKCmZvciBhdHRlbXB0IGluIHsxLi41fTsgZG8KICB5dW0gLXkgaW5zdGFsbCBodHRwczovL2RsLmZlZG9yYXByb2plY3Qub3JnL3B1Yi9lcGVsL2VwZWwtcmVsZWFzZS1sYXRlc3QtOC5ub2FyY2gucnBtICYmIGJyZWFrCiAgaWYgW1sgJHthdHRlbXB0fSAtbHQgNSBdXTsgdGhlbiBzbGVlcCAxMDsgZWxzZSBleGl0IDE7IGZpCmRvbmUKCmVjaG8gImNvbmZpZ3VyaW5nIGxvZ3JvdGF0ZSIKCiMgZ2F0ZXdheV9sb2dkaXIgaXMgYSByZWFkb25seSB2YXJpYWJsZSB0aGF0IHNwZWNpZmllcyB0aGUgaG9zdCBwYXRoIG1vdW50IHBvaW50IGZvciB0aGUgZ2F0ZXdheSBjb250YWluZXIgbG9nIGZpbGUKIyBmb3IgdGhlIHB1cnBvc2Ugb2Ygcm90YXRpbmcgdGhlIGdhdGV3YXkgbG9ncwpkZWNsYXJlIC1yIGdhdGV3YXlfbG9nZGlyPScvdmFyL2xvZy9hcm8tZ2F0ZXdheScKCmNhdCA+L2V0Yy9sb2dyb3RhdGUuY29uZiA8PEVPRgojIHNlZSAibWFuIGxvZ3JvdGF0ZSIgZm9yIGRldGFpbHMKIyByb3RhdGUgbG9nIGZpbGVzIHdlZWtseQp3ZWVrbHkKCiMga2VlcCAyIHdlZWtzIHdvcnRoIG9mIGJhY2tsb2dzCnJvdGF0ZSAyCgojIGNyZWF0ZSBuZXcgKGVtcHR5KSBsb2cgZmlsZXMgYWZ0ZXIgcm90YXRpbmcgb2xkIG9uZXMKY3JlYXRlCgojIHVzZSBkYXRlIGFzIGEgc3VmZml4IG9mIHRoZSByb3RhdGVkIGZpbGUKZGF0ZWV4dAoKIyB1bmNvbW1lbnQgdGhpcyBpZiB5b3Ugd2FudCB5b3VyIGxvZyBmaWxlcyBjb21wcmVzc2VkCmNvbXByZXNzCgojIFJQTSBwYWNrYWdlcyBkcm9wIGxvZyByb3RhdGlvbiBpbmZvcm1hdGlvbiBpbnRvIHRoaXMgZGlyZWN0b3J5CmluY2x1ZGUgL2V0Yy9sb2dyb3RhdGUuZAoKIyBubyBwYWNrYWdlcyBvd24gd3RtcCBhbmQgYnRtcCAtLSB3ZSdsbCByb3RhdGUgdGhlbSBoZXJlCi92YXIvbG9nL3d0bXAgewogICAgbW9udGhseQogICAgY3JlYXRlIDA2NjQgcm9vdCB1dG1wCiAgICAgICAgbWluc2l6ZSAxTQogICAgcm90YXRlIDEKfQoKL3Zhci9sb2cvYnRtcCB7CiAgICBtaXNzaW5nb2sKICAgIG1vbnRobHkKICAgIGNyZWF0ZSAwNjAwIHJvb3QgdXRtcAogICAgcm90YXRlIDEKfQoKIyBNYXhpbXVtIGxvZyBkaXJlY3Rvcnkgc2l6ZSBpcyAxMDBHIHdpdGggdGhpcyBjb25maWd1cmF0aW9uCiMgU2V0dGluZyBsaW1pdCB0byAxMDBHIHRvIGFsbG93IHNwYWNlIGZvciBvdGhlciBsb2dnaW5nIHNlcnZpY2VzCiMgY29weXRydW5jYXRlIGlzIGEgY3JpdGljYWwgb3B0aW9uIHVzZWQgdG8gcHJldmVudCBsb2dzIGZyb20gYmVpbmcgc2hpcHBlZCB0d2ljZQoke2dhdGV3YXlfbG9nZGlyfSB7CiAgICBzaXplIDIwRwogICAgcm90YXRlIDUKICAgIGNyZWF0ZSAwNjAwIHJvb3Qgcm9vdAogICAgY29weXRydW5jYXRlCiAgICBub29sZGRpcgogICAgY29tcHJlc3MKfQpFT0YKCmVjaG8gImNvbmZpZ3VyaW5nIHl1bSByZXBvc2l0b3J5IGFuZCBydW5uaW5nIHl1bSB1cGRhdGUiCmNhdCA+L2V0Yy95dW0ucmVwb3MuZC9henVyZS5yZXBvIDw8J0VPRicKW2F6dXJlLWNsaV0KbmFtZT1henVyZS1jbGkKYmFzZXVybD1odHRwczovL3BhY2thZ2VzLm1pY3Jvc29mdC5jb20veXVtcmVwb3MvYXp1cmUtY2xpCmVuYWJsZWQ9eWVzCmdwZ2NoZWNrPXllcwoKW2F6dXJlY29yZV0KbmFtZT1henVyZWNvcmUKYmFzZXVybD1odHRwczovL3BhY2thZ2VzLm1pY3Jvc29mdC5jb20veXVtcmVwb3MvYXp1cmVjb3JlCmVuYWJsZWQ9eWVzCmdwZ2NoZWNrPW5vCkVPRgoKc2VtYW5hZ2UgZmNvbnRleHQgLWEgLXQgdmFyX2xvZ190ICIvdmFyL2xvZy9qb3VybmFsKC8uKik/Igpta2RpciAtcCAvdmFyL2xvZy9qb3VybmFsCgpmb3IgYXR0ZW1wdCBpbiB7MS4uNX07IGRvCiAgeXVtIC15IGluc3RhbGwgY2xhbWF2IGF6c2VjLWNsYW1hdiBhenNlYy1tb25pdG9yIGF6dXJlLWNsaSBhenVyZS1tZHNkIGF6dXJlLXNlY3VyaXR5IHBvZG1hbi1kb2NrZXIgb3BlbnNzbC1wZXJsIHB5dGhvbjMgJiYgYnJlYWsKICAjIGhhY2sgLSB3ZSBhcmUgaW5zdGFsbGluZyBweXRob24zIG9uIGhvc3RzIGR1ZSB0byBhbiBpc3N1ZSB3aXRoIEF6dXJlIExpbnV4IEV4dGVuc2lvbnMgaHR0cHM6Ly9naXRodWIuY29tL0F6dXJlL2F6dXJlLWxpbnV4LWV4dGVuc2lvbnMvcHVsbC8xNTA1CiAgaWYgW1sgJHthdHRlbXB0fSAtbHQgNSBdXTsgdGhlbiBzbGVlcCAxMDsgZWxzZSBleGl0IDE7IGZpCmRvbmUKCmVjaG8gImFwcGx5aW5nIGZpcmV3YWxsIHJ1bGVzIgojIGh0dHBzOi8vYWNjZXNzLnJlZGhhdC5jb20vc2VjdXJpdHkvY3ZlL2N2ZS0yMDIwLTEzNDAxCmNhdCA+L2V0Yy9zeXNjdGwuZC8wMi1kaXNhYmxlLWFjY2VwdC1yYS5jb25mIDw8J0VPRicKbmV0LmlwdjYuY29uZi5hbGwuYWNjZXB0X3JhPTAKRU9GCgpjYXQgPi9ldGMvc3lzY3RsLmQvMDEtZGlzYWJsZS1jb3JlLmNvbmYgPDwnRU9GJwprZXJuZWwuY29yZV9wYXR0ZXJuID0gfC9iaW4vdHJ1ZQpFT0YKc3lzY3RsIC0tc3lzdGVtCgpmaXJld2FsbC1jbWQgLS1hZGQtcG9ydD04MC90Y3AgLS1wZXJtYW5lbnQKZmlyZXdhbGwtY21kIC0tYWRkLXBvcnQ9ODA4MS90Y3AgLS1wZXJtYW5lbnQKZmlyZXdhbGwtY21kIC0tYWRkLXBvcnQ9NDQzL3RjcCAtLXBlcm1hbmVudAoKZWNobyAibG9nZ2luZyBpbnRvIHByb2QgYWNyIgpleHBvcnQgQVpVUkVfQ0xPVURfTkFNRT0kQVpVUkVDTE9VRE5BTUUKYXogbG9naW4gLWkgLS1hbGxvdy1uby1zdWJzY3JpcHRpb25zCgojIFRoZSBtYW5hZ2VkIGlkZW50aXR5IHRoYXQgdGhlIFZNIHJ1bnMgYXMgb25seSBoYXMgYSBzaW5nbGUgcm9sZWFzc2lnbm1lbnQuCiMgVGhpcyByb2xlIGFzc2lnbm1lbnQgaXMgQUNSUHVsbCB3aGljaCBpcyBub3QgbmVjZXNzYXJpbHkgcHJlc2VudCBpbiB0aGUKIyBzdWJzY3JpcHRpb24gd2UncmUgZGVwbG95aW5nIGludG8uICBJZiB0aGUgaWRlbnRpdHkgZG9lcyBub3QgaGF2ZSBhbnkKIyByb2xlIGFzc2lnbm1lbnRzIHNjb3BlZCBvbiB0aGUgc3Vic2NyaXB0aW9uIHdlJ3JlIGRlcGxveWluZyBpbnRvLCBpdCB3aWxsCiMgbm90IHNob3cgb24gYXogbG9naW4gLWksIHdoaWNoIGlzIHdoeSB0aGUgYmVsb3cgbGluZSBpcyBjb21tZW50ZWQuCiMgYXogYWNjb3VudCBzZXQgLXMgIiRTVUJTQ1JJUFRJT05JRCIKCiMgU3VwcHJlc3MgZW11bGF0aW9uIG91dHB1dCBmb3IgcG9kbWFuIGluc3RlYWQgb2YgZG9ja2VyIGZvciBheiBhY3IgY29tcGF0YWJpbGl0eQpta2RpciAtcCAvZXRjL2NvbnRhaW5lcnMvCnRvdWNoIC9ldGMvY29udGFpbmVycy9ub2RvY2tlcgoKbWtkaXIgLXAgL3Jvb3QvLmRvY2tlcgpSRUdJU1RSWV9BVVRIX0ZJTEU9Ii9yb290Ly5kb2NrZXIvY29uZmlnLmpzb24iCmF6IGFjciBsb2dpbiAtLW5hbWUgIiQoc2VkIC1lICdzfC4qL3x8JyA8PDwiJEFDUlJFU09VUkNFSUQiKSIKCk1ETUlNQUdFPSIke1JQSU1BR0UlJS8qfS8ke01ETUlNQUdFIyMqL30iCmRvY2tlciBwdWxsICIkTURNSU1BR0UiCmRvY2tlciBwdWxsICIkUlBJTUFHRSIKZG9ja2VyIHB1bGwgIiRGTFVFTlRCSVRJTUFHRSIKCmF6IGxvZ291dAoKZWNobyAiY29uZmlndXJpbmcgZmx1ZW50Yml0IHNlcnZpY2UiCm1rZGlyIC1wIC9ldGMvZmx1ZW50Yml0Lwpta2RpciAtcCAvdmFyL2xpYi9mbHVlbnQKCmNhdCA+L2V0Yy9mbHVlbnRiaXQvZmx1ZW50Yml0LmNvbmYgPDwnRU9GJwpbSU5QVVRdCglOYW1lIHN5c3RlbWQKCVRhZyBqb3VybmFsZAoJU3lzdGVtZF9GaWx0ZXIgX0NPTU09YXJvCglEQiAvdmFyL2xpYi9mbHVlbnQvam91cm5hbGRiCgpbRklMVEVSXQoJTmFtZSBtb2RpZnkKCU1hdGNoIGpvdXJuYWxkCglSZW1vdmVfd2lsZGNhcmQgXwoJUmVtb3ZlIFRJTUVTVEFNUAoKW09VVFBVVF0KCU5hbWUgZm9yd2FyZAoJTWF0Y2ggKgoJUG9ydCAyOTIzMApFT0YKCmVjaG8gIkZMVUVOVEJJVElNQUdFPSRGTFVFTlRCSVRJTUFHRSIgPi9ldGMvc3lzY29uZmlnL2ZsdWVudGJpdAoKY2F0ID4vZXRjL3N5c3RlbWQvc3lzdGVtL2ZsdWVudGJpdC5zZXJ2aWNlIDw8J0VPRicKW1VuaXRdCkFmdGVyPW5ldHdvcmstb25saW5lLnRhcmdldApXYW50cz1uZXR3b3JrLW9ubGluZS50YXJnZXQKU3RhcnRMaW1pdEludGVydmFsU2VjPTAKCltTZXJ2aWNlXQpSZXN0YXJ0U2VjPTFzCkVudmlyb25tZW50RmlsZT0vZXRjL3N5c2NvbmZpZy9mbHVlbnRiaXQKRXhlY1N0YXJ0UHJlPS0vdXNyL2Jpbi9kb2NrZXIgcm0gLWYgJU4KRXhlY1N0YXJ0PS91c3IvYmluL2RvY2tlciBydW4gXAogIC0tc2VjdXJpdHktb3B0IGxhYmVsPWRpc2FibGUgXAogIC0tZW50cnlwb2ludCAvb3B0L3RkLWFnZW50LWJpdC9iaW4vdGQtYWdlbnQtYml0IFwKICAtLW5ldD1ob3N0IFwKICAtLWhvc3RuYW1lICVIIFwKICAtLW5hbWUgJU4gXAogIC0tcm0gXAogIC0tY2FwLWRyb3AgbmV0X3JhdyBcCiAgLXYgL2V0Yy9mbHVlbnRiaXQvZmx1ZW50Yml0LmNvbmY6L2V0Yy9mbHVlbnRiaXQvZmx1ZW50Yml0LmNvbmYgXAogIC12IC92YXIvbGliL2ZsdWVudDovdmFyL2xpYi9mbHVlbnQ6eiBcCiAgLXYgL3Zhci9sb2cvam91cm5hbDovdmFyL2xvZy9qb3VybmFsOnJvIFwKICAtdiAvZXRjL21hY2hpbmUtaWQ6L2V0Yy9tYWNoaW5lLWlkOnJvIFwKICAkRkxVRU5UQklUSU1BR0UgXAogIC1jIC9ldGMvZmx1ZW50Yml0L2ZsdWVudGJpdC5jb25mCgpFeGVjU3RvcD0vdXNyL2Jpbi9kb2NrZXIgc3RvcCAlTgpSZXN0YXJ0PWFsd2F5cwpSZXN0YXJ0U2VjPTUKU3RhcnRMaW1pdEludGVydmFsPTAKCltJbnN0YWxsXQpXYW50ZWRCeT1tdWx0aS11c2VyLnRhcmdldApFT0YKCmVjaG8gImNvbmZpZ3VyaW5nIG1kbSBzZXJ2aWNlIgpjYXQgPi9ldGMvc3lzY29uZmlnL21kbSA8PEVPRgpNRE1GUk9OVEVORFVSTD0nJE1ETUZST05URU5EVVJMJwpNRE1JTUFHRT0nJE1ETUlNQUdFJwpNRE1TT1VSQ0VFTlZJUk9OTUVOVD0nJExPQ0FUSU9OJwpNRE1TT1VSQ0VST0xFPWdhdGV3YXkKTURNU09VUkNFUk9MRUlOU1RBTkNFPSckKGhvc3RuYW1lKScKRU9GCgpta2RpciAvdmFyL2V0dwpjYXQgPi9ldGMvc3lzdGVtZC9zeXN0ZW0vbWRtLnNlcnZpY2UgPDwnRU9GJwpbVW5pdF0KQWZ0ZXI9bmV0d29yay1vbmxpbmUudGFyZ2V0CldhbnRzPW5ldHdvcmstb25saW5lLnRhcmdldAoKW1NlcnZpY2VdCkVudmlyb25tZW50RmlsZT0vZXRjL3N5c2NvbmZpZy9tZG0KRXhlY1N0YXJ0UHJlPS0vdXNyL2Jpbi9kb2NrZXIgcm0gLWYgJU4KRXhlY1N0YXJ0PS91c3IvYmluL2RvY2tlciBydW4gXAogIC0tZW50cnlwb2ludCAvdXNyL3NiaW4vTWV0cmljc0V4dGVuc2lvbiBcCiAgLS1ob3N0bmFtZSAlSCBcCiAgLS1uYW1lICVOIFwKICAtLXJtIFwKICAtLWNhcC1kcm9wIG5ldF9yYXcgXAogIC1tIDJnIFwKICAtdiAvZXRjL21kbS5wZW06L2V0Yy9tZG0ucGVtIFwKICAtdiAvdmFyL2V0dzovdmFyL2V0dzp6IFwKICAkTURNSU1BR0UgXAogIC1DZXJ0RmlsZSAvZXRjL21kbS5wZW0gXAogIC1Gcm9udEVuZFVybCAkTURNRlJPTlRFTkRVUkwgXAogIC1Mb2dnZXIgQ29uc29sZSBcCiAgLUxvZ0xldmVsIFdhcm5pbmcgXAogIC1Qcml2YXRlS2V5RmlsZSAvZXRjL21kbS5wZW0gXAogIC1Tb3VyY2VFbnZpcm9ubWVudCAkTURNU09VUkNFRU5WSVJPTk1FTlQgXAogIC1Tb3VyY2VSb2xlICRNRE1TT1VSQ0VST0xFIFwKICAtU291cmNlUm9sZUluc3RhbmNlICRNRE1TT1VSQ0VST0xFSU5TVEFOQ0UKRXhlY1N0b3A9L3Vzci9iaW4vZG9ja2VyIHN0b3AgJU4KUmVzdGFydD1hbHdheXMKUmVzdGFydFNlYz0xClN0YXJ0TGltaXRJbnRlcnZhbD0wCgpbSW5zdGFsbF0KV2FudGVkQnk9bXVsdGktdXNlci50YXJnZXQKRU9GCgplY2hvICJjb25maWd1cmluZyBhcm8tZ2F0ZXdheSBzZXJ2aWNlIgpjYXQgPi9ldGMvc3lzY29uZmlnL2Fyby1nYXRld2F5IDw8RU9GCkFDUl9SRVNPVVJDRV9JRD0nJEFDUlJFU09VUkNFSUQnCkRBVEFCQVNFX0FDQ09VTlRfTkFNRT0nJERBVEFCQVNFQUNDT1VOVE5BTUUnCkFaVVJFX0RCVE9LRU5fQ0xJRU5UX0lEPSckREJUT0tFTkNMSUVOVElEJwpEQlRPS0VOX1VSTD0nJERCVE9LRU5VUkwnCk1ETV9BQ0NPVU5UPSIkUlBNRE1BQ0NPVU5UIgpNRE1fTkFNRVNQQUNFPUdhdGV3YXkKR0FURVdBWV9ET01BSU5TPSckR0FURVdBWURPTUFJTlMnCkdBVEVXQVlfRkVBVFVSRVM9JyRHQVRFV0FZRkVBVFVSRVMnClJQSU1BR0U9JyRSUElNQUdFJwpFT0YKCmNhdCA+L2V0Yy9zeXN0ZW1kL3N5c3RlbS9hcm8tZ2F0ZXdheS5zZXJ2aWNlIDw8RU9GCltVbml0XQpBZnRlcj1uZXR3b3JrLW9ubGluZS50YXJnZXQKV2FudHM9bmV0d29yay1vbmxpbmUudGFyZ2V0CgpbU2VydmljZV0KRW52aXJvbm1lbnRGaWxlPS9ldGMvc3lzY29uZmlnL2Fyby1nYXRld2F5CkV4ZWNTdGFydFByZT0tL3Vzci9iaW4vZG9ja2VyIHJtIC1mICVOCkV4ZWNTdGFydFByZT0vdXNyL2Jpbi9ta2RpciAtcCAke2dhdGV3YXlfbG9nZGlyfQpFeGVjU3RhcnQ9L3Vzci9iaW4vZG9ja2VyIHJ1biBcCiAgLS1ob3N0bmFtZSAlSCBcCiAgLS1uYW1lICVOIFwKICAtLXJtIFwKICAtLWNhcC1kcm9wIG5ldF9yYXcgXAogIC1lIEFDUl9SRVNPVVJDRV9JRCBcCiAgLWUgREFUQUJBU0VfQUNDT1VOVF9OQU1FIFwKICAtZSBBWlVSRV9EQlRPS0VOX0NMSUVOVF9JRCBcCiAgLWUgREJUT0tFTl9VUkwgXAogIC1lIEdBVEVXQVlfRE9NQUlOUyBcCiAgLWUgR0FURVdBWV9GRUFUVVJFUyBcCiAgLWUgTURNX0FDQ09VTlQgXAogIC1lIE1ETV9OQU1FU1BBQ0UgXAogIC1tIDJnIFwKICAtcCA4MDo4MDgwIFwKICAtcCA4MDgxOjgwODEgXAogIC1wIDQ0Mzo4NDQzIFwKICAtdiAvcnVuL3N5c3RlbWQvam91cm5hbDovcnVuL3N5c3RlbWQvam91cm5hbCBcCiAgLXYgL3Zhci9ldHc6L3Zhci9ldHc6eiBcCiAgLXYgJHtnYXRld2F5X2xvZ2Rpcn06L2N0ci5sb2c6eiBcCiAgXCRSUElNQUdFIFwKICBnYXRld2F5CkV4ZWNTdG9wPS91c3IvYmluL2RvY2tlciBzdG9wIC10IDM2MDAgJU4KVGltZW91dFN0b3BTZWM9MzYwMApSZXN0YXJ0PWFsd2F5cwpSZXN0YXJ0U2VjPTEKU3RhcnRMaW1pdEludGVydmFsPTAKCltJbnN0YWxsXQpXYW50ZWRCeT1tdWx0aS11c2VyLnRhcmdldApFT0YKCmNoY29uIC1SIHN5c3RlbV91Om9iamVjdF9yOnZhcl9sb2dfdDpzMCAvdmFyL29wdC9taWNyb3NvZnQvbGludXhtb25hZ2VudAoKbWtkaXIgLXAgL3Zhci9saWIvd2FhZ2VudC9NaWNyb3NvZnQuQXp1cmUuS2V5VmF1bHQuU3RvcmUKCmVjaG8gImNvbmZpZ3VyaW5nIG1kc2QgYW5kIG1kbSBzZXJ2aWNlcyIKZm9yIHZhciBpbiAibWRzZCIgIm1kbSI7IGRvCmNhdCA+L2V0Yy9zeXN0ZW1kL3N5c3RlbS9kb3dubG9hZC0kdmFyLWNyZWRlbnRpYWxzLnNlcnZpY2UgPDxFT0YKW1VuaXRdCkRlc2NyaXB0aW9uPVBlcmlvZGljICR2YXIgY3JlZGVudGlhbHMgcmVmcmVzaAoKW1NlcnZpY2VdClR5cGU9b25lc2hvdApFeGVjU3RhcnQ9L3Vzci9sb2NhbC9iaW4vZG93bmxvYWQtY3JlZGVudGlhbHMuc2ggJHZhcgpFT0YKCmNhdCA+L2V0Yy9zeXN0ZW1kL3N5c3RlbS9kb3dubG9hZC0kdmFyLWNyZWRlbnRpYWxzLnRpbWVyIDw8RU9GCltVbml0XQpEZXNjcmlwdGlvbj1QZXJpb2RpYyAkdmFyIGNyZWRlbnRpYWxzIHJlZnJlc2gKQWZ0ZXI9bmV0d29yay1vbmxpbmUudGFyZ2V0CldhbnRzPW5ldHdvcmstb25saW5lLnRhcmdldAoKW1RpbWVyXQpPbkJvb3RTZWM9MG1pbgpPbkNhbGVuZGFyPTAvMTI6MDA6MDAKQWNjdXJhY3lTZWM9NXMKCltJbnN0YWxsXQpXYW50ZWRCeT10aW1lcnMudGFyZ2V0CkVPRgpkb25lCgpjYXQgPi91c3IvbG9jYWwvYmluL2Rvd25sb2FkLWNyZWRlbnRpYWxzLnNoIDw8RU9GCiMhL2Jpbi9iYXNoCnNldCAtZXUKCkNPTVBPTkVOVD0iXCQxIgplY2hvICJEb3dubG9hZCBcJENPTVBPTkVOVCBjcmVkZW50aWFscyIKClRFTVBfRElSPVwkKG1rdGVtcCAtZCkKZXhwb3J0IEFaVVJFX0NPTkZJR19ESVI9XCQobWt0ZW1wIC1kKQoKZWNobyAiTG9nZ2luZyBpbnRvIEF6dXJlLi4uIgpSRVRSSUVTPTMKd2hpbGUgWyAiXCRSRVRSSUVTIiAtZ3QgMCBdOyBkbwogICAgaWYgYXogbG9naW4gLWkgLS1hbGxvdy1uby1zdWJzY3JpcHRpb25zCiAgICB0aGVuCiAgICAgICAgZWNobyAiYXogbG9naW4gc3VjY2Vzc2Z1bCIKICAgICAgICBicmVhawogICAgZWxzZQogICAgICAgIGVjaG8gImF6IGxvZ2luIGZhaWxlZC4gUmV0cnlpbmcuLi4iCiAgICAgICAgbGV0IFJFVFJJRVMtPTEKICAgICAgICBzbGVlcCA1CiAgICBmaQpkb25lCgp0cmFwICJjbGVhbnVwIiBFWElUCgpjbGVhbnVwKCkgewogIGF6IGxvZ291dAogIFtbICJcJFRFTVBfRElSIiA9fiAvdG1wLy4rIF1dICYmIHJtIC1yZiBcJFRFTVBfRElSCiAgW1sgIlwkQVpVUkVfQ09ORklHX0RJUiIgPX4gL3RtcC8uKyBdXSAmJiBybSAtcmYgXCRBWlVSRV9DT05GSUdfRElSCn0KCmlmIFsgIlwkQ09NUE9ORU5UIiA9ICJtZG0iIF07IHRoZW4KICBDVVJSRU5UX0NFUlRfRklMRT0iL2V0Yy9tZG0ucGVtIgplbGlmIFsgIlwkQ09NUE9ORU5UIiA9ICJtZHNkIiBdOyB0aGVuCiAgQ1VSUkVOVF9DRVJUX0ZJTEU9Ii92YXIvbGliL3dhYWdlbnQvTWljcm9zb2Z0LkF6dXJlLktleVZhdWx0LlN0b3JlL21kc2QucGVtIgplbHNlCiAgZWNobyBJbnZhbGlkIHVzYWdlICYmIGV4aXQgMQpmaQoKU0VDUkVUX05BTUU9Imd3eS1cJHtDT01QT05FTlR9IgpORVdfQ0VSVF9GSUxFPSJcJFRFTVBfRElSL1wkQ09NUE9ORU5ULnBlbSIKZm9yIGF0dGVtcHQgaW4gezEuLjV9OyBkbwogIGF6IGtleXZhdWx0IHNlY3JldCBkb3dubG9hZCAtLWZpbGUgXCRORVdfQ0VSVF9GSUxFIC0taWQgImh0dHBzOi8vJEtFWVZBVUxUUFJFRklYLWd3eS4kS0VZVkFVTFRETlNTVUZGSVgvc2VjcmV0cy9cJFNFQ1JFVF9OQU1FIiAmJiBicmVhawogIGlmIFtbIFwkYXR0ZW1wdCAtbHQgNSBdXTsgdGhlbiBzbGVlcCAxMDsgZWxzZSBleGl0IDE7IGZpCmRvbmUKCmlmIFsgLWYgXCRORVdfQ0VSVF9GSUxFIF07IHRoZW4KICBpZiBbICJcJENPTVBPTkVOVCIgPSAibWRzZCIgXTsgdGhlbgogICAgY2hvd24gc3lzbG9nOnN5c2xvZyBcJE5FV19DRVJUX0ZJTEUKICBlbHNlCiAgICBzZWQgLWkgLW5lICcxLC9FTkQgQ0VSVElGSUNBVEUvIHAnIFwkTkVXX0NFUlRfRklMRQogIGZpCgogIG5ld19jZXJ0X3NuPSJcJChvcGVuc3NsIHg1MDkgLWluICJcJE5FV19DRVJUX0ZJTEUiIC1ub291dCAtc2VyaWFsIHwgYXdrIC1GPSAne3ByaW50IFwkMn0nKSIKICBjdXJyZW50X2NlcnRfc249IlwkKG9wZW5zc2wgeDUwOSAtaW4gIlwkQ1VSUkVOVF9DRVJUX0ZJTEUiIC1ub291dCAtc2VyaWFsIHwgYXdrIC1GPSAne3ByaW50IFwkMn0nKSIKICBpZiBbWyAhIC16IFwkbmV3X2NlcnRfc24gXV0gJiYgW1sgXCRuZXdfY2VydF9zbiAhPSAiXCRjdXJyZW50X2NlcnRfc24iIF1dOyB0aGVuCiAgICBlY2hvIHVwZGF0aW5nIGNlcnRpZmljYXRlIGZvciBcJENPTVBPTkVOVAogICAgY2htb2QgMDYwMCBcJE5FV19DRVJUX0ZJTEUKICAgIG12IFwkTkVXX0NFUlRfRklMRSBcJENVUlJFTlRfQ0VSVF9GSUxFCiAgZmkKZWxzZQogIGVjaG8gRmFpbGVkIHRvIHJlZnJlc2ggY2VydGlmaWNhdGUgZm9yIFwkQ09NUE9ORU5UICYmIGV4aXQgMQpmaQpFT0YKCmNobW9kIHUreCAvdXNyL2xvY2FsL2Jpbi9kb3dubG9hZC1jcmVkZW50aWFscy5zaAoKc3lzdGVtY3RsIGVuYWJsZSBkb3dubG9hZC1tZHNkLWNyZWRlbnRpYWxzLnRpbWVyCnN5c3RlbWN0bCBlbmFibGUgZG93bmxvYWQtbWRtLWNyZWRlbnRpYWxzLnRpbWVyCgovdXNyL2xvY2FsL2Jpbi9kb3dubG9hZC1jcmVkZW50aWFscy5zaCBtZHNkCi91c3IvbG9jYWwvYmluL2Rvd25sb2FkLWNyZWRlbnRpYWxzLnNoIG1kbQpNRFNEQ0VSVElGSUNBVEVTQU49JChvcGVuc3NsIHg1MDkgLWluIC92YXIvbGliL3dhYWdlbnQvTWljcm9zb2Z0LkF6dXJlLktleVZhdWx0LlN0b3JlL21kc2QucGVtIC1ub291dCAtc3ViamVjdCB8IHNlZCAtZSAncy8uKkNOID0gLy8nKQoKY2F0ID4vZXRjL3N5c3RlbWQvc3lzdGVtL3dhdGNoLW1kbS1jcmVkZW50aWFscy5zZXJ2aWNlIDw8RU9GCltVbml0XQpEZXNjcmlwdGlvbj1XYXRjaCBmb3IgY2hhbmdlcyBpbiBtZG0ucGVtIGFuZCByZXN0YXJ0cyB0aGUgbWRtIHNlcnZpY2UKCltTZXJ2aWNlXQpUeXBlPW9uZXNob3QKRXhlY1N0YXJ0PS91c3IvYmluL3N5c3RlbWN0bCByZXN0YXJ0IG1kbS5zZXJ2aWNlCgpbSW5zdGFsbF0KV2FudGVkQnk9bXVsdGktdXNlci50YXJnZXQKRU9GCgpjYXQgPi9ldGMvc3lzdGVtZC9zeXN0ZW0vd2F0Y2gtbWRtLWNyZWRlbnRpYWxzLnBhdGggPDxFT0YKW1BhdGhdClBhdGhNb2RpZmllZD0vZXRjL21kbS5wZW0KCltJbnN0YWxsXQpXYW50ZWRCeT1tdWx0aS11c2VyLnRhcmdldApFT0YKCnN5c3RlbWN0bCBlbmFibGUgd2F0Y2gtbWRtLWNyZWRlbnRpYWxzLnBhdGgKc3lzdGVtY3RsIHN0YXJ0IHdhdGNoLW1kbS1jcmVkZW50aWFscy5wYXRoCgpta2RpciAvZXRjL3N5c3RlbWQvc3lzdGVtL21kc2Quc2VydmljZS5kCmNhdCA+L2V0Yy9zeXN0ZW1kL3N5c3RlbS9tZHNkLnNlcnZpY2UuZC9vdmVycmlkZS5jb25mIDw8J0VPRicKW1VuaXRdCkFmdGVyPW5ldHdvcmstb25saW5lLnRhcmdldApFT0YKCmNhdCA+L2V0Yy9kZWZhdWx0L21kc2QgPDxFT0YKTURTRF9ST0xFX1BSRUZJWD0vdmFyL3J1bi9tZHNkL2RlZmF1bHQKTURTRF9PUFRJT05TPSItQSAtZCAtciBcJE1EU0RfUk9MRV9QUkVGSVgiCgpleHBvcnQgTU9OSVRPUklOR19HQ1NfRU5WSVJPTk1FTlQ9JyRNRFNERU5WSVJPTk1FTlQnCmV4cG9ydCBNT05JVE9SSU5HX0dDU19BQ0NPVU5UPSckUlBNRFNEQUNDT1VOVCcKZXhwb3J0IE1PTklUT1JJTkdfR0NTX1JFR0lPTj0nJExPQ0FUSU9OJwpleHBvcnQgTU9OSVRPUklOR19HQ1NfQVVUSF9JRF9UWVBFPUF1dGhLZXlWYXVsdApleHBvcnQgTU9OSVRPUklOR19HQ1NfQVVUSF9JRD0nJE1EU0RDRVJUSUZJQ0FURVNBTicKZXhwb3J0IE1PTklUT1JJTkdfR0NTX05BTUVTUEFDRT0nJFJQTURTRE5BTUVTUEFDRScKZXhwb3J0IE1PTklUT1JJTkdfQ09ORklHX1ZFUlNJT049JyRHQVRFV0FZTURTRENPTkZJR1ZFUlNJT04nCmV4cG9ydCBNT05JVE9SSU5HX1VTRV9HRU5FVkFfQ09ORklHX1NFUlZJQ0U9dHJ1ZQoKZXhwb3J0IE1PTklUT1JJTkdfVEVOQU5UPSckTE9DQVRJT04nCmV4cG9ydCBNT05JVE9SSU5HX1JPTEU9Z2F0ZXdheQpleHBvcnQgTU9OSVRPUklOR19ST0xFX0lOU1RBTkNFPSckKGhvc3RuYW1lKScKCmV4cG9ydCBNRFNEX01TR1BBQ0tfU09SVF9DT0xVTU5TPTEKRU9GCgojIHNldHRpbmcgTU9OSVRPUklOR19HQ1NfQVVUSF9JRF9UWVBFPUF1dGhLZXlWYXVsdCBzZWVtcyB0byBoYXZlIGNhdXNlZCBtZHNkIG5vdAojIHRvIGhvbm91ciBTU0xfQ0VSVF9GSUxFIGFueSBtb3JlLCBoZWF2ZW4gb25seSBrbm93cyB3aHkuCm1rZGlyIC1wIC91c3IvbGliL3NzbC9jZXJ0cwpjc3BsaXQgLWYgL3Vzci9saWIvc3NsL2NlcnRzL2NlcnQtIC1iICUwM2QucGVtIC9ldGMvcGtpL3Rscy9jZXJ0cy9jYS1idW5kbGUuY3J0IC9eJC8xIHsqfSA+L2Rldi9udWxsCmNfcmVoYXNoIC91c3IvbGliL3NzbC9jZXJ0cwoKIyB3ZSBsZWF2ZSBjbGllbnRJZCBibGFuayBhcyBsb25nIGFzIG9ubHkgMSBtYW5hZ2VkIGlkZW50aXR5IGFzc2lnbmVkIHRvIHZtc3MKIyBpZiB3ZSBoYXZlIG1vcmUgdGhhbiAxLCB3ZSB3aWxsIG5lZWQgdG8gcG9wdWxhdGUgd2l0aCBjbGllbnRJZCB1c2VkIGZvciBvZmYtbm9kZSBzY2FubmluZwpjYXQgPi9ldGMvZGVmYXVsdC92c2Etbm9kZXNjYW4tYWdlbnQuY29uZmlnIDw8RU9GCnsKICAgICJOaWNlIjogMTksCiAgICAiVGltZW91dCI6IDEwODAwLAogICAgIkNsaWVudElkIjogIiIsCiAgICAiVGVuYW50SWQiOiAiJEFaVVJFU0VDUEFDS1ZTQVRFTkFOVElEIiwKICAgICJRdWFseXNTdG9yZUJhc2VVcmwiOiAiJEFaVVJFU0VDUEFDS1FVQUxZU1VSTCIsCiAgICAiUHJvY2Vzc1RpbWVvdXQiOiAzMDAsCiAgICAiQ29tbWFuZERlbGF5IjogMAogIH0KRU9GCgplY2hvICJlbmFibGluZyBhcm8gc2VydmljZXMiCmZvciBzZXJ2aWNlIGluIGFyby1nYXRld2F5IGF1b21zIGF6c2VjZCBhenNlY21vbmQgbWRzZCBtZG0gY2hyb255ZCBmbHVlbnRiaXQ7IGRvCiAgc3lzdGVtY3RsIGVuYWJsZSAkc2VydmljZS5zZXJ2aWNlCmRvbmUKCmZvciBzY2FuIGluIGJhc2VsaW5lIGNsYW1hdiBzb2Z0d2FyZTsgZG8KICAvdXNyL2xvY2FsL2Jpbi9henNlY2QgY29uZmlnIC1zICRzY2FuIC1kIFAxRApkb25lCgplY2hvICJyZWJvb3RpbmciCnJlc3RvcmVjb24gLVJGIC92YXIvbG9nLyoKKHNsZWVwIDMwOyByZWJvb3QpICYK')))]" + "script": "[base64(concat(base64ToString('c2V0IC1leAoK'),'ACRRESOURCEID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('acrResourceId')),''')\n','AZURECLOUDNAME=$(base64 -d \u003c\u003c\u003c''',base64(parameters('azureCloudName')),''')\n','AZURESECPACKQUALYSURL=$(base64 -d \u003c\u003c\u003c''',base64(parameters('azureSecPackQualysUrl')),''')\n','AZURESECPACKVSATENANTID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('azureSecPackVSATenantId')),''')\n','DATABASEACCOUNTNAME=$(base64 -d \u003c\u003c\u003c''',base64(parameters('databaseAccountName')),''')\n','DBTOKENCLIENTID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('dbtokenClientId')),''')\n','DBTOKENURL=$(base64 -d \u003c\u003c\u003c''',base64(parameters('dbtokenUrl')),''')\n','MDMFRONTENDURL=$(base64 -d \u003c\u003c\u003c''',base64(parameters('mdmFrontendUrl')),''')\n','MDSDENVIRONMENT=$(base64 -d \u003c\u003c\u003c''',base64(parameters('mdsdEnvironment')),''')\n','FLUENTBITIMAGE=$(base64 -d \u003c\u003c\u003c''',base64(parameters('fluentbitImage')),''')\n','GATEWAYMDSDCONFIGVERSION=$(base64 -d \u003c\u003c\u003c''',base64(parameters('gatewayMdsdConfigVersion')),''')\n','GATEWAYDOMAINS=$(base64 -d \u003c\u003c\u003c''',base64(parameters('gatewayDomains')),''')\n','GATEWAYFEATURES=$(base64 -d \u003c\u003c\u003c''',base64(parameters('gatewayFeatures')),''')\n','KEYVAULTDNSSUFFIX=$(base64 -d \u003c\u003c\u003c''',base64(parameters('keyvaultDNSSuffix')),''')\n','KEYVAULTPREFIX=$(base64 -d \u003c\u003c\u003c''',base64(parameters('keyvaultPrefix')),''')\n','RPIMAGE=$(base64 -d \u003c\u003c\u003c''',base64(parameters('rpImage')),''')\n','RPMDMACCOUNT=$(base64 -d \u003c\u003c\u003c''',base64(parameters('rpMdmAccount')),''')\n','RPMDSDACCOUNT=$(base64 -d \u003c\u003c\u003c''',base64(parameters('rpMdsdAccount')),''')\n','RPMDSDNAMESPACE=$(base64 -d \u003c\u003c\u003c''',base64(parameters('rpMdsdNamespace')),''')\n','MDMIMAGE=''/genevamdm:2.2024.328.1744-c5fb79-20240328t1935''\n','LOCATION=$(base64 -d \u003c\u003c\u003c''',base64(resourceGroup().location),''')\n','SUBSCRIPTIONID=$(base64 -d \u003c\u003c\u003c''',base64(subscription().subscriptionId),''')\n','RESOURCEGROUPNAME=$(base64 -d \u003c\u003c\u003c''',base64(resourceGroup().name),''')\n','\n',base64ToString('IyEvYmluL2Jhc2gKCnNldCAtbyBlcnJleGl0IFwKICAgIC1vIG5vdW5zZXQKCmlmIFsgIiR7REVCVUc6LWZhbHNlfSIgPT0gdHJ1ZSBdOyB0aGVuCiAgICBzZXQgLXgKZmkKCm1haW4oKSB7CiAgICBsb2NhbCAtciBnYXRld2F5X2xvZ2Rpcj0nL3Zhci9sb2cvYXJvLWdhdGV3YXknCiAgICBwYXJzZV9ydW5fb3B0aW9ucyAiJEAiIGdhdGV3YXlfbG9nZGlyCgoKICAgIGNvbmZpZ3VyZV9zc2hkCiAgICBjb25maWd1cmVfYW5kX2luc3RhbGxfZG5mX3BrZ3NfcmVwb3MKICAgIGNvbmZpZ3VyZV9kaXNrX3BhcnRpdGlvbnMKICAgIGNvbmZpZ3VyZV9sb2dyb3RhdGUgZ2F0ZXdheV9sb2dkaXIKICAgIGNvbmZpZ3VyZV9zZWxpbnV4CgogICAgbWtkaXIgLXAgL3Zhci9sb2cvam91cm5hbAogICAgbWtkaXIgLXAgL3Zhci9saWIvd2FhZ2VudC9NaWNyb3NvZnQuQXp1cmUuS2V5VmF1bHQuU3RvcmUKCiAgICBjb25maWd1cmVfZmlyZXdhbGxkX3J1bGVzCiAgICBwdWxsX2NvbnRhaW5lcl9pbWFnZXMKICAgIGNvbmZpZ3VyZV9zeXN0ZW1fc2VydmljZXMgZ2F0ZXdheV9sb2dkaXIKICAgIHJlYm9vdF92bQp9Cgp1c2FnZSgpIHsKICAgIGxvY2FsIC1uIG9wdGlvbnM9IiQxIgogICAgbG9nICIkKGJhc2VuYW1lICIkMCIpIFskb3B0aW9uc10KICAgICAgICAtZCBDb25maWd1cmUgRGlzayBQYXJ0aXRpb25zCiAgICAgICAgLXAgQ29uZmlndXJlIHJwbSByZXBvc2l0b3JpZXMsIGltcG9ydCByZXF1aXJlZCBycG0ga2V5cywgdXBkYXRlICYgaW5zdGFsbCBwYWNrYWdlcyB3aXRoIGRuZgogICAgICAgIC1sIENvbmZpZ3VyZSBsb2dyb3RhdGUuY29uZgogICAgICAgIC1zIE1ha2Ugc2VsaW51eCBtb2RpZmljYXRpb25zIHJlcXVpcmVkIGZvciBBUk8gUlAKICAgICAgICAtciBDb25maWd1cmUgc3NoZCAtIEFsbG93IHBhc3N3b3JkIGF1dGhlbnRpY2FpdG9uCiAgICAgICAgLWYgQ29uZmlndXJlIGZpcmV3YWxsZCBkZWZhdWx0IHpvbmUgcnVsZXMKICAgICAgICAtdSBDb25maWd1cmUgc3lzdGVtZCB1bml0IGZpbGVzIGZvciBBUk8gUlAKICAgICAgICAtaSBQdWxsIGNvbnRhaW5lciBpbWFnZXMKCiAgICAgICAgTm90ZTogc3RlcHMgd2lsbCBiZSBleGVjdXRlZCBpbiB0aGUgb3JkZXIgdGhhdCBmbGFncyBhcmUgcHJvdmlkZWQKICAgICIKfQoKIyBwYXJzZV9ydW5fb3B0aW9ucyB0YWtlcyBhbGwgYXJndWVtZW50cyBwYXNzZWQgdG8gbWFpbiBhbmQgcGFyc2VzIHRoZW0KIyBhbGxvd2luZyBpbmRpdmlkdWFsIHN0ZXAocykgdG8gYmUgcmFuLCByYXRoZXIgdGhhbiBhbGwgc3RlcHMKIwojIFRoaXMgaXMgdXNlZnVsIGZvciBsb2NhbCB0ZXN0aW5nLCBvciBwb3NzaWJseSBtb2RpZnlpbmcgdGhlIGJvb3RzdHJhcCBleGVjdXRpb24gdmlhIGVudmlyb25tZW50IHZhcmlhYmxlcyBpbiB0aGUgZGVwbG95bWVudCBwaXBlbGluZQpwYXJzZV9ydW5fb3B0aW9ucygpIHsKICAgICMgc2hlbGxjaGVjayBkaXNhYmxlPVNDMjIwNgogICAgbG9jYWwgLWEgb3B0aW9ucz0oJHsxOi19KQogICAgaWYgWyAiJHsjb3B0aW9uc1tAXX0iIC1lcSAwIF07IHRoZW4KICAgICAgICBsb2cgIlJ1bm5pbmcgYWxsIHN0ZXBzIgogICAgICAgIHJldHVybiAwCiAgICBmaQoKICAgIGxvY2FsIE9QVElORAogICAgbG9jYWwgLXIgYWxsb3dlZF9vcHRpb25zPSJkcGxzcmZ1aSIKICAgIHdoaWxlIGdldG9wdHMgJHthbGxvd2VkX29wdGlvbnN9IG9wdGlvbnM7IGRvCiAgICAgICAgY2FzZSAiJHtvcHRpb25zfSIgaW4KICAgICAgICAgICAgZCkKICAgICAgICAgICAgICAgIGxvZyAiUnVubmluZyBzdGVwIGNvbmZpZ3VyZV9kaXNrX3BhcnRpdGlvbnMiCiAgICAgICAgICAgICAgICBjb25maWd1cmVfZGlza19wYXJ0aXRpb25zCiAgICAgICAgICAgICAgICA7OwogICAgICAgICAgICBwKQogICAgICAgICAgICAgICAgbG9nICJSdW5uaW5nIHN0ZXAgY29uZmlndXJlX2FuZF9pbnN0YWxsX2RuZl9wa2dzX3JlcG9zIgogICAgICAgICAgICAgICAgY29uZmlndXJlX2FuZF9pbnN0YWxsX2RuZl9wa2dzX3JlcG9zCiAgICAgICAgICAgICAgICA7OwogICAgICAgICAgICBsKQogICAgICAgICAgICAgICAgbG9nICJSdW5uaW5nIGNvbmZpZ3VyZV9sb2dyb3RhdGUiCiAgICAgICAgICAgICAgICBjb25maWd1cmVfbG9ncm90YXRlICIkMiIKICAgICAgICAgICAgICAgIDs7CiAgICAgICAgICAgIHMpCiAgICAgICAgICAgICAgICBsb2cgIlJ1bm5pbmcgY29uZmlndXJlX3NlbGludXgiCiAgICAgICAgICAgICAgICBjb25maWd1cmVfc2VsaW51eAogICAgICAgICAgICAgICAgOzsKICAgICAgICAgICAgcikKICAgICAgICAgICAgICAgIGxvZyAiUnVubmluZyBjb25maWd1cmVfc3NoZCIKICAgICAgICAgICAgICAgIGNvbmZpZ3VyZV9zc2hkCiAgICAgICAgICAgICAgICA7OwogICAgICAgICAgICBmKQogICAgICAgICAgICAgICAgbG9nICJSdW5uaW5nIGNvbmZpZ3VyZV9maXJld2FsbGRfcnVsZXMiCiAgICAgICAgICAgICAgICBjb25maWd1cmVfZmlyZXdhbGxkX3J1bGVzCiAgICAgICAgICAgICAgICA7OwogICAgICAgICAgICB1KQogICAgICAgICAgICAgICAgbG9nICJSdW5uaW5nIHB1bGxfY29udGFpbmVyX2ltYWdlcyAmIGNvbmZpZ3VyZV9zeXN0ZW1fc2VydmljZXMiCiAgICAgICAgICAgICAgICBjb25maWd1cmVfc3lzdGVtX3NlcnZpY2VzICIkMiIKICAgICAgICAgICAgICAgIDs7CiAgICAgICAgICAgIGkpCiAgICAgICAgICAgICAgICBsb2cgIlJ1bm5pbmcgcHVsbF9jb250YWluZXJfaW1hZ2VzIgogICAgICAgICAgICAgICAgcHVsbF9jb250YWluZXJfaW1hZ2VzIAogICAgICAgICAgICAgICAgOzsKICAgICAgICAgICAgKikKICAgICAgICAgICAgICAgIHVzYWdlIGFsbG93ZWRfb3B0aW9ucwogICAgICAgICAgICAgICAgYWJvcnQgIlVua293biBvcHRpb24gcHJvdmlkZWQiCiAgICAgICAgICAgICAgICA7OwogICAgICAgIGVzYWMKICAgIGRvbmUKICAgIAogICAgZXhpdCAwCn0KCiMgV2UgbmVlZCB0byBjb25maWd1cmUgUGFzc3dvcmRBdXRoZW50aWNhdGlvbiB0byB5ZXMgaW4gb3JkZXIgZm9yIHRoZSBWTVNTIEFjY2VzcyBKSVQgdG8gd29yawpjb25maWd1cmVfc3NoZCgpIHsKICAgIGxvZyAic3RhcnRpbmciCiAgICBsb2cgInNldHRpbmcgc3NoIHBhc3N3b3JkIGF1dGhlbnRpY2F0aW9uIgogICAgc2VkIC1pICdzL1Bhc3N3b3JkQXV0aGVudGljYXRpb24gbm8vUGFzc3dvcmRBdXRoZW50aWNhdGlvbiB5ZXMvZycgL2V0Yy9zc2gvc3NoZF9jb25maWcKCiAgICBzeXN0ZW1jdGwgcmVsb2FkIHNzaGQuc2VydmljZQogICAgc3lzdGVtY3RsIGlzLWFjdGl2ZSAtLXF1aWV0IHNzaGQgfHwgYWJvcnQgInNzaGQgZmFpbGVkIHRvIHJlbG9hZCIKfQoKIyBjb25maWd1cmVfYW5kX2luc3RhbGxfZG5mX3BrZ3NfcmVwb3MKY29uZmlndXJlX2FuZF9pbnN0YWxsX2RuZl9wa2dzX3JlcG9zKCkgewogICAgbG9nICJzdGFydGluZyIKCiAgICAjIHRyYW5zYWN0aW9uIGF0dGVtcHQgcmV0cnkgdGltZSBpbiBzZWNvbmRzCiAgICBsb2NhbCAtcmkgcmV0cnlfd2FpdF90aW1lPTYwCiAgICBjb25maWd1cmVfcmh1aV9yZXBvIHJldHJ5X3dhaXRfdGltZQogICAgY3JlYXRlX2F6dXJlX3JwbV9yZXBvcyByZXRyeV93YWl0X3RpbWUKCiAgICBsb2NhbCAtYXIgZXhjbHVkZV9wa2dzPSgKICAgICAgICAiLXggV0FMaW51eEFnZW50IgogICAgICAgICIteCBXQUxpbnV4QWdlbnQtdWRldiIKICAgICkKCiAgICBkbmZfdXBkYXRlX3BrZ3MgZXhjbHVkZV9wa2dzIHJldHJ5X3dhaXRfdGltZQoKICAgIGxvY2FsIC1yYSBycG1fa2V5cz0oCiAgICAgICAgaHR0cHM6Ly9kbC5mZWRvcmFwcm9qZWN0Lm9yZy9wdWIvZXBlbC9SUE0tR1BHLUtFWS1FUEVMLTgKICAgICAgICBodHRwczovL3BhY2thZ2VzLm1pY3Jvc29mdC5jb20va2V5cy9taWNyb3NvZnQuYXNjCiAgICApCgogICAgcnBtX2ltcG9ydF9rZXlzIHJwbV9rZXlzIHJldHJ5X3dhaXRfdGltZQoKICAgIGxvY2FsIC1yYSByZXBvX3JwbV9wa2dzPSgKICAgICAgICBodHRwczovL2RsLmZlZG9yYXByb2plY3Qub3JnL3B1Yi9lcGVsL2VwZWwtcmVsZWFzZS1sYXRlc3QtOC5ub2FyY2gucnBtCiAgICApCgogICAgbG9jYWwgLXJhIGluc3RhbGxfcGtncz0oCiAgICAgICAgY2xhbWF2CiAgICAgICAgYXpzZWMtY2xhbWF2CiAgICAgICAgYXpzZWMtbW9uaXRvcgogICAgICAgIGF6dXJlLWNsaQogICAgICAgIGF6dXJlLW1kc2QKICAgICAgICBhenVyZS1zZWN1cml0eQogICAgICAgIHBvZG1hbgogICAgICAgIHBvZG1hbi1kb2NrZXIKICAgICAgICBvcGVuc3NsLXBlcmwKICAgICAgICAjIGhhY2sgLSB3ZSBhcmUgaW5zdGFsbGluZyBweXRob24zIG9uIGhvc3RzIGR1ZSB0byBhbiBpc3N1ZSB3aXRoIEF6dXJlIExpbnV4IEV4dGVuc2lvbnMgaHR0cHM6Ly9naXRodWIuY29tL0F6dXJlL2F6dXJlLWxpbnV4LWV4dGVuc2lvbnMvcHVsbC8xNTA1CiAgICAgICAgcHl0aG9uMwogICAgKQoKICAgIGRuZl9pbnN0YWxsX3BrZ3MgcmVwb19ycG1fcGtncyByZXRyeV93YWl0X3RpbWUKICAgIGRuZl9pbnN0YWxsX3BrZ3MgaW5zdGFsbF9wa2dzIHJldHJ5X3dhaXRfdGltZQp9CgojIGNvbmZpZ3VyZV9yaHVpX3JlcG8KY29uZmlndXJlX3JodWlfcmVwbygpIHsKICAgIGxvZyAic3RhcnRpbmciCgogICAgbG9jYWwgLXJhIGNtZD0oCiAgICAgICAgZG5mCiAgICAgICAgdXBkYXRlCiAgICAgICAgLXkKICAgICAgICAtLWRpc2FibGVyZXBvPScqJwogICAgICAgIC0tZW5hYmxlcmVwbz0ncmh1aS1taWNyb3NvZnQtYXp1cmUqJwogICAgKQoKICAgIGxvZyAicnVubmluZyBSSFVJIHBhY2thZ2UgdXBkYXRlcyIKICAgIHJldHJ5IGNtZCAiJDEiCn0KCiMgcmV0cnkgQWRkaW5nIHJldHJ5IGxvZ2ljIHRvIHl1bSBjb21tYW5kcyBpbiBvcmRlciB0byBhdm9pZCBzdGFsbGluZyBvdXQgb24gcmVzb3VyY2UgbG9ja3MKcmV0cnkoKSB7CiAgICBsb2NhbCAtbiBjbWRfcmV0cnk9IiQxIgogICAgbG9jYWwgLW4gd2FpdF90aW1lPSIkMiIKCiAgICBmb3IgYXR0ZW1wdCBpbiB7MS4uNX07IGRvCiAgICAgICAgbG9nICJhdHRlbXB0ICMke2F0dGVtcHR9IC0gJHtGVU5DTkFNRVsyXX0iCiAgICAgICAgJHtjbWRfcmV0cnlbQF19ICYKCiAgICAgICAgd2FpdCAkISAmJiBicmVhawogICAgICAgIGlmIFtbICR7YXR0ZW1wdH0gLWx0IDUgXV07IHRoZW4KICAgICAgICAgICAgc2xlZXAgIiR3YWl0X3RpbWUiCiAgICAgICAgZWxzZQogICAgICAgICAgICBhYm9ydCAiYXR0ZW1wdCAjJHthdHRlbXB0fSAtIEZhaWxlZCB0byB1cGRhdGUgcGFja2FnZXMiCiAgICAgICAgZmkKICAgIGRvbmUKfQoKIyBkbmZfdXBkYXRlX3BrZ3MKZG5mX3VwZGF0ZV9wa2dzKCkgewogICAgbG9jYWwgLW4gZXhjbHVkZXM9IiQxIgogICAgbG9nICJzdGFydGluZyIKCiAgICBsb2NhbCAtcmEgY21kPSgKICAgICAgICBkbmYKICAgICAgICAteQogICAgICAgICR7ZXhjbHVkZXNbQF19CiAgICAgICAgdXBkYXRlCiAgICAgICAgLS1hbGxvd2VyYXNpbmcKICAgICkKCiAgICBsb2cgIlVwZGF0aW5nIGFsbCBwYWNrYWdlcyIKICAgIHJldHJ5IGNtZCAiJDIiCn0KCiMgZG5mX2luc3RhbGxfcGtncwpkbmZfaW5zdGFsbF9wa2dzKCkgewogICAgbG9jYWwgLW4gcGtncz0iJDEiCiAgICBsb2cgInN0YXJ0aW5nIgoKICAgIGxvY2FsIC1yYSBjbWQ9KAogICAgICAgIGRuZgogICAgICAgIC15CiAgICAgICAgaW5zdGFsbAogICAgICAgICR7cGtnc1tAXX0KICAgICkKCiAgICBsb2cgIkF0dGVtcHRpbmcgdG8gaW5zdGFsbCBwYWNrYWdlczogJHtwa2dzWypdfSIKICAgIHJldHJ5IGNtZCAiJDIiCn0KCiMgcnBtX2ltcG9ydF9rZXlzCnJwbV9pbXBvcnRfa2V5cygpIHsKICAgIGxvY2FsIC1uIGtleXM9IiQxIgogICAgbG9nICJzdGFydGluZyIKCgogICAgIyBzaGVsbGNoZWNrIGRpc2FibGU9U0MyMDY4CiAgICBmb3Iga2V5IGluICR7a2V5c1tAXX07IGRvCiAgICAgICAgaWYgWyAkeyNrZXlzW0BdfSAtZXEgMCBdOyB0aGVuCiAgICAgICAgICAgIGJyZWFrCiAgICAgICAgZmkKICAgICAgICAgICAgbG9jYWwgLWEgY21kPSgKICAgICAgICAgICAgICAgIHJwbQogICAgICAgICAgICAgICAgLS1pbXBvcnQKICAgICAgICAgICAgICAgIC12CiAgICAgICAgICAgICAgICAiJGtleSIKICAgICAgICAgICAgKQoKICAgICAgICAgICAgbG9nICJhdHRlbXB0ICMkYXR0ZW1wdCAtIGltcG9ydGluZyBycG0gcmVwb3NpdG9yeSBrZXkgJGtleSIKICAgICAgICAgICAgcmV0cnkgY21kICIkMiIgJiYgdW5zZXQga2V5CiAgICBkb25lCn0KCiMgY29uZmlndXJlX2Rpc2tfcGFydGl0aW9ucwpjb25maWd1cmVfZGlza19wYXJ0aXRpb25zKCkgewogICAgbG9nICJzdGFydGluZyIKICAgIGxvZyAiZXh0ZW5kaW5nIHBhcnRpdGlvbiB0YWJsZSIKCiAgICAjIExpbnV4IGJsb2NrIGRldmljZXMgYXJlIGluY29uc2lzdGVudGx5IG5hbWVkCiAgICAjIGl0J3MgZGlmZmljdWx0IHRvIHRpZSB0aGUgbHZtIHB2IHRvIHRoZSBwaHlzaWNhbCBkaXNrIHVzaW5nIC9kZXYvZGlzayBmaWxlcywgd2hpY2ggaXMgd2h5IGx2cyBpcyB1c2VkIGhlcmUKICAgIHBoeXNpY2FsX2Rpc2s9IiQobHZzIC1vIGRldmljZXMgLWEgfCBoZWFkIC1uMiB8IHRhaWwgLW4xIHwgY3V0IC1kICcgJyAtZiAzIHwgY3V0IC1kIFwoIC1mIDEgfCB0ciAtZCAnWzpkaWdpdDpdJykiCiAgICBncm93cGFydCAiJHBoeXNpY2FsX2Rpc2siIDIKCiAgICBsb2cgImV4dGVuZGluZyBmaWxlc3lzdGVtcyIKICAgIGxvZyAiZXh0ZW5kaW5nIHJvb3QgbHZtIgogICAgbHZleHRlbmQgLWwgKzIwJUZSRUUgL2Rldi9yb290dmcvcm9vdGx2CiAgICBsb2cgImdyb3dpbmcgcm9vdCBmaWxlc3lzdGVtIgogICAgeGZzX2dyb3dmcyAvCgogICAgbG9nICJleHRlbmRpbmcgdmFyIGx2bSIKICAgIGx2ZXh0ZW5kIC1sICsxMDAlRlJFRSAvZGV2L3Jvb3R2Zy92YXJsdgogICAgbG9nICJncm93aW5nIHZhciBmaWxlc3lzdGVtIgogICAgeGZzX2dyb3dmcyAvdmFyCn0KCiMgY29uZmlndXJlX2xvZ3JvdGF0ZSBjbG9iYmVycyAvZXRjL2xvZ3JvdGF0ZS5jb25mCmNvbmZpZ3VyZV9sb2dyb3RhdGUoKSB7CiAgICBsb2NhbCAtbiBsb2dfZGlyPSIkMSIKICAgIGxvZyAic3RhcnRpbmciCgogICAgbG9jYWwgLXIgbG9ncm90YXRlX2NvbmZfZmlsZW5hbWU9Jy9ldGMvbG9ncm90YXRlLmNvbmYnCiAgICBsb2NhbCAtciBsb2dyb3RhdGVfY29uZl9maWxlPSIjIHNlZSAnbWFuIGxvZ3JvdGF0ZScgZm9yIGRldGFpbHMKIyByb3RhdGUgbG9nIGZpbGVzIHdlZWtseQp3ZWVrbHkKCiMga2VlcCAyIHdlZWtzIHdvcnRoIG9mIGJhY2tsb2dzCnJvdGF0ZSAyCgojIGNyZWF0ZSBuZXcgKGVtcHR5KSBsb2cgZmlsZXMgYWZ0ZXIgcm90YXRpbmcgb2xkIG9uZXMKY3JlYXRlCgojIHVzZSBkYXRlIGFzIGEgc3VmZml4IG9mIHRoZSByb3RhdGVkIGZpbGUKZGF0ZWV4dAoKIyB1bmNvbW1lbnQgdGhpcyBpZiB5b3Ugd2FudCB5b3VyIGxvZyBmaWxlcyBjb21wcmVzc2VkCmNvbXByZXNzCgojIFJQTSBwYWNrYWdlcyBkcm9wIGxvZyByb3RhdGlvbiBpbmZvcm1hdGlvbiBpbnRvIHRoaXMgZGlyZWN0b3J5CmluY2x1ZGUgL2V0Yy9sb2dyb3RhdGUuZAoKIyBubyBwYWNrYWdlcyBvd24gd3RtcCBhbmQgYnRtcCAtLSB3ZSB3aWxsIHJvdGF0ZSB0aGVtIGhlcmUKL3Zhci9sb2cvd3RtcCB7CiAgICBtb250aGx5CiAgICBjcmVhdGUgMDY2NCByb290IHV0bXAKICAgICAgICBtaW5zaXplIDFNCiAgICByb3RhdGUgMQp9CgovdmFyL2xvZy9idG1wIHsKICAgIG1pc3NpbmdvawogICAgbW9udGhseQogICAgY3JlYXRlIDA2MDAgcm9vdCB1dG1wCiAgICByb3RhdGUgMQp9CgojIE1heGltdW0gbG9nIGRpcmVjdG9yeSBzaXplIGlzIDEwMEcgd2l0aCB0aGlzIGNvbmZpZ3VyYXRpb24KIyBTZXR0aW5nIGxpbWl0IHRvIDEwMEcgdG8gYWxsb3cgc3BhY2UgZm9yIG90aGVyIGxvZ2dpbmcgc2VydmljZXMKIyBjb3B5dHJ1bmNhdGUgaXMgYSBjcml0aWNhbCBvcHRpb24gdXNlZCB0byBwcmV2ZW50IGxvZ3MgZnJvbSBiZWluZyBzaGlwcGVkIHR3aWNlCiR7bG9nX2Rpcn0gewogICAgc2l6ZSAyMEcKICAgIHJvdGF0ZSA1CiAgICBjcmVhdGUgMDYwMCByb290IHJvb3QKICAgIGNvcHl0cnVuY2F0ZQogICAgbm9vbGRkaXIKICAgIGNvbXByZXNzCn0iCgogICAgd3JpdGVfZmlsZSBsb2dyb3RhdGVfY29uZl9maWxlbmFtZSBsb2dyb3RhdGVfY29uZl9maWxlIHRydWUKfQoKIyBjcmVhdGVfYXp1cmVfcnBtX3JlcG9zIGNyZWF0ZXMgL2V0Yy95dW0ucmVwb3MuZC9henVyZS5yZXBvIHJlcG9zaXRvcnkgZmlsZQpjcmVhdGVfYXp1cmVfcnBtX3JlcG9zKCkgewogICAgbG9nICJzdGFydGluZyIKCiAgICBsb2NhbCAtciBhenVyZV9yZXBvX2ZpbGVuYW1lPScvZXRjL3l1bS5yZXBvcy5kL2F6dXJlLnJlcG8nCiAgICBsb2NhbCAtciBhenVyZV9yZXBvX2ZpbGU9J1thenVyZS1jbGldCm5hbWU9YXp1cmUtY2xpCmJhc2V1cmw9aHR0cHM6Ly9wYWNrYWdlcy5taWNyb3NvZnQuY29tL3l1bXJlcG9zL2F6dXJlLWNsaQplbmFibGVkPXllcwpncGdjaGVjaz15ZXMKClthenVyZWNvcmVdCm5hbWU9YXp1cmVjb3JlCmJhc2V1cmw9aHR0cHM6Ly9wYWNrYWdlcy5taWNyb3NvZnQuY29tL3l1bXJlcG9zL2F6dXJlY29yZQplbmFibGVkPXllcwpncGdjaGVjaz1ubycKCiAgICB3cml0ZV9maWxlIGF6dXJlX3JlcG9fZmlsZW5hbWUgYXp1cmVfcmVwb19maWxlIHRydWUKfQoKIyBjb25maWd1cmVfc2VsaW51eApjb25maWd1cmVfc2VsaW51eCgpIHsKICAgIGxvZyAic3RhcnRpbmciCgogICAgbG9jYWwgLXIgcmVsYWJlbD0iJHsxOi1mYWxzZX0iCgogICAgYWxyZWFkeV9kZWZpbmVkX2lnbm9yZV9lcnJvcj0iRmlsZSBjb250ZXh0IGZvciAvdmFyL2xvZy9qb3VybmFsKC8uKik/IGFscmVhZHkgZGVmaW5lZCIKICAgIHNlbWFuYWdlIGZjb250ZXh0IC1hIC10IHZhcl9sb2dfdCAiL3Zhci9sb2cvam91cm5hbCgvLiopPyIgfHwgbG9nICIkYWxyZWFkeV9kZWZpbmVkX2lnbm9yZV9lcnJvciIKICAgIGNoY29uIC1SIHN5c3RlbV91Om9iamVjdF9yOnZhcl9sb2dfdDpzMCAvdmFyL29wdC9taWNyb3NvZnQvbGludXhtb25hZ2VudAoKICAgIGlmICIkcmVsYWJlbCI7IHRoZW4KICAgICAgICByZXN0b3JlY29uIC1SRiAvdmFyL2xvZy8qIHx8IGxvZyAiJGFscmVhZHlfZGVmaW5lZF9pZ25vcmVfZXJyb3IiCiAgICBmaQp9CgojIGNvbmZpZ3VyZV9maXJld2FsbGRfcnVsZXMKY29uZmlndXJlX2ZpcmV3YWxsZF9ydWxlcygpIHsKICAgIGxvZyAic3RhcnRpbmciCgogICAgIyBodHRwczovL2FjY2Vzcy5yZWRoYXQuY29tL3NlY3VyaXR5L2N2ZS9jdmUtMjAyMC0xMzQwMQogICAgbG9jYWwgLXIgcHJlZml4PSIvZXRjL3N5c2N0bC5kIgogICAgbG9jYWwgLXIgZGlzYWJsZV9hY2NlcHRfcmFfY29uZl9maWxlbmFtZT0iJHByZWZpeC8wMi1kaXNhYmxlLWFjY2VwdC1yYS5jb25mIgogICAgbG9jYWwgLXIgZGlzYWJsZV9hY2NlcHRfcmFfY29uZl9maWxlPSJuZXQuaXB2Ni5jb25mLmFsbC5hY2NlcHRfcmE9MCIKCiAgICB3cml0ZV9maWxlIGRpc2FibGVfYWNjZXB0X3JhX2NvbmZfZmlsZW5hbWUgZGlzYWJsZV9hY2NlcHRfcmFfY29uZl9maWxlIHRydWUKCiAgICBsb2NhbCAtciBkaXNhYmxlX2NvcmVfZmlsZW5hbWU9IiRwcmVmaXgvMDEtZGlzYWJsZS1jb3JlLmNvbmYiCiAgICBsb2NhbCAtciBkaXNhYmxlX2NvcmVfZmlsZT0ia2VybmVsLmNvcmVfcGF0dGVybiA9IHwvYmluL3RydWUKICAgICIKICAgIHdyaXRlX2ZpbGUgZGlzYWJsZV9jb3JlX2ZpbGVuYW1lIGRpc2FibGVfY29yZV9maWxlIHRydWUKCiAgICBzeXNjdGwgLS1zeXN0ZW0KCiAgICBsb2NhbCAtcmEgZW5hYmxlX3BvcnRzPSgKICAgICAgICAiODAvdGNwIgogICAgICAgICI4MDgxL3RjcCIKICAgICAgICAiNDQzL3RjcCIKICAgICkKCiAgICBsb2cgIkVuYWJsaW5nIHBvcnRzICR7ZW5hYmxlX3BvcnRzWypdfSBvbiBkZWZhdWx0IGZpcmV3YWxsZCB6b25lIgogICAgIyBzaGVsbGNoZWNrIGRpc2FibGU9U0MyMDY4CiAgICBmb3IgcG9ydCBpbiAke2VuYWJsZV9wb3J0c1tAXX07IGRvCiAgICAgICAgbG9nICJFbmFibGluZyBwb3J0ICRwb3J0IG5vdyIKICAgICAgICBmaXJld2FsbC1jbWQgIi0tYWRkLXBvcnQ9JHBvcnQiCiAgICBkb25lCgogICAgZmlyZXdhbGwtY21kIC0tcnVudGltZS10by1wZXJtYW5lbnQKfQoKIyBwdWxsX2NvbnRhaW5lcl9pbWFnZXMKcHVsbF9jb250YWluZXJfaW1hZ2VzKCkgewogICAgbG9nICJzdGFydGluZyIKCiAgICAjIFRoZSBtYW5hZ2VkIGlkZW50aXR5IHRoYXQgdGhlIFZNIHJ1bnMgYXMgb25seSBoYXMgYSBzaW5nbGUgcm9sZWFzc2lnbm1lbnQuCiAgICAjIFRoaXMgcm9sZSBhc3NpZ25tZW50IGlzIEFDUlB1bGwgd2hpY2ggaXMgbm90IG5lY2Vzc2FyaWx5IHByZXNlbnQgaW4gdGhlCiAgICAjIHN1YnNjcmlwdGlvbiB3ZSdyZSBkZXBsb3lpbmcgaW50by4gIElmIHRoZSBpZGVudGl0eSBkb2VzIG5vdCBoYXZlIGFueQogICAgIyByb2xlIGFzc2lnbm1lbnRzIHNjb3BlZCBvbiB0aGUgc3Vic2NyaXB0aW9uIHdlJ3JlIGRlcGxveWluZyBpbnRvLCBpdCB3aWxsCiAgICAjIG5vdCBzaG93IG9uIGF6IGxvZ2luIC1pLCB3aGljaCBpcyB3aHkgdGhlIGJlbG93IGxpbmUgaXMgY29tbWVudGVkLgogICAgIyBheiBhY2NvdW50IHNldCAtcyAiJFNVQlNDUklQVElPTklEIgogICAgYXogbG9naW4gLWkgLS1hbGxvdy1uby1zdWJzY3JpcHRpb25zCgogICAgIyBTdXBwcmVzcyBlbXVsYXRpb24gb3V0cHV0IGZvciBwb2RtYW4gaW5zdGVhZCBvZiBkb2NrZXIgZm9yIGF6IGFjciBjb21wYXRhYmlsaXR5CiAgICBta2RpciAtcCAvZXRjL2NvbnRhaW5lcnMvCiAgICBta2RpciAtcCAvcm9vdC8uZG9ja2VyCiAgICB0b3VjaCAvZXRjL2NvbnRhaW5lcnMvbm9kb2NrZXIKCgkjIFRoaXMgbmFtZSBpcyB1c2VkIGluIHRoZSBjYXNlIHRoYXQgYXogYWNyIGxvZ2luIHNlYXJjaGVzIGZvciB0aGlzIGluIGl0J3MgZW52aXJvbm1lbnQKICAgIGxvY2FsIC1yIFJFR0lTVFJZX0FVVEhfRklMRT0iL3Jvb3QvLmRvY2tlci9jb25maWcuanNvbiIKICAgIAogICAgbG9nICJsb2dnaW5nIGludG8gcHJvZCBhY3IiCiAgICBheiBhY3IgbG9naW4gLS1uYW1lICIkKHNlZCAtZSAnc3wuKi98fCcgPDw8IiRBQ1JSRVNPVVJDRUlEIikiCgogICAgTURNSU1BR0U9IiR7UlBJTUFHRSUlLyp9LyR7TURNSU1BR0UjIyovfSIKICAgIGRvY2tlciBwdWxsICIkTURNSU1BR0UiCiAgICBkb2NrZXIgcHVsbCAiJFJQSU1BR0UiCiAgICBkb2NrZXIgcHVsbCAiJEZMVUVOVEJJVElNQUdFIgoKICAgIGF6IGxvZ291dAp9CgojIGNvbmZpZ3VyZV9zeXN0ZW1fc2VydmljZXMgY3JlYXRlcywgY29uZmlndXJlcywgYW5kIGVuYWJsZXMgdGhlIGZvbGxvd2luZyBzeXN0ZW1kIHNlcnZpY2VzIGFuZCB0aW1lcnMKIyBzZXJ2aWNlcwojICAgZmx1ZW50Yml0CiMgICBtZG0KIyAgIG1kc2QKIyAgIGFycC1ycAojICAgYXJvLWRidG9rZW4KIyAgIGFyby1tb25pdG9yCiMgICBhcm8tcG9ydGFsCmNvbmZpZ3VyZV9zeXN0ZW1fc2VydmljZXMoKSB7CiAgICBjb25maWd1cmVfc2VydmljZV9mbHVlbnRiaXQKICAgIGNvbmZpZ3VyZV9zZXJ2aWNlX21kbQogICAgY29uZmlndXJlX3RpbWVyc19tZG1fbWRzZAogICAgY29uZmlndXJlX3NlcnZpY2VfYXJvX2dhdGV3YXkgIiQxIgogICAgY29uZmlndXJlX3NlcnZpY2VfbWRzZAp9CgojIGVuYWJsZV9hcm9fc2VydmljZXMgZW5hYmxlcyBhbGwgc2VydmljZXMgcmVxdWlyZWQgZm9yIGFybyBycAplbmFibGVfYXJvX3NlcnZpY2VzKCkgewogICAgbG9nICJzdGFydGluZyIKCiAgICBsb2NhbCAtcmEgYXJvX3NlcnZpY2VzPSgKICAgICAgYXJvLWdhdGV3YXkKICAgICAgYXVvbXMKICAgICAgYXpzZWNkCiAgICAgIGF6c2VjbW9uZAogICAgICBtZHNkCiAgICAgIG1kbQogICAgICBjaHJvbnlkCiAgICAgIGZsdWVudGJpdAogICAgKQogICAgbG9nICJlbmFibGluZyBnYXRld2F5IHNlcnZpY2VzICR7YXJvX3NlcnZpY2VzWypdfSIKICAgICMgc2hlbGxjaGVjayBkaXNhYmxlPVNDMjA2OAogICAgZm9yIHNlcnZpY2UgaW4gJHthcm9fc2VydmljZXNbQF19OyBkbwogICAgICAgIGxvZyAiRW5hYmxpbmcgJHNlcnZpY2Ugbm93IgogICAgICAgIHN5c3RlbWN0bCBlbmFibGUgIiRzZXJ2aWNlLnNlcnZpY2UiCiAgICBkb25lCn0KCiMgY29uZmlndXJlX3NlcnZpY2VfZmx1ZW50Yml0CmNvbmZpZ3VyZV9zZXJ2aWNlX2ZsdWVudGJpdCgpIHsKICAgIGxvZyAic3RhcnRpbmciCiAgICBsb2cgImNvbmZpZ3VyaW5nIGZsdWVudGJpdCBzZXJ2aWNlIgoKICAgIG1rZGlyIC1wIC9ldGMvZmx1ZW50Yml0LwogICAgbWtkaXIgLXAgL3Zhci9saWIvZmx1ZW50CgogICAgbG9jYWwgLXIgZmx1ZW50Yml0X2NvbmZfZmlsZW5hbWU9Jy9ldGMvZmx1ZW50Yml0L2ZsdWVudGJpdC5jb25mJwogICAgbG9jYWwgLXIgZmx1ZW50Yml0X2NvbmZfZmlsZT0iW0lOUFVUXQpOYW1lIHN5c3RlbWQKVGFnIGpvdXJuYWxkClN5c3RlbWRfRmlsdGVyIF9DT01NPWFybwpEQiAvdmFyL2xpYi9mbHVlbnQvam91cm5hbGRiCgpbRklMVEVSXQoJTmFtZSBtb2RpZnkKCU1hdGNoIGpvdXJuYWxkCglSZW1vdmVfd2lsZGNhcmQgXwoJUmVtb3ZlIFRJTUVTVEFNUAoKW09VVFBVVF0KCU5hbWUgZm9yd2FyZAoJTWF0Y2ggKgoJUG9ydCAyOTIzMCIKCiAgICB3cml0ZV9maWxlIGZsdWVudGJpdF9jb25mX2ZpbGVuYW1lIGZsdWVudGJpdF9jb25mX2ZpbGUgdHJ1ZQoKICAgIGxvY2FsIC1yIHN5c2NvbmZpZ19mbHVlbnRiaXRfZmlsZW5hbWU9Jy9ldGMvc3lzY29uZmlnL2ZsdWVudGJpdCcKICAgIGxvY2FsIC1yIHN5c2NvbmZpZ19mbHVlbnRiaXRfZmlsZT0iRkxVRU5UQklUSU1BR0U9JEZMVUVOVEJJVElNQUdFIgoKICAgIHdyaXRlX2ZpbGUgc3lzY29uZmlnX2ZsdWVudGJpdF9maWxlbmFtZSBzeXNjb25maWdfZmx1ZW50Yml0X2ZpbGUgdHJ1ZQoKICAgIGxvY2FsIC1yIGZsdWVudGJpdF9zZXJ2aWNlX2ZpbGVuYW1lPScvZXRjL3N5c3RlbWQvc3lzdGVtL2ZsdWVudGJpdC5zZXJ2aWNlJwoKICAgIGxvY2FsIC1yIGZsdWVudGJpdF9zZXJ2aWNlX2ZpbGU9IltVbml0XQpBZnRlcj1uZXR3b3JrLW9ubGluZS50YXJnZXQKV2FudHM9bmV0d29yay1vbmxpbmUudGFyZ2V0ClN0YXJ0TGltaXRJbnRlcnZhbFNlYz0wCgpbU2VydmljZV0KUmVzdGFydFNlYz0xcwpFbnZpcm9ubWVudEZpbGU9L2V0Yy9zeXNjb25maWcvZmx1ZW50Yml0CkV4ZWNTdGFydFByZT0tL3Vzci9iaW4vZG9ja2VyIHJtIC1mICVOCkV4ZWNTdGFydD0vdXNyL2Jpbi9kb2NrZXIgcnVuIFwKICAtLXNlY3VyaXR5LW9wdCBsYWJlbD1kaXNhYmxlIFwKICAtLWVudHJ5cG9pbnQgL29wdC90ZC1hZ2VudC1iaXQvYmluL3RkLWFnZW50LWJpdCBcCiAgLS1uZXQ9aG9zdCBcCiAgLS1ob3N0bmFtZSAlSCBcCiAgLS1uYW1lICVOIFwKICAtLXJtIFwKICAtLWNhcC1kcm9wIG5ldF9yYXcgXAogIC12IC9ldGMvZmx1ZW50Yml0L2ZsdWVudGJpdC5jb25mOi9ldGMvZmx1ZW50Yml0L2ZsdWVudGJpdC5jb25mIFwKICAtdiAvdmFyL2xpYi9mbHVlbnQ6L3Zhci9saWIvZmx1ZW50OnogXAogIC12IC92YXIvbG9nL2pvdXJuYWw6L3Zhci9sb2cvam91cm5hbDpybyBcCiAgLXYgL2V0Yy9tYWNoaW5lLWlkOi9ldGMvbWFjaGluZS1pZDpybyBcCiAgJEZMVUVOVEJJVElNQUdFIFwKICAtYyAvZXRjL2ZsdWVudGJpdC9mbHVlbnRiaXQuY29uZgoKRXhlY1N0b3A9L3Vzci9iaW4vZG9ja2VyIHN0b3AgJU4KUmVzdGFydD1hbHdheXMKUmVzdGFydFNlYz01ClN0YXJ0TGltaXRJbnRlcnZhbD0wCgpbSW5zdGFsbF0KV2FudGVkQnk9bXVsdGktdXNlci50YXJnZXQiCgogICAgd3JpdGVfZmlsZSBmbHVlbnRiaXRfY29uZl9maWxlbmFtZSBmbHVlbnRiaXRfY29uZl9maWxlIHRydWUKfQoKIyBjb25maWd1cmVfY2VydHMKY29uZmlndXJlX2NlcnRzKCkgewogICAgbG9nICJzdGFydGluZyIKCiAgICBta2RpciAvZXRjL2Fyby1ycAogICAgYmFzZTY0IC1kIDw8PCIkQURNSU5BUElDQUJVTkRMRSIgPi9ldGMvYXJvLXJwL2FkbWluLWNhLWJ1bmRsZS5wZW0KICAgIGlmIFtbIC1uICIkQVJNQVBJQ0FCVU5ETEUiIF1dOyB0aGVuCiAgICBiYXNlNjQgLWQgPDw8IiRBUk1BUElDQUJVTkRMRSIgPi9ldGMvYXJvLXJwL2FybS1jYS1idW5kbGUucGVtCiAgICBmaQogICAgY2hvd24gLVIgMTAwMDoxMDAwIC9ldGMvYXJvLXJwCgogICAgIyBzZXR0aW5nIE1PTklUT1JJTkdfR0NTX0FVVEhfSURfVFlQRT1BdXRoS2V5VmF1bHQgc2VlbXMgdG8gaGF2ZSBjYXVzZWQgbWRzZCBub3QKICAgICMgdG8gaG9ub3VyIFNTTF9DRVJUX0ZJTEUgYW55IG1vcmUsIGhlYXZlbiBvbmx5IGtub3dzIHdoeS4KICAgIG1rZGlyIC1wIC91c3IvbGliL3NzbC9jZXJ0cwogICAgY3NwbGl0IC1mIC91c3IvbGliL3NzbC9jZXJ0cy9jZXJ0LSAtYiAlMDNkLnBlbSAvZXRjL3BraS90bHMvY2VydHMvY2EtYnVuZGxlLmNydCAvXiQvMSAieyp9IiA+L2Rldi9udWxsCiAgICBjX3JlaGFzaCAvdXNyL2xpYi9zc2wvY2VydHMKCiMgd2UgbGVhdmUgY2xpZW50SWQgYmxhbmsgYXMgbG9uZyBhcyBvbmx5IDEgbWFuYWdlZCBpZGVudGl0eSBhc3NpZ25lZCB0byB2bXNzCiMgaWYgd2UgaGF2ZSBtb3JlIHRoYW4gMSwgd2Ugd2lsbCBuZWVkIHRvIHBvcHVsYXRlIHdpdGggY2xpZW50SWQgdXNlZCBmb3Igb2ZmLW5vZGUgc2Nhbm5pbmcKICAgIGxvY2FsIC1yIG5vZGVzY2FuX2FnZW50X2ZpbGVuYW1lPSIvZXRjL2RlZmF1bHQvdnNhLW5vZGVzY2FuLWFnZW50LmNvbmZpZyIKICAgIGxvY2FsIC1yIG5vZGVzY2FuX2FnZW50X2ZpbGU9InsKICAgIFwiTmljZVwiOiAxOSwKICAgIFwiVGltZW91dFwiOiAxMDgwMCwKICAgIFwiQ2xpZW50SWRcIjogXCJcIiwKICAgIFwiVGVuYW50SWRcIjogJEFaVVJFU0VDUEFDS1ZTQVRFTkFOVElELAogICAgXCJRdWFseXNTdG9yZUJhc2VVcmxcIjogJEFaVVJFU0VDUEFDS1FVQUxZU1VSTCwKICAgIFwiUHJvY2Vzc1RpbWVvdXRcIjogMzAwLAogICAgXCJDb21tYW5kRGVsYXlcIjogMAogIH0iCgogICAgd3JpdGVfZmlsZSBub2Rlc2Nhbl9hZ2VudF9maWxlbmFtZSBub2Rlc2Nhbl9hZ2VudF9maWxlIHRydWUKfQoKIyBjb25maWd1cmVfc2VydmljZV9tZG0KY29uZmlndXJlX3NlcnZpY2VfbWRtKCkgewogICAgbG9nICJzdGFydGluZyIKICAgIGxvZyAiY29uZmlndXJpbmcgbWRtIHNlcnZpY2UiCgogICAgbG9jYWwgLXIgc3lzY29uZmlnX21kbV9maWxlbmFtZT0iL2V0Yy9zeXNjb25maWcvbWRtIgogICAgbG9jYWwgLXIgc3lzY29uZmlnX21kbV9maWxlPSJNRE1GUk9OVEVORFVSTD0nJE1ETUZST05URU5EVVJMJwpNRE1JTUFHRT0nJE1ETUlNQUdFJwpNRE1TT1VSQ0VFTlZJUk9OTUVOVD0nJExPQ0FUSU9OJwpNRE1TT1VSQ0VST0xFPWdhdGV3YXkKTURNU09VUkNFUk9MRUlOU1RBTkNFPVwiJChob3N0bmFtZSlcIiIKCiAgICB3cml0ZV9maWxlIHN5c2NvbmZpZ19tZG1fZmlsZW5hbWUgc3lzY29uZmlnX21kbV9maWxlIHRydWUKCiAgICBta2RpciAtcCAvdmFyL2V0dwogICAgbG9jYWwgLXIgbWRtX3NlcnZpY2VfZmlsZW5hbWU9Ii9ldGMvc3lzdGVtZC9zeXN0ZW0vbWRtLnNlcnZpY2UiCiAgICBsb2NhbCAtciBtZG1fc2VydmljZV9maWxlPSJbVW5pdF0KQWZ0ZXI9bmV0d29yay1vbmxpbmUudGFyZ2V0CldhbnRzPW5ldHdvcmstb25saW5lLnRhcmdldAoKW1NlcnZpY2VdCkVudmlyb25tZW50RmlsZT0vZXRjL3N5c2NvbmZpZy9tZG0KRXhlY1N0YXJ0UHJlPS0vdXNyL2Jpbi9kb2NrZXIgcm0gLWYgJU4KRXhlY1N0YXJ0PS91c3IvYmluL2RvY2tlciBydW4gXAogIC0tZW50cnlwb2ludCAvdXNyL3NiaW4vTWV0cmljc0V4dGVuc2lvbiBcCiAgLS1ob3N0bmFtZSAlSCBcCiAgLS1uYW1lICVOIFwKICAtLXJtIFwKICAtLWNhcC1kcm9wIG5ldF9yYXcgXAogIC1tIDJnIFwKICAtdiAvZXRjL21kbS5wZW06L2V0Yy9tZG0ucGVtIFwKICAtdiAvdmFyL2V0dzovdmFyL2V0dzp6IFwKICAkTURNSU1BR0UgXAogIC1DZXJ0RmlsZSAvZXRjL21kbS5wZW0gXAogIC1Gcm9udEVuZFVybCAkTURNRlJPTlRFTkRVUkwgXAogIC1Mb2dnZXIgQ29uc29sZSBcCiAgLUxvZ0xldmVsIFdhcm5pbmcgXAogIC1Qcml2YXRlS2V5RmlsZSAvZXRjL21kbS5wZW0gXAogIC1Tb3VyY2VFbnZpcm9ubWVudCAkTURNU09VUkNFRU5WSVJPTk1FTlQgXAogIC1Tb3VyY2VSb2xlICRNRE1TT1VSQ0VST0xFIFwKICAtU291cmNlUm9sZUluc3RhbmNlICRNRE1TT1VSQ0VST0xFSU5TVEFOQ0UKRXhlY1N0b3A9L3Vzci9iaW4vZG9ja2VyIHN0b3AgJU4KUmVzdGFydD1hbHdheXMKUmVzdGFydFNlYz0xClN0YXJ0TGltaXRJbnRlcnZhbD0wCgpbSW5zdGFsbF0KV2FudGVkQnk9bXVsdGktdXNlci50YXJnZXQiCgogICAgd3JpdGVfZmlsZSBtZG1fc2VydmljZV9maWxlbmFtZSBtZG1fc2VydmljZV9maWxlIHRydWUKfQoKIyBjb25maWd1cmVfdGltZXJzX21kbV9tZHNkCmNvbmZpZ3VyZV90aW1lcnNfbWRtX21kc2QoKSB7CiAgICBsb2cgInN0YXJ0aW5nIgoKICAgIGZvciB2YXIgaW4gIm1kc2QiICJtZG0iOyBkbwogICAgICAgIGxvY2FsIGRvd25sb2FkX2NyZWRzX3NlcnZpY2VfZmlsZW5hbWU9Ii9ldGMvc3lzdGVtZC9zeXN0ZW0vZG93bmxvYWQtJHZhci1jcmVkZW50aWFscy5zZXJ2aWNlIgogICAgICAgIGxvY2FsIGRvd25sb2FkX2NyZWRzX3NlcnZpY2VfZmlsZT0iW1VuaXRdCkRlc2NyaXB0aW9uPVBlcmlvZGljICR2YXIgY3JlZGVudGlhbHMgcmVmcmVzaAoKW1NlcnZpY2VdClR5cGU9b25lc2hvdApFeGVjU3RhcnQ9L3Vzci9sb2NhbC9iaW4vZG93bmxvYWQtY3JlZGVudGlhbHMuc2ggJHZhciIKCiAgICAgICAgd3JpdGVfZmlsZSBkb3dubG9hZF9jcmVkc19zZXJ2aWNlX2ZpbGVuYW1lIGRvd25sb2FkX2NyZWRzX3NlcnZpY2VfZmlsZSB0cnVlCgogICAgICAgIGxvY2FsIGRvd25sb2FkX2NyZWRzX3RpbWVyX2ZpbGVuYW1lPSIvZXRjL3N5c3RlbWQvc3lzdGVtL2Rvd25sb2FkLSR2YXItY3JlZGVudGlhbHMudGltZXIiCiAgICAgICAgbG9jYWwgZG93bmxvYWRfY3JlZHNfdGltZXJfZmlsZT0iW1VuaXRdCkRlc2NyaXB0aW9uPVBlcmlvZGljICR2YXIgY3JlZGVudGlhbHMgcmVmcmVzaApBZnRlcj1uZXR3b3JrLW9ubGluZS50YXJnZXQKV2FudHM9bmV0d29yay1vbmxpbmUudGFyZ2V0CgpbVGltZXJdCk9uQm9vdFNlYz0wbWluCk9uQ2FsZW5kYXI9MC8xMjowMDowMApBY2N1cmFjeVNlYz01cwoKW0luc3RhbGxdCldhbnRlZEJ5PXRpbWVycy50YXJnZXQiCgogICAgICAgIHdyaXRlX2ZpbGUgZG93bmxvYWRfY3JlZHNfdGltZXJfZmlsZW5hbWUgZG93bmxvYWRfY3JlZHNfdGltZXJfZmlsZSB0cnVlCiAgICBkb25lCgogICAgbG9jYWwgLXIgZG93bmxvYWRfY3JlZHNfc2NyaXB0X2ZpbGVuYW1lPSIvdXNyL2xvY2FsL2Jpbi9kb3dubG9hZC1jcmVkZW50aWFscy5zaCIKICAgIGxvY2FsIC1yIGRvd25sb2FkX2NyZWRzX3NjcmlwdF9maWxlPSIjIS9iaW4vYmFzaApzZXQgLWV1CgpDT01QT05FTlQ9XCQxCmVjaG8gXCJEb3dubG9hZCBcJENPTVBPTkVOVCBjcmVkZW50aWFsc1wiCgpURU1QX0RJUj1cIlwkKG1rdGVtcCAtZClcIgpleHBvcnQgQVpVUkVfQ09ORklHX0RJUj1cIlwkKG1rdGVtcCAtZClcIgoKZWNobyBcIkxvZ2dpbmcgaW50byBBenVyZS4uLlwiClJFVFJJRVM9Mwp3aGlsZSBbWyBcJFJFVFJJRVMgLWd0IDAgXV07IGRvCiAgICBpZiBheiBsb2dpbiAtaSAtLWFsbG93LW5vLXN1YnNjcmlwdGlvbnMKICAgIHRoZW4KICAgICAgICBlY2hvIFwiYXogbG9naW4gc3VjY2Vzc2Z1bFwiCiAgICAgICAgYnJlYWsKICAgIGVsc2UKICAgICAgICBlY2hvIFwiYXogbG9naW4gZmFpbGVkLiBSZXRyeWluZy4uLlwiCiAgICAgICAgbGV0IFJFVFJJRVMtPTEKICAgICAgICBzbGVlcCA1CiAgICBmaQpkb25lCgp0cmFwIFwiY2xlYW51cFwiIEVYSVQKCmNsZWFudXAoKSB7CiAgYXogbG9nb3V0CiAgW1sgXCRURU1QX0RJUiA9fiAvdG1wLy4rIF1dICYmIHJtIC1yZiBcJFRFTVBfRElSCiAgW1sgXCRBWlVSRV9DT05GSUdfRElSID1+IC90bXAvLisgXV0gJiYgcm0gLXJmIFwkQVpVUkVfQ09ORklHX0RJUgp9CgppZiBbWyBcJENPTVBPTkVOVCA9IFwibWRtXCIgXV07IHRoZW4KICBDVVJSRU5UX0NFUlRfRklMRT1cIi9ldGMvbWRtLnBlbVwiCmVsaWYgW1sgXCRDT01QT05FTlRcID0gXCJtZHNkXCIgXV07IHRoZW4KICBDVVJSRU5UX0NFUlRfRklMRT1cIi92YXIvbGliL3dhYWdlbnQvTWljcm9zb2Z0LkF6dXJlLktleVZhdWx0LlN0b3JlL21kc2QucGVtXCIKZWxzZQogIGVjaG8gSW52YWxpZCB1c2FnZSAmJiBleGl0IDEKZmkKClNFQ1JFVF9OQU1FPVwiZ3d5LVwke0NPTVBPTkVOVH1cIgpORVdfQ0VSVF9GSUxFPVwiXCRURU1QX0RJUi9cJENPTVBPTkVOVC5wZW1cIgpmb3IgYXR0ZW1wdCBpbiB7MS4uNX07IGRvCiAgYXoga2V5dmF1bHQgXAogICAgc2VjcmV0IFwKICAgIGRvd25sb2FkIFwKICAgIC0tZmlsZSBcIlwkTkVXX0NFUlRfRklMRVwiIFwKICAgIC0taWQgXCJodHRwczovLyRLRVlWQVVMVFBSRUZJWC1nd3kuJEtFWVZBVUxURE5TU1VGRklYL3NlY3JldHMvXCRTRUNSRVRfTkFNRVwiIFwKICAgICYmIGJyZWFrCiAgaWYgW1sgXCRhdHRlbXB0IC1sdCA1IF1dOyB0aGVuIHNsZWVwIDEwOyBlbHNlIGV4aXQgMTsgZmkKZG9uZQoKaWYgWyAtZiBcJE5FV19DRVJUX0ZJTEUgXTsgdGhlbgogIGlmIFtbIFwkQ09NUE9ORU5UID0gXCJtZHNkXCIgXV07IHRoZW4KICAgIGNob3duIHN5c2xvZzpzeXNsb2cgXCRORVdfQ0VSVF9GSUxFCiAgZWxzZQogICAgc2VkIC1pIC1uZSAnMSwvRU5EIENFUlRJRklDQVRFLyBwJyBcJE5FV19DRVJUX0ZJTEUKICBmaQoKICBuZXdfY2VydF9zbj1cIlwkKG9wZW5zc2wgeDUwOSAtaW4gXCJcJE5FV19DRVJUX0ZJTEVcIiAtbm9vdXQgLXNlcmlhbCB8IGF3ayAtRj0gJ3twcmludCBcJDJ9JylcIgogIGN1cnJlbnRfY2VydF9zbj1cIlwkKG9wZW5zc2wgeDUwOSAtaW4gXCJcJENVUlJFTlRfQ0VSVF9GSUxFXCIgLW5vb3V0IC1zZXJpYWwgfCBhd2sgLUY9ICd7cHJpbnQgXCQyfScpXCIKICBpZiBbWyAhIC16IFwkbmV3X2NlcnRfc24gXV0gJiYgW1sgXCRuZXdfY2VydF9zbiAhPSBcIlwkY3VycmVudF9jZXJ0X3NuXCIgXV07IHRoZW4KICAgIGVjaG8gdXBkYXRpbmcgY2VydGlmaWNhdGUgZm9yIFwkQ09NUE9ORU5UCiAgICBjaG1vZCAwNjAwIFwkTkVXX0NFUlRfRklMRQogICAgbXYgXCRORVdfQ0VSVF9GSUxFIFwkQ1VSUkVOVF9DRVJUX0ZJTEUKICBmaQplbHNlCiAgZWNobyBGYWlsZWQgdG8gcmVmcmVzaCBjZXJ0aWZpY2F0ZSBmb3IgXCRDT01QT05FTlQgJiYgZXhpdCAxCmZpIgoKICAgIHdyaXRlX2ZpbGUgZG93bmxvYWRfY3JlZHNfc2NyaXB0X2ZpbGVuYW1lIGRvd25sb2FkX2NyZWRzX3NjcmlwdF9maWxlIHRydWUKCiAgICBjaG1vZCB1K3ggL3Vzci9sb2NhbC9iaW4vZG93bmxvYWQtY3JlZGVudGlhbHMuc2gKCiAgICBzeXN0ZW1jdGwgZW5hYmxlIGRvd25sb2FkLW1kc2QtY3JlZGVudGlhbHMudGltZXIKICAgIHN5c3RlbWN0bCBlbmFibGUgZG93bmxvYWQtbWRtLWNyZWRlbnRpYWxzLnRpbWVyCgogICAgL3Vzci9sb2NhbC9iaW4vZG93bmxvYWQtY3JlZGVudGlhbHMuc2ggbWRzZAogICAgL3Vzci9sb2NhbC9iaW4vZG93bmxvYWQtY3JlZGVudGlhbHMuc2ggbWRtCgogICAgbG9jYWwgLXIgTURTRENFUlRJRklDQVRFU0FOPSIkKG9wZW5zc2wgeDUwOSAtaW4gL3Zhci9saWIvd2FhZ2VudC9NaWNyb3NvZnQuQXp1cmUuS2V5VmF1bHQuU3RvcmUvbWRzZC5wZW0gLW5vb3V0IC1zdWJqZWN0IHwgc2VkIC1lICdzLy4qQ04gPSAvLycpIgogICAgbG9jYWwgLXIgd2F0Y2hfbWRtX2NyZWRzX3NlcnZpY2VfZmlsZW5hbWU9Ii9ldGMvc3lzdGVtZC9zeXN0ZW0vd2F0Y2gtbWRtLWNyZWRlbnRpYWxzLnNlcnZpY2UiCiAgICBsb2NhbCAtciB3YXRjaF9tZG1fY3JlZHNfc2VydmljZV9maWxlPSJbVW5pdF0KRGVzY3JpcHRpb249V2F0Y2ggZm9yIGNoYW5nZXMgaW4gbWRtLnBlbSBhbmQgcmVzdGFydHMgdGhlIG1kbSBzZXJ2aWNlCgpbU2VydmljZV0KVHlwZT1vbmVzaG90CkV4ZWNTdGFydD0vdXNyL2Jpbi9zeXN0ZW1jdGwgcmVzdGFydCBtZG0uc2VydmljZQoKW0luc3RhbGxdCldhbnRlZEJ5PW11bHRpLXVzZXIudGFyZ2V0IgoKICAgIHdyaXRlX2ZpbGUgd2F0Y2hfbWRtX2NyZWRzX3NlcnZpY2VfZmlsZW5hbWUgd2F0Y2hfbWRtX2NyZWRzX3NlcnZpY2VfZmlsZSB0cnVlCgogICAgbG9jYWwgLXIgd2F0Y2hfbWRtX2NyZWRzX3BhdGhfZmlsZW5hbWU9Jy9ldGMvc3lzdGVtZC9zeXN0ZW0vd2F0Y2gtbWRtLWNyZWRlbnRpYWxzLnBhdGgnCiAgICBsb2NhbCAtciB3YXRjaF9tZG1fY3JlZHNfcGF0aF9maWxlPSdbUGF0aF0KUGF0aE1vZGlmaWVkPS9ldGMvbWRtLnBlbQoKW0luc3RhbGxdCldhbnRlZEJ5PW11bHRpLXVzZXIudGFyZ2V0JwoKICAgIHdyaXRlX2ZpbGUgd2F0Y2hfbWRtX2NyZWRzX3BhdGhfZmlsZW5hbWUgd2F0Y2hfbWRtX2NyZWRzX3BhdGhfZmlsZSB0cnVlCgogICAgbG9jYWwgLXIgd2F0Y2hfbWRtX2NyZWRzPSd3YXRjaC1tZG0tY3JlZGVudGlhbHMucGF0aCcKICAgIHN5c3RlbWN0bCBlbmFibGUgIiR3YXRjaF9tZG1fY3JlZHMiIHx8IGFib3J0ICJmYWlsZWQgdG8gZW5hYmxlICR3YXRjaF9tZG1fY3JlZHMiCiAgICBzeXN0ZW1jdGwgc3RhcnQgIiR3YXRjaF9tZG1fY3JlZHMiIHx8IGFib3J0ICJmYWlsZWQgdG8gc3RhcnQgJHdhdGNoX21kbV9jcmVkcyIKfQoKIyBjb25maWd1cmVfc2VydmljZV9hcm9fcnAKY29uZmlndXJlX3NlcnZpY2VfYXJvX2dhdGV3YXkoKSB7CiAgICBsb2NhbCAtbiBsb2dfZGlyPSIkMSIKICAgIGxvZyAic3RhcnRpbmciCgogICAgbG9jYWwgLXIgYXJvX2dhdGV3YXlfY29uZl9maWxlbmFtZT0nL2V0Yy9zeXNjb25maWcvYXJvLWdhdGV3YXknCiAgICBsb2NhbCAtciBhcm9fZ2F0ZXdheV9jb25mX2ZpbGU9IkFDUl9SRVNPVVJDRV9JRD0nJEFDUlJFU09VUkNFSUQnCkFETUlOX0FQSV9DTElFTlRfQ0VSVF9DT01NT05fTkFNRT0nJEFETUlOQVBJQ0xJRU5UQ0VSVENPTU1PTk5BTUUnCkFSTV9BUElfQ0xJRU5UX0NFUlRfQ09NTU9OX05BTUU9JyRBUk1BUElDTElFTlRDRVJUQ09NTU9OTkFNRScKQVpVUkVfQVJNX0NMSUVOVF9JRD0nJEFSTUNMSUVOVElEJwpBWlVSRV9GUF9DTElFTlRfSUQ9JyRGUENMSUVOVElEJwpBWlVSRV9GUF9TRVJWSUNFX1BSSU5DSVBBTF9JRD0nJEZQU0VSVklDRVBSSU5DSVBBTElEJwpCSUxMSU5HX0UyRV9TVE9SQUdFX0FDQ09VTlRfSUQ9JyRCSUxMSU5HRTJFU1RPUkFHRUFDQ09VTlRJRCcKQ0xVU1RFUl9NRE1fQUNDT1VOVD0nJENMVVNURVJNRE1BQ0NPVU5UJwpDTFVTVEVSX01ETV9OQU1FU1BBQ0U9UlAKQ0xVU1RFUl9NRFNEX0FDQ09VTlQ9JyRDTFVTVEVSTURTREFDQ09VTlQnCkNMVVNURVJfTURTRF9DT05GSUdfVkVSU0lPTj0nJENMVVNURVJNRFNEQ09ORklHVkVSU0lPTicKQ0xVU1RFUl9NRFNEX05BTUVTUEFDRT0nJENMVVNURVJNRFNETkFNRVNQQUNFJwpEQVRBQkFTRV9BQ0NPVU5UX05BTUU9JyREQVRBQkFTRUFDQ09VTlROQU1FJwpET01BSU5fTkFNRT0nJExPQ0FUSU9OLiRDTFVTVEVSUEFSRU5URE9NQUlOTkFNRScKQVpVUkVfREJUT0tFTl9DTElFTlRfSUQ9JyREQlRPS0VOQ0xJRU5USUQnCkRCVE9LRU5fVVJMPSckREJUT0tFTlVSTCcKTURNX0FDQ09VTlQ9JyRSUE1ETUFDQ09VTlQnCk1ETV9OQU1FU1BBQ0U9R2F0ZXdheQpHQVRFV0FZX0RPTUFJTlM9JyRHQVRFV0FZRE9NQUlOUycKR0FURVdBWV9GRUFUVVJFUz0nJEdBVEVXQVlGRUFUVVJFUycKR0FURVdBWV9SRVNPVVJDRUdST1VQPSckR0FURVdBWVJFU09VUkNFR1JPVVBOQU1FJwpLRVlWQVVMVF9QUkVGSVg9JyRLRVlWQVVMVFBSRUZJWCcKTURNX0FDQ09VTlQ9JyRSUE1ETUFDQ09VTlQnCk1ETV9OQU1FU1BBQ0U9UlAKTURTRF9FTlZJUk9OTUVOVD0nJE1EU0RFTlZJUk9OTUVOVCcKUlBfRkVBVFVSRVM9JyRSUEZFQVRVUkVTJwpSUElNQUdFPSckUlBJTUFHRScKQVJPX0lOU1RBTExfVklBX0hJVkU9JyRDTFVTVEVSU0lOU1RBTExWSUFISVZFJwpBUk9fSElWRV9ERUZBVUxUX0lOU1RBTExFUl9QVUxMU1BFQz0nJENMVVNURVJERUZBVUxUSU5TVEFMTEVSUFVMTFNQRUMnCkFST19BRE9QVF9CWV9ISVZFPSckQ0xVU1RFUlNBRE9QVEJZSElWRScKVVNFX0NIRUNLQUNDRVNTPSckVVNFQ0hFQ0tBQ0NFU1MnIgoKICAgIHdyaXRlX2ZpbGUgYXJvX2dhdGV3YXlfY29uZl9maWxlbmFtZSBhcm9fZ2F0ZXdheV9jb25mX2ZpbGUgdHJ1ZQoKICAgIGxvY2FsIC1yIGFyb19nYXRld2F5X3NlcnZpY2VfZmlsZW5hbWU9Jy9ldGMvc3lzdGVtZC9zeXN0ZW0vYXJvLWdhdGV3YXkuc2VydmljZScKCiAgICBsb2NhbCAtciBhcm9fZ2F0ZXdheV9zZXJ2aWNlX2ZpbGU9IltVbml0XQpBZnRlcj1uZXR3b3JrLW9ubGluZS50YXJnZXQKV2FudHM9bmV0d29yay1vbmxpbmUudGFyZ2V0CgpbU2VydmljZV0KRW52aXJvbm1lbnRGaWxlPS9ldGMvc3lzY29uZmlnL2Fyby1nYXRld2F5CkV4ZWNTdGFydFByZT0tL3Vzci9iaW4vZG9ja2VyIHJtIC1mICVOCkV4ZWNTdGFydFByZT0vdXNyL2Jpbi9ta2RpciAtcCAke2xvZ19kaXJ9CkV4ZWNTdGFydD0vdXNyL2Jpbi9kb2NrZXIgcnVuIFwKICAtLWhvc3RuYW1lICVIIFwKICAtLW5hbWUgJU4gXAogIC0tcm0gXAogIC0tY2FwLWRyb3AgbmV0X3JhdyBcCiAgLWUgQUNSX1JFU09VUkNFX0lEIFwKICAtZSBEQVRBQkFTRV9BQ0NPVU5UX05BTUUgXAogIC1lIEFaVVJFX0RCVE9LRU5fQ0xJRU5UX0lEIFwKICAtZSBEQlRPS0VOX1VSTCBcCiAgLWUgR0FURVdBWV9ET01BSU5TIFwKICAtZSBHQVRFV0FZX0ZFQVRVUkVTIFwKICAtZSBNRE1fQUNDT1VOVCBcCiAgLWUgTURNX05BTUVTUEFDRSBcCiAgLW0gMmcgXAogIC1wIDgwOjgwODAgXAogIC1wIDgwODE6ODA4MSBcCiAgLXAgNDQzOjg0NDMgXAogIC12IC9ydW4vc3lzdGVtZC9qb3VybmFsOi9ydW4vc3lzdGVtZC9qb3VybmFsIFwKICAtdiAvdmFyL2V0dzovdmFyL2V0dzp6IFwKICAtdiAke2xvZ19kaXJ9Oi9jdHIubG9nOnogXAogIFwkUlBJTUFHRSBcCiAgZ2F0ZXdheQpFeGVjU3RvcD0vdXNyL2Jpbi9kb2NrZXIgc3RvcCAtdCAzNjAwICVOClRpbWVvdXRTdG9wU2VjPTM2MDAKUmVzdGFydD1hbHdheXMKUmVzdGFydFNlYz0xClN0YXJ0TGltaXRJbnRlcnZhbD0wCgpbSW5zdGFsbF0KV2FudGVkQnk9bXVsdGktdXNlci50YXJnZXQKICAgICIKCiAgICB3cml0ZV9maWxlIGFyb19nYXRld2F5X3NlcnZpY2VfZmlsZW5hbWUgYXJvX2dhdGV3YXlfc2VydmljZV9maWxlIHRydWUKfQoKIyBjb25maWd1cmVfc2VydmljZV9hcm9fZGJ0b2tlbgpjb25maWd1cmVfc2VydmljZV9hcm9fZGJ0b2tlbigpIHsKICAgIGxvZyAic3RhcnRpbmciCgogICAgbG9jYWwgLXIgYXJvX2RidG9rZW5fc2VydmljZV9jb25mX2ZpbGVuYW1lPScvZXRjL3N5c2NvbmZpZy9hcm8tZGJ0b2tlbicKICAgIGxvY2FsIC1yIGFyb19kYnRva2VuX3NlcnZpY2VfY29uZl9maWxlPSJBQ1JfUkVTT1VSQ0VfSUQ9JyRBQ1JSRVNPVVJDRUlEJwpEQVRBQkFTRV9BQ0NPVU5UX05BTUU9JyREQVRBQkFTRUFDQ09VTlROQU1FJwpBWlVSRV9EQlRPS0VOX0NMSUVOVF9JRD0nJERCVE9LRU5DTElFTlRJRCcKREJUT0tFTl9VUkw9JyREQlRPS0VOVVJMJwpNRE1fQUNDT1VOVD0nJFJQTURNQUNDT1VOVCcKTURNX05BTUVTUEFDRT1HYXRld2F5CkdBVEVXQVlfRE9NQUlOUz0nJEdBVEVXQVlET01BSU5TJwpHQVRFV0FZX0ZFQVRVUkVTPSckR0FURVdBWUZFQVRVUkVTJwpSUElNQUdFPSckUlBJTUFHRSciCgogICAgd3JpdGVfZmlsZSBhcm9fZGJ0b2tlbl9zZXJ2aWNlX2NvbmZfZmlsZW5hbWUgYXJvX2RidG9rZW5fc2VydmljZV9jb25mX2ZpbGUgdHJ1ZQoKICAgIGxvY2FsIC1yIGFyb19kYnRva2VuX3NlcnZpY2VfZmlsZW5hbWU9Jy9ldGMvc3lzdGVtZC9zeXN0ZW0vYXJvLWRidG9rZW4uc2VydmljZScKICAgIGxvY2FsIC1yIGFyb19kYnRva2VuX3NlcnZpY2VfZmlsZT0iW1VuaXRdCkFmdGVyPW5ldHdvcmstb25saW5lLnRhcmdldApXYW50cz1uZXR3b3JrLW9ubGluZS50YXJnZXQKCltTZXJ2aWNlXQpFbnZpcm9ubWVudEZpbGU9L2V0Yy9zeXNjb25maWcvYXJvLWdhdGV3YXkKRXhlY1N0YXJ0UHJlPS0vdXNyL2Jpbi9kb2NrZXIgcm0gLWYgJU4KRXhlY1N0YXJ0UHJlPS91c3IvYmluL21rZGlyIC1wICR7Z2F0ZXdheV9sb2dkaXJ9CkV4ZWNTdGFydD0vdXNyL2Jpbi9kb2NrZXIgcnVuIFwKICAtLWhvc3RuYW1lICVIIFwKICAtLW5hbWUgJU4gXAogIC0tcm0gXAogIC0tY2FwLWRyb3AgbmV0X3JhdyBcCiAgLWUgQUNSX1JFU09VUkNFX0lEIFwKICAtZSBEQVRBQkFTRV9BQ0NPVU5UX05BTUUgXAogIC1lIEFaVVJFX0RCVE9LRU5fQ0xJRU5UX0lEIFwKICAtZSBEQlRPS0VOX1VSTCBcCiAgLWUgR0FURVdBWV9ET01BSU5TIFwKICAtZSBHQVRFV0FZX0ZFQVRVUkVTIFwKICAtZSBNRE1fQUNDT1VOVCBcCiAgLWUgTURNX05BTUVTUEFDRSBcCiAgLW0gMmcgXAogIC1wIDgwOjgwODAgXAogIC1wIDgwODE6ODA4MSBcCiAgLXAgNDQzOjg0NDMgXAogIC12IC9ydW4vc3lzdGVtZC9qb3VybmFsOi9ydW4vc3lzdGVtZC9qb3VybmFsIFwKICAtdiAvdmFyL2V0dzovdmFyL2V0dzp6IFwKICAtdiAke2dhdGV3YXlfbG9nZGlyfTovY3RyLmxvZzp6IFwKICBcJFJQSU1BR0UgXAogIGdhdGV3YXkKRXhlY1N0b3A9L3Vzci9iaW4vZG9ja2VyIHN0b3AgLXQgMzYwMCAlTgpUaW1lb3V0U3RvcFNlYz0zNjAwClJlc3RhcnQ9YWx3YXlzClJlc3RhcnRTZWM9MQpTdGFydExpbWl0SW50ZXJ2YWw9MAoKW0luc3RhbGxdCldhbnRlZEJ5PW11bHRpLXVzZXIudGFyZ2V0IgoKICAgIHdyaXRlX2ZpbGUgYXJvX2RidG9rZW5fc2VydmljZV9maWxlbmFtZSBhcm9fZGJ0b2tlbl9zZXJ2aWNlX2ZpbGUgdHJ1ZQp9CgojIGNvbmZpZ3VyZV9zZXJ2aWNlX21kc2QKY29uZmlndXJlX3NlcnZpY2VfbWRzZCgpIHsKICAgIGxvZyAic3RhcnRpbmciCgogICAgbG9jYWwgLXIgbWRzZF9zZXJ2aWNlX2Rpcj0iL2V0Yy9zeXN0ZW1kL3N5c3RlbS9tZHNkLnNlcnZpY2UuZCIKICAgIG1rZGlyICIkbWRzZF9zZXJ2aWNlX2RpciIKCiAgICBsb2NhbCAtciBtZHNkX292ZXJyaWRlX2NvbmZfZmlsZW5hbWU9IiRtZHNkX3NlcnZpY2VfZGlyL292ZXJyaWRlLmNvbmYiCiAgICBsb2NhbCAtciBtZHNkX292ZXJyaWRlX2NvbmZfZmlsZT0iW1VuaXRdCkFmdGVyPW5ldHdvcmstb25saW5lLnRhcmdldCIKCiAgICB3cml0ZV9maWxlIG1kc2Rfb3ZlcnJpZGVfY29uZl9maWxlbmFtZSBtZHNkX292ZXJyaWRlX2NvbmZfZmlsZSB0cnVlCgogICAgbG9jYWwgLXIgZGVmYXVsdF9tZHNkX2ZpbGVuYW1lPSIvZXRjL2RlZmF1bHQvbWRzZCIKICAgIGxvY2FsIC1yIGRlZmF1bHRfbWRzZF9maWxlPSJNRFNEX1JPTEVfUFJFRklYPS92YXIvcnVuL21kc2QvZGVmYXVsdApNRFNEX09QVElPTlM9XCItQSAtZCAtciBcJE1EU0RfUk9MRV9QUkVGSVhcIgoKZXhwb3J0IE1PTklUT1JJTkdfR0NTX0VOVklST05NRU5UPSckTURTREVOVklST05NRU5UJwpleHBvcnQgTU9OSVRPUklOR19HQ1NfQUNDT1VOVD0nJFJQTURTREFDQ09VTlQnCmV4cG9ydCBNT05JVE9SSU5HX0dDU19SRUdJT049JyRMT0NBVElPTicKZXhwb3J0IE1PTklUT1JJTkdfR0NTX0FVVEhfSURfVFlQRT1BdXRoS2V5VmF1bHQKZXhwb3J0IE1PTklUT1JJTkdfR0NTX0FVVEhfSUQ9JyRNRFNEQ0VSVElGSUNBVEVTQU4nCmV4cG9ydCBNT05JVE9SSU5HX0dDU19OQU1FU1BBQ0U9JyRSUE1EU0ROQU1FU1BBQ0UnCmV4cG9ydCBNT05JVE9SSU5HX0NPTkZJR19WRVJTSU9OPSckR0FURVdBWU1EU0RDT05GSUdWRVJTSU9OJwpleHBvcnQgTU9OSVRPUklOR19VU0VfR0VORVZBX0NPTkZJR19TRVJWSUNFPXRydWUKCmV4cG9ydCBNT05JVE9SSU5HX1RFTkFOVD0nJExPQ0FUSU9OJwpleHBvcnQgTU9OSVRPUklOR19ST0xFPWdhdGV3YXkKZXhwb3J0IE1PTklUT1JJTkdfUk9MRV9JTlNUQU5DRT1cIiQoaG9zdG5hbWUpXCIKCmV4cG9ydCBNRFNEX01TR1BBQ0tfU09SVF9DT0xVTU5TPTFcIiIKCiAgICB3cml0ZV9maWxlIGRlZmF1bHRfbWRzZF9maWxlbmFtZSBkZWZhdWx0X21kc2RfZmlsZSB0cnVlCgp9CgojIHJ1bl9henNlY2RfY29uZmlnX3NjYW4KcnVuX2F6c2VjZF9jb25maWdfc2NhbigpIHsKICAgIGxvZyAic3RhcnRpbmciCgogICAgbG9jYWwgLWFyIGNvbmZpZ3M9KAogICAgICAgICJiYXNlbGluZSIKICAgICAgICAiY2xhbWF2IgogICAgICAgICJzb2Z0d2FyZSIKICAgICkKCiAgICBsb2cgIlNjYW5uaW5nIGNvbmZpZ3VyYXRpb24gZmlsZXMgJHtjb25maWdzWypdfSIKICAgICMgc2hlbGxjaGVjayBkaXNhYmxlPVNDMjA2OAogICAgZm9yIHNjYW4gaW4gJHtjb25maWdzW0BdfTsgZG8KICAgICAgICBsb2cgIlNjYW5uaW5nIGNvbmZpZyBmaWxlICRzY2FuIG5vdyIKICAgICAgICAvdXNyL2xvY2FsL2Jpbi9henNlY2QgY29uZmlnIC1zICIkc2NhbiIgLWQgUDFECiAgICBkb25lCn0KCiMgd3JpdGVfZmlsZQojIEFyZ3MKIyAxKSBmaWxlbmFtZSAtIHN0cmluZwojIDIpIGZpbGVfY29udGVudHMgLSBzdHJpbmcKIyAzKSBjbG9iYmVyIC0gYm9vbGVhbjsgb3B0aW9uYWwgLSBkZWZhdWx0cyB0byBmYWxzZQp3cml0ZV9maWxlKCkgewogICAgbG9jYWwgLW4gZmlsZW5hbWU9IiQxIgogICAgbG9jYWwgLW4gZmlsZV9jb250ZW50cz0iJDIiCiAgICBsb2NhbCAtciBjbG9iYmVyPSIkezM6LWZhbHNlfSIKCiAgICBpZiAkY2xvYmJlcjsgdGhlbgogICAgICAgIGxvZyAiT3ZlcndyaXRpbmcgZmlsZSAkZmlsZW5hbWUiCiAgICAgICAgZWNobyAiJGZpbGVfY29udGVudHMiID4gIiRmaWxlbmFtZSIKICAgIGVsc2UKICAgICAgICBsb2cgIkFwcGVuZGluZyB0byAkZmlsZW5hbWUiCiAgICAgICAgZWNobyAiJGZpbGVfY29udGVudHMiID4+ICIkZmlsZW5hbWUiCiAgICBmaQp9CgojIHJlYm9vdF92bSByZXN0b3JlcyBhbGwgc2VsaW51eCBmaWxlIGNvbnRleHRzLCB3YWl0cyAzMCBzZWNvbmRzIHRoZW4gcmVib290cwpyZWJvb3Rfdm0oKSB7CiAgICBsb2cgInN0YXJ0aW5nIgoKICAgIGNvbmZpZ3VyZV9zZWxpbnV4ICJ0cnVlIgogICAgKHNsZWVwIDMwICYmIGxvZyAicmVib290aW5nIHZtIG5vdyI7IHJlYm9vdCkgJgp9CgojIGxvZyBpcyBhIHdyYXBwZXIgZm9yIGVjaG8gdGhhdCBpbmNsdWRlcyB0aGUgZnVuY3Rpb24gbmFtZQpsb2coKSB7CiAgICBsb2NhbCAtciBtc2c9IiR7MTotImxvZyBtZXNzYWdlIGlzIGVtcHR5In0iCiAgICBsb2NhbCAtciBzdGFja19sZXZlbD0iJHsyOi0xfSIKICAgIGVjaG8gIiR7RlVOQ05BTUVbJHtzdGFja19sZXZlbH1dfTogJHttc2d9Igp9CgojIGFib3J0IGlzIGEgd3JhcHBlciBmb3IgbG9nIHRoYXQgZXhpdHMgd2l0aCBhbiBlcnJvciBjb2RlCmFib3J0KCkgewogICAgbG9jYWwgLXJpIG9yaWdpbl9zdGFja2xldmVsPTIKICAgIGxvZyAiJHsxfSIgIiRvcmlnaW5fc3RhY2tsZXZlbCIKICAgIGxvZyAiRXhpdGluZyIKICAgIGV4aXQgMQp9CgpleHBvcnQgQVpVUkVfQ0xPVURfTkFNRT0iJHtBWlVSRUNMT1VETkFNRTo/IkZhaWxlZCB0byBjYXJyeSBvdmVyIHZhcmlhYmxlcyJ9IgoKbWFpbiAiJEAiCg==')))]" } } } diff --git a/pkg/deploy/assets/rp-production.json b/pkg/deploy/assets/rp-production.json index eec290c2170..99f72f4d6ff 100644 --- a/pkg/deploy/assets/rp-production.json +++ b/pkg/deploy/assets/rp-production.json @@ -516,7 +516,7 @@ "autoUpgradeMinorVersion": true, "settings": {}, "protectedSettings": { - "script": "[base64(concat(base64ToString('c2V0IC1leAoK'),'ACRRESOURCEID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('acrResourceId')),''')\n','ADMINAPICLIENTCERTCOMMONNAME=$(base64 -d \u003c\u003c\u003c''',base64(parameters('adminApiClientCertCommonName')),''')\n','ARMAPICLIENTCERTCOMMONNAME=$(base64 -d \u003c\u003c\u003c''',base64(parameters('armApiClientCertCommonName')),''')\n','ARMCLIENTID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('armClientId')),''')\n','AZURECLOUDNAME=$(base64 -d \u003c\u003c\u003c''',base64(parameters('azureCloudName')),''')\n','AZURESECPACKQUALYSURL=$(base64 -d \u003c\u003c\u003c''',base64(parameters('azureSecPackQualysUrl')),''')\n','AZURESECPACKVSATENANTID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('azureSecPackVSATenantId')),''')\n','BILLINGE2ESTORAGEACCOUNTID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('billingE2EStorageAccountId')),''')\n','CLUSTERMDMACCOUNT=$(base64 -d \u003c\u003c\u003c''',base64(parameters('clusterMdmAccount')),''')\n','CLUSTERMDSDACCOUNT=$(base64 -d \u003c\u003c\u003c''',base64(parameters('clusterMdsdAccount')),''')\n','CLUSTERMDSDCONFIGVERSION=$(base64 -d \u003c\u003c\u003c''',base64(parameters('clusterMdsdConfigVersion')),''')\n','CLUSTERMDSDNAMESPACE=$(base64 -d \u003c\u003c\u003c''',base64(parameters('clusterMdsdNamespace')),''')\n','CLUSTERPARENTDOMAINNAME=$(base64 -d \u003c\u003c\u003c''',base64(parameters('clusterParentDomainName')),''')\n','DATABASEACCOUNTNAME=$(base64 -d \u003c\u003c\u003c''',base64(parameters('databaseAccountName')),''')\n','DBTOKENCLIENTID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('dbtokenClientId')),''')\n','FLUENTBITIMAGE=$(base64 -d \u003c\u003c\u003c''',base64(parameters('fluentbitImage')),''')\n','FPCLIENTID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('fpClientId')),''')\n','FPSERVICEPRINCIPALID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('fpServicePrincipalId')),''')\n','GATEWAYDOMAINS=$(base64 -d \u003c\u003c\u003c''',base64(parameters('gatewayDomains')),''')\n','GATEWAYRESOURCEGROUPNAME=$(base64 -d \u003c\u003c\u003c''',base64(parameters('gatewayResourceGroupName')),''')\n','GATEWAYSERVICEPRINCIPALID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('gatewayServicePrincipalId')),''')\n','KEYVAULTDNSSUFFIX=$(base64 -d \u003c\u003c\u003c''',base64(parameters('keyvaultDNSSuffix')),''')\n','KEYVAULTPREFIX=$(base64 -d \u003c\u003c\u003c''',base64(parameters('keyvaultPrefix')),''')\n','MDMFRONTENDURL=$(base64 -d \u003c\u003c\u003c''',base64(parameters('mdmFrontendUrl')),''')\n','MDSDENVIRONMENT=$(base64 -d \u003c\u003c\u003c''',base64(parameters('mdsdEnvironment')),''')\n','PORTALACCESSGROUPIDS=$(base64 -d \u003c\u003c\u003c''',base64(parameters('portalAccessGroupIds')),''')\n','PORTALCLIENTID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('portalClientId')),''')\n','PORTALELEVATEDGROUPIDS=$(base64 -d \u003c\u003c\u003c''',base64(parameters('portalElevatedGroupIds')),''')\n','RPFEATURES=$(base64 -d \u003c\u003c\u003c''',base64(parameters('rpFeatures')),''')\n','RPIMAGE=$(base64 -d \u003c\u003c\u003c''',base64(parameters('rpImage')),''')\n','RPMDMACCOUNT=$(base64 -d \u003c\u003c\u003c''',base64(parameters('rpMdmAccount')),''')\n','RPMDSDACCOUNT=$(base64 -d \u003c\u003c\u003c''',base64(parameters('rpMdsdAccount')),''')\n','RPMDSDCONFIGVERSION=$(base64 -d \u003c\u003c\u003c''',base64(parameters('rpMdsdConfigVersion')),''')\n','RPMDSDNAMESPACE=$(base64 -d \u003c\u003c\u003c''',base64(parameters('rpMdsdNamespace')),''')\n','RPPARENTDOMAINNAME=$(base64 -d \u003c\u003c\u003c''',base64(parameters('rpParentDomainName')),''')\n','CLUSTERSINSTALLVIAHIVE=$(base64 -d \u003c\u003c\u003c''',base64(parameters('clustersInstallViaHive')),''')\n','CLUSTERSADOPTBYHIVE=$(base64 -d \u003c\u003c\u003c''',base64(parameters('clustersAdoptByHive')),''')\n','CLUSTERDEFAULTINSTALLERPULLSPEC=$(base64 -d \u003c\u003c\u003c''',base64(parameters('clusterDefaultInstallerPullspec')),''')\n','USECHECKACCESS=$(base64 -d \u003c\u003c\u003c''',base64(parameters('useCheckAccess')),''')\n','ADMINAPICABUNDLE=''',parameters('adminApiCaBundle'),'''\n','ARMAPICABUNDLE=''',parameters('armApiCaBundle'),'''\n','MDMIMAGE=''/genevamdm:2.2024.328.1744-c5fb79-20240328t1935''\n','LOCATION=$(base64 -d \u003c\u003c\u003c''',base64(resourceGroup().location),''')\n','SUBSCRIPTIONID=$(base64 -d \u003c\u003c\u003c''',base64(subscription().subscriptionId),''')\n','RESOURCEGROUPNAME=$(base64 -d \u003c\u003c\u003c''',base64(resourceGroup().name),''')\n','\n',base64ToString('IyEvYmluL2Jhc2gKCnNldCAtbyBlcnJleGl0IFwKICAgIC1vIG5vdW5zZXQKCnRyYXAgJ2NhdGNoJyBFUlIKCm1haW4oKSB7CiAgICBjb25maWd1cmVfc3NoZAogICAgY29uZmlndXJlX2FuZF9pbnN0YWxsX2RuZl9wa2dzX3JlcG9zCiAgICBjb25maWd1cmVfZGlza19wYXJ0aXRpb25zCiAgICBjb25maWd1cmVfbG9ncm90YXRlCiAgICBjb25maWd1cmVfc2VsaW51eAoKICAgIG1rZGlyIC1wIC92YXIvbG9nL2pvdXJuYWwKICAgIG1rZGlyIC1wIC92YXIvbGliL3dhYWdlbnQvTWljcm9zb2Z0LkF6dXJlLktleVZhdWx0LlN0b3JlCgogICAgY29uZmlndXJlX2ZpcmV3YWxsZF9ydWxlcwogICAgcHVsbF9jb250YWluZXJfaW1hZ2VzCiAgICBjb25maWd1cmVfc3lzdGVtX3NlcnZpY2VzCiAgICByZWJvb3Rfdm0KfQoKIyBXZSBuZWVkIHRvIGNvbmZpZ3VyZSBQYXNzd29yZEF1dGhlbnRpY2F0aW9uIHRvIHllcyBpbiBvcmRlciBmb3IgdGhlIFZNU1MgQWNjZXNzIEpJVCB0byB3b3JrCmNvbmZpZ3VyZV9zc2hkKCkgewogICAgbG9nICJzZXR0aW5nIHNzaCBwYXNzd29yZCBhdXRoZW50aWNhdGlvbiIKICAgIHNlZCAtaSAncy9QYXNzd29yZEF1dGhlbnRpY2F0aW9uIG5vL1Bhc3N3b3JkQXV0aGVudGljYXRpb24geWVzL2cnIC9ldGMvc3NoL3NzaGRfY29uZmlnCgogICAgc3lzdGVtY3RsIHJlbG9hZCBzc2hkLnNlcnZpY2UKICAgIHN5c3RlbWN0bCBpcy1hY3RpdmUgLS1xdWlldCBzc2hkIHx8IGFib3J0ICJzc2hkIGZhaWxlZCB0byByZWxvYWQiCn0KCiMgY29uZmlndXJlX2FuZF9pbnN0YWxsX2RuZl9wa2dzX3JlcG9zCmNvbmZpZ3VyZV9hbmRfaW5zdGFsbF9kbmZfcGtnc19yZXBvcygpIHsKICAgIGNvbmZpZ3VyZV9yaHVpX3JlcG8KICAgIGNyZWF0ZV9henVyZV9ycG1fcmVwb3MKICAgIGRuZl91cGRhdGVfcGtncwogICAgZG5mX2luc3RhbGxfcGtncwp9CgojIGNvbmZpZ3VyZV9yaHVpX3JlcG8KY29uZmlndXJlX3JodWlfcmVwbygpIHsKICAgIGxvZyAicnVubmluZyBSSFVJIHBhY2thZ2UgdXBkYXRlcyIKICAgICNBZGRpbmcgcmV0cnkgbG9naWMgdG8geXVtIGNvbW1hbmRzIGluIG9yZGVyIHRvIGF2b2lkIHN0YWxsaW5nIG91dCBvbiByZXNvdXJjZSBsb2NrcwogICAgZm9yIGF0dGVtcHQgaW4gezEuLjV9OyBkbwogICAgICAgIGRuZiB1cGRhdGUgXAogICAgICAgICAgICAteSBcCiAgICAgICAgICAgIC0tZGlzYWJsZXJlcG89JyonIFwKICAgICAgICAgICAgLS1lbmFibGVyZXBvPSdyaHVpLW1pY3Jvc29mdC1henVyZSonIFwKICAgICAgICAgICAgJiYgYnJlYWsKICAgICAgICBpZiBbWyAke2F0dGVtcHR9IC1sdCA1IF1dOyB0aGVuCiAgICAgICAgICAgIHNsZWVwIDEwCiAgICAgICAgZWxzZQogICAgICAgICAgICBhYm9ydCAiZmFpbGVkIHRvIHJ1biBkbmYgdXBkYXRlIgogICAgICAgIGZpCiAgICBkb25lCn0KCiMgZG5mX3VwZGF0ZV9wa2dzCmRuZl91cGRhdGVfcGtncygpIHsKICAgIGxvZyAicnVubmluZyBkbmYgdXBkYXRlIgogICAgZm9yIGF0dGVtcHQgaW4gezEuLjV9OyBkbwogICAgICAgIGRuZiAteSBcCiAgICAgICAgICAgIC14IFdBTGludXhBZ2VudCBcCiAgICAgICAgICAgIC14IFdBTGludXhBZ2VudC11ZGV2IFwKICAgICAgICAgICAgdXBkYXRlIC0tYWxsb3dlcmFzaW5nIFwKICAgICAgICAgICAgJiYgYnJlYWsKICAgICAgICBpZiBbWyAke2F0dGVtcHR9IC1sdCA1IF1dOyB0aGVuCiAgICAgICAgICAgIHNsZWVwIDEwCiAgICAgICAgZWxzZQogICAgICAgICAgICByZXR1cm4gMQogICAgICAgIGZpCiAgICBkb25lCn0KCiMgZG5mX2luc3RhbGxfcGtncwpkbmZfaW5zdGFsbF9wa2dzKCkgewogICAgbG9nICJpbXBvcnRpbmcgcnBtIHJlcG9zaXRvcmllcyIKICAgIHJwbSAtLWltcG9ydCBodHRwczovL2RsLmZlZG9yYXByb2plY3Qub3JnL3B1Yi9lcGVsL1JQTS1HUEctS0VZLUVQRUwtOAogICAgcnBtIC0taW1wb3J0IGh0dHBzOi8vcGFja2FnZXMubWljcm9zb2Z0LmNvbS9rZXlzL21pY3Jvc29mdC5hc2MKCiAgICBmb3IgYXR0ZW1wdCBpbiB7MS4uNX07IGRvCiAgICAgICAgZG5mIC15IFwKICAgICAgICAgICAgaW5zdGFsbCBodHRwczovL2RsLmZlZG9yYXByb2plY3Qub3JnL3B1Yi9lcGVsL2VwZWwtcmVsZWFzZS1sYXRlc3QtOC5ub2FyY2gucnBtIFwKICAgICAgICAgICAgJiYgYnJlYWsKICAgICAgICBpZiBbWyAke2F0dGVtcHR9IC1sdCA1IF1dOyB0aGVuCiAgICAgICAgICAgIHNsZWVwIDEwCiAgICAgICAgZWxzZQogICAgICAgICAgICByZXR1cm4gMQogICAgICAgIGZpCiAgICBkb25lCgogICAgZm9yIGF0dGVtcHQgaW4gezEuLjV9OyBkbwogICAgICAgIGRuZiAteSBcCiAgICAgICAgICAgIGluc3RhbGwgXAogICAgICAgICAgICBjbGFtYXYgXAogICAgICAgICAgICBhenNlYy1jbGFtYXYgXAogICAgICAgICAgICBhenNlYy1tb25pdG9yIFwKICAgICAgICAgICAgYXp1cmUtY2xpIFwKICAgICAgICAgICAgYXp1cmUtbWRzZCBcCiAgICAgICAgICAgIGF6dXJlLXNlY3VyaXR5IFwKICAgICAgICAgICAgcG9kbWFuIFwKICAgICAgICAgICAgcG9kbWFuLWRvY2tlciBcCiAgICAgICAgICAgIG9wZW5zc2wtcGVybCBcCiAgICAgICAgICAgIHB5dGhvbjMgXAogICAgICAgICAgICAmJiBicmVhawogICAgICAgICMgaGFjayAtIHdlIGFyZSBpbnN0YWxsaW5nIHB5dGhvbjMgb24gaG9zdHMgZHVlIHRvIGFuIGlzc3VlIHdpdGggQXp1cmUgTGludXggRXh0ZW5zaW9ucyBodHRwczovL2dpdGh1Yi5jb20vQXp1cmUvYXp1cmUtbGludXgtZXh0ZW5zaW9ucy9wdWxsLzE1MDUKICAgICAgICBpZiBbWyAke2F0dGVtcHR9IC1sdCA1IF1dOyB0aGVuCiAgICAgICAgICAgIHNsZWVwIDEwCiAgICAgICAgZWxzZQogICAgICAgICAgICBhYm9ydCAiZmFpbGVkIHRvIGluc3RhbGwgcmVxdWlyZWQgcGFja2FnZXMiCiAgICAgICAgZmkKICAgIGRvbmUKfQoKIyBjb25maWd1cmVfZGlza19wYXJ0aXRpb25zCmNvbmZpZ3VyZV9kaXNrX3BhcnRpdGlvbnMoKSB7CiAgICBsb2cgImV4dGVuZGluZyBwYXJ0aXRpb24gdGFibGUiCiAgICAjIExpbnV4IGJsb2NrIGRldmljZXMgYXJlIGluY29uc2lzdGVudGx5IG5hbWVkCiAgICAjIGl0J3MgZGlmZmljdWx0IHRvIHRpZSB0aGUgbHZtIHB2IHRvIHRoZSBwaHlzaWNhbCBkaXNrIHVzaW5nIC9kZXYvZGlzayBmaWxlcywgd2hpY2ggaXMgd2h5IGx2cyBpcyB1c2VkIGhlcmUKICAgIHBoeXNpY2FsRGlzaz0iJChsdnMgLW8gZGV2aWNlcyAtYSB8IGhlYWQgLW4yIHwgdGFpbCAtbjEgfCBjdXQgLWQgJyAnIC1mIDMgfCBjdXQgLWQgXCggLWYgMSB8IHRyIC1kICdbOmRpZ2l0Ol0nKSIKICAgIGdyb3dwYXJ0ICIkcGh5c2ljYWxEaXNrIiAyCgogICAgbG9nICJleHRlbmRpbmcgZmlsZXN5c3RlbXMiCiAgICBsb2cgImV4dGVuZGluZyByb290IGx2bSIKICAgIGx2ZXh0ZW5kIC1sICsyMCVGUkVFIC9kZXYvcm9vdHZnL3Jvb3RsdgogICAgbG9nICJncm93aW5nIHJvb3QgZmlsZXN5c3RlbSIKICAgIHhmc19ncm93ZnMgLwoKICAgIGxvZyAiZXh0ZW5kaW5nIHZhciBsdm0iCiAgICBsdmV4dGVuZCAtbCArMTAwJUZSRUUgL2Rldi9yb290dmcvdmFybHYKICAgIGxvZyAiZ3Jvd2luZyB2YXIgZmlsZXN5c3RlbSIKICAgIHhmc19ncm93ZnMgL3Zhcgp9CgojIGNvbmZpZ3VyZV9sb2dyb3RhdGUgY2xvYmJlcnMgL2V0Yy9sb2dyb3RhdGUuY29uZgpjb25maWd1cmVfbG9ncm90YXRlKCkgewogICAgbG9jYWwgLXIgbG9ncm90YXRlX2NvbmZfZmlsZW5hbWU9Jy9ldGMvbG9ncm90YXRlLmNvbmYnCiAgICBsb2NhbCAtciBsb2dyb3RhdGVfY29uZl9maWxlPScjIHNlZSAibWFuIGxvZ3JvdGF0ZSIgZm9yIGRldGFpbHMKIyByb3RhdGUgbG9nIGZpbGVzIHdlZWtseQp3ZWVrbHkKCiMga2VlcCAyIHdlZWtzIHdvcnRoIG9mIGJhY2tsb2dzCnJvdGF0ZSAyCgojIGNyZWF0ZSBuZXcgKGVtcHR5KSBsb2cgZmlsZXMgYWZ0ZXIgcm90YXRpbmcgb2xkIG9uZXMKY3JlYXRlCgojIHVzZSBkYXRlIGFzIGEgc3VmZml4IG9mIHRoZSByb3RhdGVkIGZpbGUKZGF0ZWV4dAoKIyB1bmNvbW1lbnQgdGhpcyBpZiB5b3Ugd2FudCB5b3VyIGxvZyBmaWxlcyBjb21wcmVzc2VkCmNvbXByZXNzCgojIFJQTSBwYWNrYWdlcyBkcm9wIGxvZyByb3RhdGlvbiBpbmZvcm1hdGlvbiBpbnRvIHRoaXMgZGlyZWN0b3J5CmluY2x1ZGUgL2V0Yy9sb2dyb3RhdGUuZAoKIyBubyBwYWNrYWdlcyBvd24gd3RtcCBhbmQgYnRtcCAtLSB3ZSB3aWxsIHJvdGF0ZSB0aGVtIGhlcmUKL3Zhci9sb2cvd3RtcCB7CiAgICBtb250aGx5CiAgICBjcmVhdGUgMDY2NCByb290IHV0bXAKICAgICAgICBtaW5zaXplIDFNCiAgICByb3RhdGUgMQp9CgovdmFyL2xvZy9idG1wIHsKICAgIG1pc3NpbmdvawogICAgbW9udGhseQogICAgY3JlYXRlIDA2MDAgcm9vdCB1dG1wCiAgICByb3RhdGUgMQp9JwoKICAgIHdyaXRlX2ZpbGUgbG9ncm90YXRlX2NvbmZfZmlsZW5hbWUgbG9ncm90YXRlX2NvbmZfZmlsZSB0cnVlCn0KCiMgY3JlYXRlX2F6dXJlX3JwbV9yZXBvcyBjcmVhdGVzIC9ldGMveXVtLnJlcG9zLmQvYXp1cmUucmVwbyByZXBvc2l0b3J5IGZpbGUKY3JlYXRlX2F6dXJlX3JwbV9yZXBvcygpIHsKICAgIGxvY2FsIC1yIGF6dXJlX3JlcG9fZmlsZW5hbWU9Jy9ldGMveXVtLnJlcG9zLmQvYXp1cmUucmVwbycKICAgIGxvY2FsIC1yIGF6dXJlX3JlcG9fZmlsZT0nW2F6dXJlLWNsaV0KbmFtZT1henVyZS1jbGkKYmFzZXVybD1odHRwczovL3BhY2thZ2VzLm1pY3Jvc29mdC5jb20veXVtcmVwb3MvYXp1cmUtY2xpCmVuYWJsZWQ9eWVzCmdwZ2NoZWNrPXllcwoKW2F6dXJlY29yZV0KbmFtZT1henVyZWNvcmUKYmFzZXVybD1odHRwczovL3BhY2thZ2VzLm1pY3Jvc29mdC5jb20veXVtcmVwb3MvYXp1cmVjb3JlCmVuYWJsZWQ9eWVzCmdwZ2NoZWNrPW5vJwoKICAgIHdyaXRlX2ZpbGUgYXp1cmVfcmVwb19maWxlbmFtZSBhenVyZV9yZXBvX2ZpbGUKfQoKIyBjb25maWd1cmVfc2VsaW51eApjb25maWd1cmVfc2VsaW51eCgpIHsKICAgIGxvY2FsIC1yIHJlbGFiZWw9IiR7MTotZmFsc2V9IgoKICAgIGFscmVhZHlfZGVmaW5lZF9pZ25vcmVfZXJyb3I9IkZpbGUgY29udGV4dCBmb3IgL3Zhci9sb2cvam91cm5hbCgvLiopPyBhbHJlYWR5IGRlZmluZWQiCiAgICBzZW1hbmFnZSBmY29udGV4dCAtYSAtdCB2YXJfbG9nX3QgIi92YXIvbG9nL2pvdXJuYWwoLy4qKT8iIHx8IGxvZyAiJGFscmVhZHlfZGVmaW5lZF9pZ25vcmVfZXJyb3IiCiAgICBjaGNvbiAtUiBzeXN0ZW1fdTpvYmplY3Rfcjp2YXJfbG9nX3Q6czAgL3Zhci9vcHQvbWljcm9zb2Z0L2xpbnV4bW9uYWdlbnQKCiAgICBpZiAiJHJlbGFiZWwiOyB0aGVuCiAgICAgICAgcmVzdG9yZWNvbiAtUkYgL3Zhci9sb2cvKiB8fCBsb2cgIiRhbHJlYWR5X2RlZmluZWRfaWdub3JlX2Vycm9yIgogICAgZmkKfQoKIyBjb25maWd1cmVfZmlyZXdhbGxkX3J1bGVzCmNvbmZpZ3VyZV9maXJld2FsbGRfcnVsZXMoKSB7CiAgICAjIGh0dHBzOi8vYWNjZXNzLnJlZGhhdC5jb20vc2VjdXJpdHkvY3ZlL2N2ZS0yMDIwLTEzNDAxCiAgICBsb2NhbCAtciBwcmVmaXg9Ii9ldGMvc3lzY3RsLmQiCiAgICBsb2NhbCAtciBkaWFibGVfYWNjZXB0X3JhX2NvbmY9IiRwcmVmaXgvMDItZGlzYWJsZS1hY2NlcHQtcmEuY29uZiIKICAgIGxvZyAiV3JpdGluZyAkZGlhYmxlX2FjY2VwdF9yYV9jb25mIgpjYXQgPiIkZGlhYmxlX2FjY2VwdF9yYV9jb25mIiA8PCdFT0YnCm5ldC5pcHY2LmNvbmYuYWxsLmFjY2VwdF9yYT0wCkVPRgoKICAgIGxvY2FsIC1yIGRpc2FibGVfY29yZV9maWxlbmFtZT0iJHByZWZpeC8wMS1kaXNhYmxlLWNvcmUuY29uZiIKICAgIGxvY2FsIC1yIGRpc2FibGVfY29yZV9maWxlPSJrZXJuZWwuY29yZV9wYXR0ZXJuID0gfC9iaW4vdHJ1ZQogICAgIgogICAgd3JpdGVfZmlsZSBkaXNhYmxlX2NvcmVfZmlsZW5hbWUgZGlzYWJsZV9jb3JlX2ZpbGUKCiAgICBzeXNjdGwgLS1zeXN0ZW0KCiAgICBlbmFibGVfcG9ydHM9KAogICAgICAgICI0NDMvdGNwIgogICAgICAgICI0NDQvdGNwIgogICAgICAgICI0NDUvdGNwIgogICAgICAgICIyMjIyL3RjcCIKICAgICkKICAgIGxvZyAiRW5hYmxpbmcgcG9ydHMgJHtlbmFibGVfcG9ydHNbKl19IG9uIGRlZmF1bHQgZmlyZXdhbGxkIHpvbmUiCiAgICAjIHNoZWxsY2hlY2sgZGlzYWJsZT1TQzIwNjgKICAgIGZvciBwb3J0IGluICR7ZW5hYmxlX3BvcnRzW0BdfTsgZG8KICAgICAgICBsb2cgIkVuYWJsaW5nIHBvcnQgJHBvcnQgbm93IgogICAgICAgIGZpcmV3YWxsLWNtZCAiLS1hZGQtcG9ydD0kcG9ydCIKICAgIGRvbmUKCiAgICBmaXJld2FsbC1jbWQgLS1ydW50aW1lLXRvLXBlcm1hbmVudAp9CgojIHB1bGxfY29udGFpbmVyX2ltYWdlcwpwdWxsX2NvbnRhaW5lcl9pbWFnZXMoKSB7CiAgICBlY2hvICJsb2dnaW5nIGludG8gcHJvZCBhY3IiCiAgICBheiBsb2dpbiAtaSAtLWFsbG93LW5vLXN1YnNjcmlwdGlvbnMKCiAgICAjIFN1cHByZXNzIGVtdWxhdGlvbiBvdXRwdXQgZm9yIHBvZG1hbiBpbnN0ZWFkIG9mIGRvY2tlciBmb3IgYXogYWNyIGNvbXBhdGFiaWxpdHkKICAgIG1rZGlyIC1wIC9ldGMvY29udGFpbmVycy8KICAgIHRvdWNoIC9ldGMvY29udGFpbmVycy9ub2RvY2tlcgoKICAgIG1rZGlyIC1wIC9yb290Ly5kb2NrZXIKICAgIGxvY2FsIC1yIFJFR0lTVFJZX0FVVEhfRklMRT0iL3Jvb3QvLmRvY2tlci9jb25maWcuanNvbiIKICAgIAogICAgYXogYWNyIGxvZ2luIC0tbmFtZSAiJChzZWQgLWUgJ3N8LiovfHwnIDw8PCIkQUNSUkVTT1VSQ0VJRCIpIgoKICAgIE1ETUlNQUdFPSIke1JQSU1BR0UlJS8qfS8ke01ETUlNQUdFIyMqL30iCiAgICBkb2NrZXIgcHVsbCAiJE1ETUlNQUdFIgogICAgZG9ja2VyIHB1bGwgIiRSUElNQUdFIgogICAgZG9ja2VyIHB1bGwgIiRGTFVFTlRCSVRJTUFHRSIKCiAgICBheiBsb2dvdXQKfQoKIyBjb25maWd1cmVfc3lzdGVtX3NlcnZpY2VzIGNyZWF0ZXMsIGNvbmZpZ3VyZXMsIGFuZCBlbmFibGVzIHRoZSBmb2xsb3dpbmcgc3lzdGVtZCBzZXJ2aWNlcyBhbmQgdGltZXJzCiMgc2VydmljZXMKIyAgIGZsdWVudGJpdAojICAgbWRtCiMgICBtZHNkCiMgICBhcnAtcnAKIyAgIGFyby1kYnRva2VuCiMgICBhcm8tbW9uaXRvcgojICAgYXJvLXBvcnRhbApjb25maWd1cmVfc3lzdGVtX3NlcnZpY2VzKCkgewogICAgY29uZmlndXJlX3NlcnZpY2VfZmx1ZW50Yml0CiAgICBjb25maWd1cmVfc2VydmljZV9tZG0KICAgIGNvbmZpZ3VyZV90aW1lcnNfbWRtX21kc2QKICAgIGNvbmZpZ3VyZV9zZXJ2aWNlX2Fyb19ycAogICAgY29uZmlndXJlX3NlcnZpY2VfYXJvX2RidG9rZW4KICAgIGNvbmZpZ3VyZV9zZXJ2aWNlX2Fyb19tb25pdG9yCiAgICBjb25maWd1cmVfc2VydmljZV9hcm9fcG9ydGFsCiAgICBjb25maWd1cmVfc2VydmljZV9tZHNkCn0KCiMgZW5hYmxlX2Fyb19zZXJ2aWNlcyBlbmFibGVzIGFsbCBzZXJ2aWNlcyByZXF1aXJlZCBmb3IgYXJvIHJwCmVuYWJsZV9hcm9fc2VydmljZXMoKSB7CiAgICBsb2NhbCAtcmEgYXJvX3NlcnZpY2VzPSgKICAgICAgICAiYXJvLWRidG9rZW4iCiAgICAgICAgImFyby1tb25pdG9yIgogICAgICAgICJhcm8tcG9ydGFsIgogICAgICAgICJhcm8tcnAiCiAgICAgICAgImF1b21zIgogICAgICAgICJhenNlY2QiCiAgICAgICAgImF6c2VjbW9uZCIKICAgICAgICAibWRzZCIKICAgICAgICAibWRtIgogICAgICAgICJjaHJvbnlkIgogICAgICAgICJmbHVlbnRiaXQiCiAgICApCiAgICBsb2cgImVuYWJsaW5nIGFybyBzZXJ2aWNlcyAke2Fyb19zZXJ2aWNlc1sqXX0iCiAgICAjIHNoZWxsY2hlY2sgZGlzYWJsZT1TQzIwNjgKICAgIGZvciBzZXJ2aWNlIGluICR7YXJvX3NlcnZpY2VzW0BdfTsgZG8KICAgICAgICBsb2cgIkVuYWJsaW5nICRzZXJ2aWNlIG5vdyIKICAgICAgICBzeXN0ZW1jdGwgZW5hYmxlICIkc2VydmljZS5zZXJ2aWNlIgogICAgZG9uZQp9CgojIGNvbmZpZ3VyZV9zZXJ2aWNlX2ZsdWVudGJpdApjb25maWd1cmVfc2VydmljZV9mbHVlbnRiaXQoKSB7CiAgICBsb2cgImNvbmZpZ3VyaW5nIGZsdWVudGJpdCBzZXJ2aWNlIgogICAgbWtkaXIgLXAgL2V0Yy9mbHVlbnRiaXQvCiAgICBta2RpciAtcCAvdmFyL2xpYi9mbHVlbnQKCiAgICBsb2NhbCAtciBmbHVlbnRiaXRfY29uZl9maWxlbmFtZT0nL2V0Yy9mbHVlbnRiaXQvZmx1ZW50Yml0LmNvbmYnCiAgICBsb2NhbCAtciBmbHVlbnRiaXRfY29uZl9maWxlPSJbSU5QVVRdCk5hbWUgc3lzdGVtZApUYWcgam91cm5hbGQKU3lzdGVtZF9GaWx0ZXIgX0NPTU09YXJvCkRCIC92YXIvbGliL2ZsdWVudC9qb3VybmFsZGIKCltGSUxURVJdCglOYW1lIG1vZGlmeQoJTWF0Y2ggam91cm5hbGQKCVJlbW92ZV93aWxkY2FyZCBfCglSZW1vdmUgVElNRVNUQU1QCgpbRklMVEVSXQoJTmFtZSByZXdyaXRlX3RhZwoJTWF0Y2ggam91cm5hbGQKCVJ1bGUgJExPR0tJTkQgYXN5bmNxb3MgYXN5bmNxb3MgdHJ1ZQoKW0ZJTFRFUl0KCU5hbWUgbW9kaWZ5CglNYXRjaCBhc3luY3FvcwoJUmVtb3ZlIENMSUVOVF9QUklOQ0lQQUxfTkFNRQoJUmVtb3ZlIEZJTEUKCVJlbW92ZSBDT01QT05FTlQKCltGSUxURVJdCglOYW1lIHJld3JpdGVfdGFnCglNYXRjaCBqb3VybmFsZAoJUnVsZSAkTE9HS0lORCBpZnhhdWRpdCBpZnhhdWRpdCBmYWxzZQoKW09VVFBVVF0KCU5hbWUgZm9yd2FyZAoJTWF0Y2ggKgoJUG9ydCAyOTIzMCIKCiAgICB3cml0ZV9maWxlIGZsdWVudGJpdF9jb25mX2ZpbGVuYW1lIGZsdWVudGJpdF9jb25mX2ZpbGUKCiAgICBsb2NhbCAtciBzeXNjb25maWdfZmx1ZW50Yml0X2ZpbGVuYW1lPScvZXRjL3N5c2NvbmZpZy9mbHVlbnRiaXQnCiAgICBsb2NhbCAtciBzeXNjb25maWdfZmx1ZW50Yml0X2ZpbGU9IkZMVUVOVEJJVElNQUdFPSRGTFVFTlRCSVRJTUFHRSIKCiAgICB3cml0ZV9maWxlIHN5c2NvbmZpZ19mbHVlbnRiaXRfZmlsZW5hbWUgc3lzY29uZmlnX2ZsdWVudGJpdF9maWxlCgogICAgbG9jYWwgLXIgZmx1ZW50Yml0X3NlcnZpY2VfZmlsZW5hbWU9Jy9ldGMvc3lzdGVtZC9zeXN0ZW0vZmx1ZW50Yml0LnNlcnZpY2UnCgogICAgbG9jYWwgLXIgZmx1ZW50Yml0X3NlcnZpY2VfZmlsZT0iW1VuaXRdCkFmdGVyPW5ldHdvcmstb25saW5lLnRhcmdldApXYW50cz1uZXR3b3JrLW9ubGluZS50YXJnZXQKU3RhcnRMaW1pdEludGVydmFsU2VjPTAKCltTZXJ2aWNlXQpSZXN0YXJ0U2VjPTFzCkVudmlyb25tZW50RmlsZT0vZXRjL3N5c2NvbmZpZy9mbHVlbnRiaXQKRXhlY1N0YXJ0UHJlPS0vdXNyL2Jpbi9kb2NrZXIgcm0gLWYgJU4KRXhlY1N0YXJ0PS91c3IvYmluL2RvY2tlciBydW4gXAogIC0tc2VjdXJpdHktb3B0IGxhYmVsPWRpc2FibGUgXAogIC0tZW50cnlwb2ludCAvb3B0L3RkLWFnZW50LWJpdC9iaW4vdGQtYWdlbnQtYml0IFwKICAtLW5ldD1ob3N0IFwKICAtLWhvc3RuYW1lICVIIFwKICAtLW5hbWUgJU4gXAogIC0tcm0gXAogIC0tY2FwLWRyb3AgbmV0X3JhdyBcCiAgLXYgL2V0Yy9mbHVlbnRiaXQvZmx1ZW50Yml0LmNvbmY6L2V0Yy9mbHVlbnRiaXQvZmx1ZW50Yml0LmNvbmYgXAogIC12IC92YXIvbGliL2ZsdWVudDovdmFyL2xpYi9mbHVlbnQ6eiBcCiAgLXYgL3Zhci9sb2cvam91cm5hbDovdmFyL2xvZy9qb3VybmFsOnJvIFwKICAtdiAvZXRjL21hY2hpbmUtaWQ6L2V0Yy9tYWNoaW5lLWlkOnJvIFwKICAkRkxVRU5UQklUSU1BR0UgXAogIC1jIC9ldGMvZmx1ZW50Yml0L2ZsdWVudGJpdC5jb25mCgpFeGVjU3RvcD0vdXNyL2Jpbi9kb2NrZXIgc3RvcCAlTgpSZXN0YXJ0PWFsd2F5cwpSZXN0YXJ0U2VjPTUKU3RhcnRMaW1pdEludGVydmFsPTAKCltJbnN0YWxsXQpXYW50ZWRCeT1tdWx0aS11c2VyLnRhcmdldCIKCiAgICB3cml0ZV9maWxlIGZsdWVudGJpdF9jb25mX2ZpbGVuYW1lIGZsdWVudGJpdF9jb25mX2ZpbGUKfQoKIyBjb25maWd1cmVfY2VydHMKY29uZmlndXJlX2NlcnRzKCkgewogICAgbWtkaXIgL2V0Yy9hcm8tcnAKICAgIGJhc2U2NCAtZCA8PDwiJEFETUlOQVBJQ0FCVU5ETEUiID4vZXRjL2Fyby1ycC9hZG1pbi1jYS1idW5kbGUucGVtCiAgICBpZiBbWyAtbiAiJEFSTUFQSUNBQlVORExFIiBdXTsgdGhlbgogICAgYmFzZTY0IC1kIDw8PCIkQVJNQVBJQ0FCVU5ETEUiID4vZXRjL2Fyby1ycC9hcm0tY2EtYnVuZGxlLnBlbQogICAgZmkKICAgIGNob3duIC1SIDEwMDA6MTAwMCAvZXRjL2Fyby1ycAoKICAgICMgc2V0dGluZyBNT05JVE9SSU5HX0dDU19BVVRIX0lEX1RZUEU9QXV0aEtleVZhdWx0IHNlZW1zIHRvIGhhdmUgY2F1c2VkIG1kc2Qgbm90CiAgICAjIHRvIGhvbm91ciBTU0xfQ0VSVF9GSUxFIGFueSBtb3JlLCBoZWF2ZW4gb25seSBrbm93cyB3aHkuCiAgICBta2RpciAtcCAvdXNyL2xpYi9zc2wvY2VydHMKICAgIGNzcGxpdCAtZiAvdXNyL2xpYi9zc2wvY2VydHMvY2VydC0gLWIgJTAzZC5wZW0gL2V0Yy9wa2kvdGxzL2NlcnRzL2NhLWJ1bmRsZS5jcnQgL14kLzEgInsqfSIgPi9kZXYvbnVsbAogICAgY19yZWhhc2ggL3Vzci9saWIvc3NsL2NlcnRzCgojIHdlIGxlYXZlIGNsaWVudElkIGJsYW5rIGFzIGxvbmcgYXMgb25seSAxIG1hbmFnZWQgaWRlbnRpdHkgYXNzaWduZWQgdG8gdm1zcwojIGlmIHdlIGhhdmUgbW9yZSB0aGFuIDEsIHdlIHdpbGwgbmVlZCB0byBwb3B1bGF0ZSB3aXRoIGNsaWVudElkIHVzZWQgZm9yIG9mZi1ub2RlIHNjYW5uaW5nCiAgICBsb2NhbCAtciBub2Rlc2Nhbl9hZ2VudF9maWxlbmFtZT0iL2V0Yy9kZWZhdWx0L3ZzYS1ub2Rlc2Nhbi1hZ2VudC5jb25maWciCiAgICBsb2NhbCAtciBub2Rlc2Nhbl9hZ2VudF9maWxlPSJ7CiAgICBcIk5pY2VcIjogMTksCiAgICBcIlRpbWVvdXRcIjogMTA4MDAsCiAgICBcIkNsaWVudElkXCI6IFwiXCIsCiAgICBcIlRlbmFudElkXCI6ICRBWlVSRVNFQ1BBQ0tWU0FURU5BTlRJRCwKICAgIFwiUXVhbHlzU3RvcmVCYXNlVXJsXCI6ICRBWlVSRVNFQ1BBQ0tRVUFMWVNVUkwsCiAgICBcIlByb2Nlc3NUaW1lb3V0XCI6IDMwMCwKICAgIFwiQ29tbWFuZERlbGF5XCI6IDAKICB9IgoKICAgIHdyaXRlX2ZpbGUgbm9kZXNjYW5fYWdlbnRfZmlsZW5hbWUgbm9kZXNjYW5fYWdlbnRfZmlsZQp9CgojIGNvbmZpZ3VyZV9zZXJ2aWNlX21kbQpjb25maWd1cmVfc2VydmljZV9tZG0oKSB7CiAgICBsb2cgImNvbmZpZ3VyaW5nIG1kbSBzZXJ2aWNlIgoKICAgIGxvY2FsIC1yIHN5c2NvbmZpZ19tZG1fZmlsZW5hbWU9Ii9ldGMvc3lzY29uZmlnL21kbSIKICAgIGxvY2FsIC1yIHN5c2NvbmZpZ19tZG1fZmlsZT0iTURNRlJPTlRFTkRVUkw9JyRNRE1GUk9OVEVORFVSTCcKTURNSU1BR0U9JyRNRE1JTUFHRScKTURNU09VUkNFRU5WSVJPTk1FTlQ9JyRMT0NBVElPTicKTURNU09VUkNFUk9MRT1ycApNRE1TT1VSQ0VST0xFSU5TVEFOQ0U9XCIkKGhvc3RuYW1lKVwiIgoKICAgIHdyaXRlX2ZpbGUgc3lzY29uZmlnX21kbV9maWxlbmFtZSBzeXNjb25maWdfbWRtX2ZpbGUKCiAgICBta2RpciAtcCAvdmFyL2V0dwogICAgbG9jYWwgLXIgbWRtX3NlcnZpY2VfZmlsZW5hbWU9Ii9ldGMvc3lzdGVtZC9zeXN0ZW0vbWRtLnNlcnZpY2UiCiAgICBsb2NhbCAtciBtZG1fc2VydmljZV9maWxlPSJbVW5pdF0KQWZ0ZXI9bmV0d29yay1vbmxpbmUudGFyZ2V0CldhbnRzPW5ldHdvcmstb25saW5lLnRhcmdldAoKW1NlcnZpY2VdCkVudmlyb25tZW50RmlsZT0vZXRjL3N5c2NvbmZpZy9tZG0KRXhlY1N0YXJ0UHJlPS0vdXNyL2Jpbi9kb2NrZXIgcm0gLWYgJU4KRXhlY1N0YXJ0PS91c3IvYmluL2RvY2tlciBydW4gXAogIC0tZW50cnlwb2ludCAvdXNyL3NiaW4vTWV0cmljc0V4dGVuc2lvbiBcCiAgLS1ob3N0bmFtZSAlSCBcCiAgLS1uYW1lICVOIFwKICAtLXJtIFwKICAtLWNhcC1kcm9wIG5ldF9yYXcgXAogIC1tIDJnIFwKICAtdiAvZXRjL21kbS5wZW06L2V0Yy9tZG0ucGVtIFwKICAtdiAvdmFyL2V0dzovdmFyL2V0dzp6IFwKICAkTURNSU1BR0UgXAogIC1DZXJ0RmlsZSAvZXRjL21kbS5wZW0gXAogIC1Gcm9udEVuZFVybCAkTURNRlJPTlRFTkRVUkwgXAogIC1Mb2dnZXIgQ29uc29sZSBcCiAgLUxvZ0xldmVsIFdhcm5pbmcgXAogIC1Qcml2YXRlS2V5RmlsZSAvZXRjL21kbS5wZW0gXAogIC1Tb3VyY2VFbnZpcm9ubWVudCAkTURNU09VUkNFRU5WSVJPTk1FTlQgXAogIC1Tb3VyY2VSb2xlICRNRE1TT1VSQ0VST0xFIFwKICAtU291cmNlUm9sZUluc3RhbmNlICRNRE1TT1VSQ0VST0xFSU5TVEFOQ0UKRXhlY1N0b3A9L3Vzci9iaW4vZG9ja2VyIHN0b3AgJU4KUmVzdGFydD1hbHdheXMKUmVzdGFydFNlYz0xClN0YXJ0TGltaXRJbnRlcnZhbD0wCgpbSW5zdGFsbF0KV2FudGVkQnk9bXVsdGktdXNlci50YXJnZXQiCgogICAgd3JpdGVfZmlsZSBtZG1fc2VydmljZV9maWxlbmFtZSBtZG1fc2VydmljZV9maWxlCn0KCiMgY29uZmlndXJlX3RpbWVyc19tZG1fbWRzZApjb25maWd1cmVfdGltZXJzX21kbV9tZHNkKCkgewogICAgZm9yIHZhciBpbiAibWRzZCIgIm1kbSI7IGRvCiAgICAgICAgbG9jYWwgZG93bmxvYWRfY3JlZHNfc2VydmljZV9maWxlbmFtZT0iL2V0Yy9zeXN0ZW1kL3N5c3RlbS9kb3dubG9hZC0kdmFyLWNyZWRlbnRpYWxzLnNlcnZpY2UiCiAgICAgICAgbG9jYWwgZG93bmxvYWRfY3JlZHNfc2VydmljZV9maWxlPSJbVW5pdF0KRGVzY3JpcHRpb249UGVyaW9kaWMgJHZhciBjcmVkZW50aWFscyByZWZyZXNoCgpbU2VydmljZV0KVHlwZT1vbmVzaG90CkV4ZWNTdGFydD0vdXNyL2xvY2FsL2Jpbi9kb3dubG9hZC1jcmVkZW50aWFscy5zaCAkdmFyIgoKICAgICAgICB3cml0ZV9maWxlIGRvd25sb2FkX2NyZWRzX3NlcnZpY2VfZmlsZW5hbWUgZG93bmxvYWRfY3JlZHNfc2VydmljZV9maWxlCgogICAgICAgIGxvY2FsIGRvd25sb2FkX2NyZWRzX3RpbWVyX2ZpbGVuYW1lPSIvZXRjL3N5c3RlbWQvc3lzdGVtL2Rvd25sb2FkLSR2YXItY3JlZGVudGlhbHMudGltZXIiCiAgICAgICAgbG9jYWwgZG93bmxvYWRfY3JlZHNfdGltZXJfZmlsZT0iW1VuaXRdCkRlc2NyaXB0aW9uPVBlcmlvZGljICR2YXIgY3JlZGVudGlhbHMgcmVmcmVzaApBZnRlcj1uZXR3b3JrLW9ubGluZS50YXJnZXQKV2FudHM9bmV0d29yay1vbmxpbmUudGFyZ2V0CgpbVGltZXJdCk9uQm9vdFNlYz0wbWluCk9uQ2FsZW5kYXI9MC8xMjowMDowMApBY2N1cmFjeVNlYz01cwoKW0luc3RhbGxdCldhbnRlZEJ5PXRpbWVycy50YXJnZXQiCgogICAgICAgIHdyaXRlX2ZpbGUgZG93bmxvYWRfY3JlZHNfdGltZXJfZmlsZW5hbWUgZG93bmxvYWRfY3JlZHNfdGltZXJfZmlsZQogICAgZG9uZQoKICAgIGxvY2FsIC1yIGRvd25sb2FkX2NyZWRzX3NjcmlwdF9maWxlbmFtZT0iL3Vzci9sb2NhbC9iaW4vZG93bmxvYWQtY3JlZGVudGlhbHMuc2giCiAgICBsb2NhbCAtciBkb3dubG9hZF9jcmVkc19zY3JpcHRfZmlsZT0iIyEvYmluL2Jhc2gKc2V0IC1ldQoKQ09NUE9ORU5UPVwkMQplY2hvIFwiRG93bmxvYWQgXCRDT01QT05FTlQgY3JlZGVudGlhbHNcIgoKVEVNUF9ESVI9XCJcJChta3RlbXAgLWQpXCIKZXhwb3J0IEFaVVJFX0NPTkZJR19ESVI9XCJcJChta3RlbXAgLWQpXCIKCmVjaG8gXCJMb2dnaW5nIGludG8gQXp1cmUuLi5cIgpSRVRSSUVTPTMKd2hpbGUgW1sgXCRSRVRSSUVTIC1ndCAwIF1dOyBkbwogICAgaWYgYXogbG9naW4gLWkgLS1hbGxvdy1uby1zdWJzY3JpcHRpb25zCiAgICB0aGVuCiAgICAgICAgZWNobyBcImF6IGxvZ2luIHN1Y2Nlc3NmdWxcIgogICAgICAgIGJyZWFrCiAgICBlbHNlCiAgICAgICAgZWNobyBcImF6IGxvZ2luIGZhaWxlZC4gUmV0cnlpbmcuLi5cIgogICAgICAgIGxldCBSRVRSSUVTLT0xCiAgICAgICAgc2xlZXAgNQogICAgZmkKZG9uZQoKdHJhcCBcImNsZWFudXBcIiBFWElUCgpjbGVhbnVwKCkgewogIGF6IGxvZ291dAogIFtbIFwkVEVNUF9ESVIgPX4gL3RtcC8uKyBdXSAmJiBybSAtcmYgXCRURU1QX0RJUgogIFtbIFwkQVpVUkVfQ09ORklHX0RJUiA9fiAvdG1wLy4rIF1dICYmIHJtIC1yZiBcJEFaVVJFX0NPTkZJR19ESVIKfQoKaWYgW1sgXCRDT01QT05FTlQgPSBcIm1kbVwiIF1dOyB0aGVuCiAgQ1VSUkVOVF9DRVJUX0ZJTEU9XCIvZXRjL21kbS5wZW1cIgplbGlmIFtbIFwkQ09NUE9ORU5UXCA9IFwibWRzZFwiIF1dOyB0aGVuCiAgQ1VSUkVOVF9DRVJUX0ZJTEU9XCIvdmFyL2xpYi93YWFnZW50L01pY3Jvc29mdC5BenVyZS5LZXlWYXVsdC5TdG9yZS9tZHNkLnBlbVwiCmVsc2UKICBlY2hvIEludmFsaWQgdXNhZ2UgJiYgZXhpdCAxCmZpCgpTRUNSRVRfTkFNRT1cInJwLVwke0NPTVBPTkVOVH1cIgpORVdfQ0VSVF9GSUxFPVwiXCRURU1QX0RJUi9cJENPTVBPTkVOVC5wZW1cIgpmb3IgYXR0ZW1wdCBpbiB7MS4uNX07IGRvCiAgYXoga2V5dmF1bHQgXAogICAgc2VjcmV0IFwKICAgIGRvd25sb2FkIFwKICAgIC0tZmlsZSBcIlwkTkVXX0NFUlRfRklMRVwiIFwKICAgIC0taWQgXCJodHRwczovLyRLRVlWQVVMVFBSRUZJWC1zdmMuJEtFWVZBVUxURE5TU1VGRklYL3NlY3JldHMvXCRTRUNSRVRfTkFNRVwiIFwKICAgICYmIGJyZWFrCiAgaWYgW1sgXCRhdHRlbXB0IC1sdCA1IF1dOyB0aGVuIHNsZWVwIDEwOyBlbHNlIGV4aXQgMTsgZmkKZG9uZQoKaWYgWyAtZiBcJE5FV19DRVJUX0ZJTEUgXTsgdGhlbgogIGlmIFtbIFwkQ09NUE9ORU5UID0gXCJtZHNkXCIgXV07IHRoZW4KICAgIGNob3duIHN5c2xvZzpzeXNsb2cgXCRORVdfQ0VSVF9GSUxFCiAgZWxzZQogICAgc2VkIC1pIC1uZSAnMSwvRU5EIENFUlRJRklDQVRFLyBwJyBcJE5FV19DRVJUX0ZJTEUKICBmaQoKICBuZXdfY2VydF9zbj1cIlwkKG9wZW5zc2wgeDUwOSAtaW4gXCJcJE5FV19DRVJUX0ZJTEVcIiAtbm9vdXQgLXNlcmlhbCB8IGF3ayAtRj0gJ3twcmludCBcJDJ9JylcIgogIGN1cnJlbnRfY2VydF9zbj1cIlwkKG9wZW5zc2wgeDUwOSAtaW4gXCJcJENVUlJFTlRfQ0VSVF9GSUxFXCIgLW5vb3V0IC1zZXJpYWwgfCBhd2sgLUY9ICd7cHJpbnQgXCQyfScpXCIKICBpZiBbWyAhIC16IFwkbmV3X2NlcnRfc24gXV0gJiYgW1sgXCRuZXdfY2VydF9zbiAhPSBcIlwkY3VycmVudF9jZXJ0X3NuXCIgXV07IHRoZW4KICAgIGVjaG8gdXBkYXRpbmcgY2VydGlmaWNhdGUgZm9yIFwkQ09NUE9ORU5UCiAgICBjaG1vZCAwNjAwIFwkTkVXX0NFUlRfRklMRQogICAgbXYgXCRORVdfQ0VSVF9GSUxFIFwkQ1VSUkVOVF9DRVJUX0ZJTEUKICBmaQplbHNlCiAgZWNobyBGYWlsZWQgdG8gcmVmcmVzaCBjZXJ0aWZpY2F0ZSBmb3IgXCRDT01QT05FTlQgJiYgZXhpdCAxCmZpIgoKICAgIHdyaXRlX2ZpbGUgZG93bmxvYWRfY3JlZHNfc2NyaXB0X2ZpbGVuYW1lIGRvd25sb2FkX2NyZWRzX3NjcmlwdF9maWxlCgogICAgY2htb2QgdSt4IC91c3IvbG9jYWwvYmluL2Rvd25sb2FkLWNyZWRlbnRpYWxzLnNoCgogICAgc3lzdGVtY3RsIGVuYWJsZSBkb3dubG9hZC1tZHNkLWNyZWRlbnRpYWxzLnRpbWVyCiAgICBzeXN0ZW1jdGwgZW5hYmxlIGRvd25sb2FkLW1kbS1jcmVkZW50aWFscy50aW1lcgoKICAgIC91c3IvbG9jYWwvYmluL2Rvd25sb2FkLWNyZWRlbnRpYWxzLnNoIG1kc2QKICAgIC91c3IvbG9jYWwvYmluL2Rvd25sb2FkLWNyZWRlbnRpYWxzLnNoIG1kbQoKICAgIGxvY2FsIC1yIE1EU0RDRVJUSUZJQ0FURVNBTj0iJChvcGVuc3NsIHg1MDkgLWluIC92YXIvbGliL3dhYWdlbnQvTWljcm9zb2Z0LkF6dXJlLktleVZhdWx0LlN0b3JlL21kc2QucGVtIC1ub291dCAtc3ViamVjdCB8IHNlZCAtZSAncy8uKkNOID0gLy8nKSIKICAgIGxvY2FsIC1yIHdhdGNoX21kbV9jcmVkc19zZXJ2aWNlX2ZpbGVuYW1lPSIvZXRjL3N5c3RlbWQvc3lzdGVtL3dhdGNoLW1kbS1jcmVkZW50aWFscy5zZXJ2aWNlIgogICAgbG9jYWwgLXIgd2F0Y2hfbWRtX2NyZWRzX3NlcnZpY2VfZmlsZT0iW1VuaXRdCkRlc2NyaXB0aW9uPVdhdGNoIGZvciBjaGFuZ2VzIGluIG1kbS5wZW0gYW5kIHJlc3RhcnRzIHRoZSBtZG0gc2VydmljZQoKW1NlcnZpY2VdClR5cGU9b25lc2hvdApFeGVjU3RhcnQ9L3Vzci9iaW4vc3lzdGVtY3RsIHJlc3RhcnQgbWRtLnNlcnZpY2UKCltJbnN0YWxsXQpXYW50ZWRCeT1tdWx0aS11c2VyLnRhcmdldCIKCiAgICB3cml0ZV9maWxlIHdhdGNoX21kbV9jcmVkc19zZXJ2aWNlX2ZpbGVuYW1lIHdhdGNoX21kbV9jcmVkc19zZXJ2aWNlX2ZpbGUKCiAgICBsb2NhbCAtciB3YXRjaF9tZG1fY3JlZHNfcGF0aF9maWxlbmFtZT0nL2V0Yy9zeXN0ZW1kL3N5c3RlbS93YXRjaC1tZG0tY3JlZGVudGlhbHMucGF0aCcKICAgIGxvY2FsIC1yIHdhdGNoX21kbV9jcmVkc19wYXRoX2ZpbGU9J1tQYXRoXQpQYXRoTW9kaWZpZWQ9L2V0Yy9tZG0ucGVtCgpbSW5zdGFsbF0KV2FudGVkQnk9bXVsdGktdXNlci50YXJnZXQnCgogICAgd3JpdGVfZmlsZSB3YXRjaF9tZG1fY3JlZHNfcGF0aF9maWxlbmFtZSB3YXRjaF9tZG1fY3JlZHNfcGF0aF9maWxlCgogICAgbG9jYWwgLXIgd2F0Y2hfbWRtX2NyZWRzPSd3YXRjaC1tZG0tY3JlZGVudGlhbHMucGF0aCcKICAgIHN5c3RlbWN0bCBlbmFibGUgIiR3YXRjaF9tZG1fY3JlZHMiIHx8IGFib3J0ICJmYWlsZWQgdG8gZW5hYmxlICR3YXRjaF9tZG1fY3JlZHMiCiAgICBzeXN0ZW1jdGwgc3RhcnQgIiR3YXRjaF9tZG1fY3JlZHMiIHx8IGFib3J0ICJmYWlsZWQgdG8gc3RhcnQgJHdhdGNoX21kbV9jcmVkcyIKfQoKIyBjb25maWd1cmVfc2VydmljZV9hcm9fcnAKY29uZmlndXJlX3NlcnZpY2VfYXJvX3JwKCkgewogICAgbG9jYWwgLXIgYXJvX3JwX2NvbmZfZmlsZW5hbWU9Jy9ldGMvc3lzY29uZmlnL2Fyby1ycCcKICAgIGxvY2FsIC1yIGFyb19ycF9jb25mX2ZpbGU9IkFDUl9SRVNPVVJDRV9JRD0nJEFDUlJFU09VUkNFSUQnCkFETUlOX0FQSV9DTElFTlRfQ0VSVF9DT01NT05fTkFNRT0nJEFETUlOQVBJQ0xJRU5UQ0VSVENPTU1PTk5BTUUnCkFSTV9BUElfQ0xJRU5UX0NFUlRfQ09NTU9OX05BTUU9JyRBUk1BUElDTElFTlRDRVJUQ09NTU9OTkFNRScKQVpVUkVfQVJNX0NMSUVOVF9JRD0nJEFSTUNMSUVOVElEJwpBWlVSRV9GUF9DTElFTlRfSUQ9JyRGUENMSUVOVElEJwpBWlVSRV9GUF9TRVJWSUNFX1BSSU5DSVBBTF9JRD0nJEZQU0VSVklDRVBSSU5DSVBBTElEJwpCSUxMSU5HX0UyRV9TVE9SQUdFX0FDQ09VTlRfSUQ9JyRCSUxMSU5HRTJFU1RPUkFHRUFDQ09VTlRJRCcKQ0xVU1RFUl9NRE1fQUNDT1VOVD0nJENMVVNURVJNRE1BQ0NPVU5UJwpDTFVTVEVSX01ETV9OQU1FU1BBQ0U9UlAKQ0xVU1RFUl9NRFNEX0FDQ09VTlQ9JyRDTFVTVEVSTURTREFDQ09VTlQnCkNMVVNURVJfTURTRF9DT05GSUdfVkVSU0lPTj0nJENMVVNURVJNRFNEQ09ORklHVkVSU0lPTicKQ0xVU1RFUl9NRFNEX05BTUVTUEFDRT0nJENMVVNURVJNRFNETkFNRVNQQUNFJwpEQVRBQkFTRV9BQ0NPVU5UX05BTUU9JyREQVRBQkFTRUFDQ09VTlROQU1FJwpET01BSU5fTkFNRT0nJExPQ0FUSU9OLiRDTFVTVEVSUEFSRU5URE9NQUlOTkFNRScKR0FURVdBWV9ET01BSU5TPSckR0FURVdBWURPTUFJTlMnCkdBVEVXQVlfUkVTT1VSQ0VHUk9VUD0nJEdBVEVXQVlSRVNPVVJDRUdST1VQTkFNRScKS0VZVkFVTFRfUFJFRklYPSckS0VZVkFVTFRQUkVGSVgnCk1ETV9BQ0NPVU5UPSckUlBNRE1BQ0NPVU5UJwpNRE1fTkFNRVNQQUNFPVJQCk1EU0RfRU5WSVJPTk1FTlQ9JyRNRFNERU5WSVJPTk1FTlQnClJQX0ZFQVRVUkVTPSckUlBGRUFUVVJFUycKUlBJTUFHRT0nJFJQSU1BR0UnCkFST19JTlNUQUxMX1ZJQV9ISVZFPSckQ0xVU1RFUlNJTlNUQUxMVklBSElWRScKQVJPX0hJVkVfREVGQVVMVF9JTlNUQUxMRVJfUFVMTFNQRUM9JyRDTFVTVEVSREVGQVVMVElOU1RBTExFUlBVTExTUEVDJwpBUk9fQURPUFRfQllfSElWRT0nJENMVVNURVJTQURPUFRCWUhJVkUnClVTRV9DSEVDS0FDQ0VTUz0nJFVTRUNIRUNLQUNDRVNTJyIKCiAgICB3cml0ZV9maWxlIGFyb19ycF9jb25mX2ZpbGVuYW1lIGFyb19ycF9jb25mX2ZpbGUKCiAgICBsb2NhbCAtciBhcm9fcnBfc2VydmljZV9maWxlbmFtZT0nL2V0Yy9zeXN0ZW1kL3N5c3RlbS9hcm8tcnAuc2VydmljZScKICAgIGxvY2FsIC1yIGFyb19ycF9zZXJ2aWNlX2ZpbGU9IltVbml0XQpBZnRlcj1uZXR3b3JrLW9ubGluZS50YXJnZXQKV2FudHM9bmV0d29yay1vbmxpbmUudGFyZ2V0CgpbU2VydmljZV0KRW52aXJvbm1lbnRGaWxlPS9ldGMvc3lzY29uZmlnL2Fyby1ycApFeGVjU3RhcnRQcmU9LS91c3IvYmluL2RvY2tlciBybSAtZiAlTgpFeGVjU3RhcnQ9L3Vzci9iaW4vZG9ja2VyIHJ1biBcCiAgLS1ob3N0bmFtZSAlSCBcCiAgLS1uYW1lICVOIFwKICAtLXJtIFwKICAtLWNhcC1kcm9wIG5ldF9yYXcgXAogIC1lIEFDUl9SRVNPVVJDRV9JRCBcCiAgLWUgQURNSU5fQVBJX0NMSUVOVF9DRVJUX0NPTU1PTl9OQU1FIFwKICAtZSBBUk1fQVBJX0NMSUVOVF9DRVJUX0NPTU1PTl9OQU1FIFwKICAtZSBBWlVSRV9BUk1fQ0xJRU5UX0lEIFwKICAtZSBBWlVSRV9GUF9DTElFTlRfSUQgXAogIC1lIEJJTExJTkdfRTJFX1NUT1JBR0VfQUNDT1VOVF9JRCBcCiAgLWUgQ0xVU1RFUl9NRE1fQUNDT1VOVCBcCiAgLWUgQ0xVU1RFUl9NRE1fTkFNRVNQQUNFIFwKICAtZSBDTFVTVEVSX01EU0RfQUNDT1VOVCBcCiAgLWUgQ0xVU1RFUl9NRFNEX0NPTkZJR19WRVJTSU9OIFwKICAtZSBDTFVTVEVSX01EU0RfTkFNRVNQQUNFIFwKICAtZSBEQVRBQkFTRV9BQ0NPVU5UX05BTUUgXAogIC1lIERPTUFJTl9OQU1FIFwKICAtZSBHQVRFV0FZX0RPTUFJTlMgXAogIC1lIEdBVEVXQVlfUkVTT1VSQ0VHUk9VUCBcCiAgLWUgS0VZVkFVTFRfUFJFRklYIFwKICAtZSBNRE1fQUNDT1VOVCBcCiAgLWUgTURNX05BTUVTUEFDRSBcCiAgLWUgTURTRF9FTlZJUk9OTUVOVCBcCiAgLWUgUlBfRkVBVFVSRVMgXAogIC1lIEFST19JTlNUQUxMX1ZJQV9ISVZFIFwKICAtZSBBUk9fSElWRV9ERUZBVUxUX0lOU1RBTExFUl9QVUxMU1BFQyBcCiAgLWUgQVJPX0FET1BUX0JZX0hJVkUgXAogIC1lIFVTRV9DSEVDS0FDQ0VTUyBcCiAgLW0gMmcgXAogIC1wIDQ0Mzo4NDQzIFwKICAtdiAvZXRjL2Fyby1ycDovZXRjL2Fyby1ycCBcCiAgLXYgL3J1bi9zeXN0ZW1kL2pvdXJuYWw6L3J1bi9zeXN0ZW1kL2pvdXJuYWwgXAogIC12IC92YXIvZXR3Oi92YXIvZXR3OnogXAogICRSUElNQUdFIFwKICBycApFeGVjU3RvcD0vdXNyL2Jpbi9kb2NrZXIgc3RvcCAtdCAzNjAwICVOClRpbWVvdXRTdG9wU2VjPTM2MDAKUmVzdGFydD1hbHdheXMKUmVzdGFydFNlYz0xClN0YXJ0TGltaXRJbnRlcnZhbD0wCgpbSW5zdGFsbF0KV2FudGVkQnk9bXVsdGktdXNlci50YXJnZXQiCgogICAgd3JpdGVfZmlsZSBhcm9fcnBfc2VydmljZV9maWxlbmFtZSBhcm9fcnBfY29uZl9maWxlCn0KCiMgY29uZmlndXJlX3NlcnZpY2VfYXJvX2RidG9rZW4KY29uZmlndXJlX3NlcnZpY2VfYXJvX2RidG9rZW4oKSB7CiAgICBsb2NhbCAtciBhcm9fZGJ0b2tlbl9zZXJ2aWNlX2NvbmZfZmlsZW5hbWU9Jy9ldGMvc3lzY29uZmlnL2Fyby1kYnRva2VuJwogICAgbG9jYWwgLXIgYXJvX2RidG9rZW5fc2VydmljZV9jb25mX2ZpbGU9IkRBVEFCQVNFX0FDQ09VTlRfTkFNRT0nJERBVEFCQVNFQUNDT1VOVE5BTUUnCkFaVVJFX0RCVE9LRU5fQ0xJRU5UX0lEPSckREJUT0tFTkNMSUVOVElEJwpBWlVSRV9HQVRFV0FZX1NFUlZJQ0VfUFJJTkNJUEFMX0lEPSckR0FURVdBWVNFUlZJQ0VQUklOQ0lQQUxJRCcKS0VZVkFVTFRfUFJFRklYPSckS0VZVkFVTFRQUkVGSVgnCk1ETV9BQ0NPVU5UPSckUlBNRE1BQ0NPVU5UJwpNRE1fTkFNRVNQQUNFPURCVG9rZW4KUlBJTUFHRT0nJFJQSU1BR0UnIgoKICAgIHdyaXRlX2ZpbGUgYXJvX2RidG9rZW5fc2VydmljZV9jb25mX2ZpbGVuYW1lIGFyb19kYnRva2VuX3NlcnZpY2VfY29uZl9maWxlCgogICAgbG9jYWwgLXIgYXJvX2RidG9rZW5fc2VydmljZV9maWxlbmFtZT0nL2V0Yy9zeXN0ZW1kL3N5c3RlbS9hcm8tZGJ0b2tlbi5zZXJ2aWNlJwogICAgbG9jYWwgLXIgYXJvX2RidG9rZW5fc2VydmljZV9maWxlPSJbVW5pdF0KQWZ0ZXI9bmV0d29yay1vbmxpbmUudGFyZ2V0CldhbnRzPW5ldHdvcmstb25saW5lLnRhcmdldAoKW1NlcnZpY2VdCkVudmlyb25tZW50RmlsZT0vZXRjL3N5c2NvbmZpZy9hcm8tZGJ0b2tlbgpFeGVjU3RhcnRQcmU9LS91c3IvYmluL2RvY2tlciBybSAtZiAlTgpFeGVjU3RhcnQ9L3Vzci9iaW4vZG9ja2VyIHJ1biBcCiAgLS1ob3N0bmFtZSAlSCBcCiAgLS1uYW1lICVOIFwKICAtLXJtIFwKICAtLWNhcC1kcm9wIG5ldF9yYXcgXAogIC1lIEFaVVJFX0dBVEVXQVlfU0VSVklDRV9QUklOQ0lQQUxfSUQgXAogIC1lIERBVEFCQVNFX0FDQ09VTlRfTkFNRSBcCiAgLWUgQVpVUkVfREJUT0tFTl9DTElFTlRfSUQgXAogIC1lIEtFWVZBVUxUX1BSRUZJWCBcCiAgLWUgTURNX0FDQ09VTlQgXAogIC1lIE1ETV9OQU1FU1BBQ0UgXAogIC1tIDJnIFwKICAtcCA0NDU6ODQ0NSBcCiAgLXYgL3J1bi9zeXN0ZW1kL2pvdXJuYWw6L3J1bi9zeXN0ZW1kL2pvdXJuYWwgXAogIC12IC92YXIvZXR3Oi92YXIvZXR3OnogXAogICRSUElNQUdFIFwKICBkYnRva2VuCkV4ZWNTdG9wPS91c3IvYmluL2RvY2tlciBzdG9wIC10IDM2MDAgJU4KVGltZW91dFN0b3BTZWM9MzYwMApSZXN0YXJ0PWFsd2F5cwpSZXN0YXJ0U2VjPTEKU3RhcnRMaW1pdEludGVydmFsPTAKCltJbnN0YWxsXQpXYW50ZWRCeT1tdWx0aS11c2VyLnRhcmdldCIKCiAgICB3cml0ZV9maWxlIGFyb19kYnRva2VuX3NlcnZpY2VfZmlsZW5hbWUgYXJvX2RidG9rZW5fc2VydmljZV9maWxlCn0KCiMgY29uZmlndXJlX3NlcnZpY2VfYXJvX21vbml0b3IKY29uZmlndXJlX3NlcnZpY2VfYXJvX21vbml0b3IoKSB7CiAgICBsb2cgImNvbmZpZ3VyaW5nIGFyby1tb25pdG9yIHNlcnZpY2UiCiAgICAjIERPTUFJTl9OQU1FLCBDTFVTVEVSX01EU0RfQUNDT1VOVCwgQ0xVU1RFUl9NRFNEX0NPTkZJR19WRVJTSU9OLCBHQVRFV0FZX0RPTUFJTlMsIEdBVEVXQVlfUkVTT1VSQ0VHUk9VUCwgTURTRF9FTlZJUk9OTUVOVCBDTFVTVEVSX01EU0RfTkFNRVNQQUNFCiAgICAjIGFyZSBub3QgdXNlZCwgYnV0IGNhbid0IGVhc2lseSBiZSByZWZhY3RvcmVkIG91dC4gU2hvdWxkIGJlIHJldmlzaXRlZCBpbiB0aGUgZnV0dXJlLgogICAgbG9jYWwgLXIgYXJvX21vbml0b3Jfc2VydmljZV9jb25mX2ZpbGVuYW1lPScvZXRjL3N5c2NvbmZpZy9hcm8tbW9uaXRvcicKICAgIGxvY2FsIC1yIGFyb19tb25pdG9yX3NlcnZpY2VfY29uZl9maWxlPSJBWlVSRV9GUF9DTElFTlRfSUQ9JyRGUENMSUVOVElEJwpET01BSU5fTkFNRT0nJExPQ0FUSU9OLiRDTFVTVEVSUEFSRU5URE9NQUlOTkFNRScKQ0xVU1RFUl9NRFNEX0FDQ09VTlQ9JyRDTFVTVEVSTURTREFDQ09VTlQnCkNMVVNURVJfTURTRF9DT05GSUdfVkVSU0lPTj0nJENMVVNURVJNRFNEQ09ORklHVkVSU0lPTicKR0FURVdBWV9ET01BSU5TPSckR0FURVdBWURPTUFJTlMnCkdBVEVXQVlfUkVTT1VSQ0VHUk9VUD0nJEdBVEVXQVlSRVNPVVJDRUdST1VQTkFNRScKTURTRF9FTlZJUk9OTUVOVD0nJE1EU0RFTlZJUk9OTUVOVCcKQ0xVU1RFUl9NRFNEX05BTUVTUEFDRT0nJENMVVNURVJNRFNETkFNRVNQQUNFJwpDTFVTVEVSX01ETV9BQ0NPVU5UPSckQ0xVU1RFUk1ETUFDQ09VTlQnCkNMVVNURVJfTURNX05BTUVTUEFDRT1CQk0KREFUQUJBU0VfQUNDT1VOVF9OQU1FPSckREFUQUJBU0VBQ0NPVU5UTkFNRScKS0VZVkFVTFRfUFJFRklYPSckS0VZVkFVTFRQUkVGSVgnCk1ETV9BQ0NPVU5UPSckUlBNRE1BQ0NPVU5UJwpNRE1fTkFNRVNQQUNFPUJCTQpSUElNQUdFPSckUlBJTUFHRSciCgogICAgd3JpdGVfZmlsZSBhcm9fbW9uaXRvcl9zZXJ2aWNlX2NvbmZfZmlsZW5hbWUgYXJvX21vbml0b3Jfc2VydmljZV9jb25mX2ZpbGUKCiAgICBsb2NhbCAtciBhcm9fbW9uaXRvcl9zZXJ2aWNlX2ZpbGVuYW1lPScvZXRjL3N5c3RlbWQvc3lzdGVtL2Fyby1tb25pdG9yLnNlcnZpY2UnCiAgICBsb2NhbCAtciBhcm9fbW9uaXRvcl9zZXJ2aWNlX2ZpbGU9IltVbml0XQpBZnRlcj1uZXR3b3JrLW9ubGluZS50YXJnZXQKV2FudHM9bmV0d29yay1vbmxpbmUudGFyZ2V0CgpbU2VydmljZV0KRW52aXJvbm1lbnRGaWxlPS9ldGMvc3lzY29uZmlnL2Fyby1tb25pdG9yCkV4ZWNTdGFydFByZT0tL3Vzci9iaW4vZG9ja2VyIHJtIC1mICVOCkV4ZWNTdGFydD0vdXNyL2Jpbi9kb2NrZXIgcnVuIFwKICAtLWhvc3RuYW1lICVIIFwKICAtLW5hbWUgJU4gXAogIC0tcm0gXAogIC0tY2FwLWRyb3AgbmV0X3JhdyBcCiAgLWUgQVpVUkVfRlBfQ0xJRU5UX0lEIFwKICAtZSBET01BSU5fTkFNRSBcCiAgLWUgQ0xVU1RFUl9NRFNEX0FDQ09VTlQgXAogIC1lIENMVVNURVJfTURTRF9DT05GSUdfVkVSU0lPTiBcCiAgLWUgR0FURVdBWV9ET01BSU5TIFwKICAtZSBHQVRFV0FZX1JFU09VUkNFR1JPVVAgXAogIC1lIE1EU0RfRU5WSVJPTk1FTlQgXAogIC1lIENMVVNURVJfTURTRF9OQU1FU1BBQ0UgXAogIC1lIENMVVNURVJfTURNX0FDQ09VTlQgXAogIC1lIENMVVNURVJfTURNX05BTUVTUEFDRSBcCiAgLWUgREFUQUJBU0VfQUNDT1VOVF9OQU1FIFwKICAtZSBLRVlWQVVMVF9QUkVGSVggXAogIC1lIE1ETV9BQ0NPVU5UIFwKICAtZSBNRE1fTkFNRVNQQUNFIFwKICAtbSAyLjVnIFwKICAtdiAvcnVuL3N5c3RlbWQvam91cm5hbDovcnVuL3N5c3RlbWQvam91cm5hbCBcCiAgLXYgL3Zhci9ldHc6L3Zhci9ldHc6eiBcCiAgJFJQSU1BR0UgXAogIG1vbml0b3IKUmVzdGFydD1hbHdheXMKUmVzdGFydFNlYz0xClN0YXJ0TGltaXRJbnRlcnZhbD0wCgpbSW5zdGFsbF0KV2FudGVkQnk9bXVsdGktdXNlci50YXJnZXQiCgogICAgd3JpdGVfZmlsZSBhcm9fbW9uaXRvcl9zZXJ2aWNlX2ZpbGVuYW1lIGFyb19tb25pdG9yX3NlcnZpY2VfZmlsZQp9CgojIGNvbmZpZ3VyZV9zZXJ2aWNlX2Fyb19wb3J0YWwKY29uZmlndXJlX3NlcnZpY2VfYXJvX3BvcnRhbCgpIHsKICAgIGxvY2FsIC1yIGFyb19wb3J0YWxfc2VydmljZV9jb25mX2ZpbGVuYW1lPScvZXRjL3N5c2NvbmZpZy9hcm8tcG9ydGFsJwogICAgbG9jYWwgLXIgYXJvX3BvcnRhbF9zZXJ2aWNlX2NvbmZfZmlsZT0iQVpVUkVfUE9SVEFMX0FDQ0VTU19HUk9VUF9JRFM9JyRQT1JUQUxBQ0NFU1NHUk9VUElEUycKQVpVUkVfUE9SVEFMX0NMSUVOVF9JRD0nJFBPUlRBTENMSUVOVElEJwpBWlVSRV9QT1JUQUxfRUxFVkFURURfR1JPVVBfSURTPSckUE9SVEFMRUxFVkFURURHUk9VUElEUycKREFUQUJBU0VfQUNDT1VOVF9OQU1FPSckREFUQUJBU0VBQ0NPVU5UTkFNRScKS0VZVkFVTFRfUFJFRklYPSckS0VZVkFVTFRQUkVGSVgnCk1ETV9BQ0NPVU5UPSckUlBNRE1BQ0NPVU5UJwpNRE1fTkFNRVNQQUNFPVBvcnRhbApQT1JUQUxfSE9TVE5BTUU9JyRMT0NBVElPTi5hZG1pbi4kUlBQQVJFTlRET01BSU5OQU1FJwpSUElNQUdFPSckUlBJTUFHRSciCgogICAgd3JpdGVfZmlsZSBhcm9fcG9ydGFsX3NlcnZpY2VfY29uZl9maWxlbmFtZSBhcm9fcG9ydGFsX3NlcnZpY2VfY29uZl9maWxlCgogICAgbG9jYWwgLXIgYXJvX3BvcnRhbF9zZXJ2aWNlX2ZpbGVuYW1lPScvZXRjL3N5c3RlbWQvc3lzdGVtL2Fyby1wb3J0YWwuc2VydmljZScKICAgIGxvY2FsIC1yIGFyb19wb3J0YWxfc2VydmljZV9maWxlPSJbVW5pdF0KQWZ0ZXI9bmV0d29yay1vbmxpbmUudGFyZ2V0CldhbnRzPW5ldHdvcmstb25saW5lLnRhcmdldApTdGFydExpbWl0SW50ZXJ2YWw9MAoKW1NlcnZpY2VdCkVudmlyb25tZW50RmlsZT0vZXRjL3N5c2NvbmZpZy9hcm8tcG9ydGFsCkV4ZWNTdGFydFByZT0tL3Vzci9iaW4vZG9ja2VyIHJtIC1mICVOCkV4ZWNTdGFydD0vdXNyL2Jpbi9kb2NrZXIgcnVuIFwKICAtLWhvc3RuYW1lICVIIFwKICAtLW5hbWUgJU4gXAogIC0tcm0gXAogIC0tY2FwLWRyb3AgbmV0X3JhdyBcCiAgLWUgQVpVUkVfUE9SVEFMX0FDQ0VTU19HUk9VUF9JRFMgXAogIC1lIEFaVVJFX1BPUlRBTF9DTElFTlRfSUQgXAogIC1lIEFaVVJFX1BPUlRBTF9FTEVWQVRFRF9HUk9VUF9JRFMgXAogIC1lIERBVEFCQVNFX0FDQ09VTlRfTkFNRSBcCiAgLWUgS0VZVkFVTFRfUFJFRklYIFwKICAtZSBNRE1fQUNDT1VOVCBcCiAgLWUgTURNX05BTUVTUEFDRSBcCiAgLWUgUE9SVEFMX0hPU1ROQU1FIFwKICAtbSAyZyBcCiAgLXAgNDQ0Ojg0NDQgXAogIC1wIDIyMjI6MjIyMiBcCiAgLXYgL3J1bi9zeXN0ZW1kL2pvdXJuYWw6L3J1bi9zeXN0ZW1kL2pvdXJuYWwgXAogIC12IC92YXIvZXR3Oi92YXIvZXR3OnogXAogICRSUElNQUdFIFwKICBwb3J0YWwKUmVzdGFydD1hbHdheXMKUmVzdGFydFNlYz0xCgpbSW5zdGFsbF0KV2FudGVkQnk9bXVsdGktdXNlci50YXJnZXQiCgogICAgd3JpdGVfZmlsZSBhcm9fcG9ydGFsX3NlcnZpY2VfY29uZl9maWxlbmFtZSBhcm9fcG9ydGFsX3NlcnZpY2VfY29uZl9maWxlCn0KCiMgY29uZmlndXJlX3NlcnZpY2VfbWRzZApjb25maWd1cmVfc2VydmljZV9tZHNkKCkgewogICAgbG9jYWwgLXIgbWRzZF9zZXJ2aWNlX2Rpcj0iL2V0Yy9zeXN0ZW1kL3N5c3RlbS9tZHNkLnNlcnZpY2UuZCIKICAgIG1rZGlyICIkbWRzZF9zZXJ2aWNlX2RpciIKCiAgICBsb2NhbCAtciBtZHNkX292ZXJyaWRlX2NvbmZfZmlsZW5hbWU9IiRtZHNkX3NlcnZpY2VfZGlyL292ZXJyaWRlLmNvbmYiCiAgICBsb2NhbCAtciBtZHNkX292ZXJyaWRlX2NvbmZfZmlsZT0iW1VuaXRdCkFmdGVyPW5ldHdvcmstb25saW5lLnRhcmdldCIKCiAgICB3cml0ZV9maWxlIG1kc2Rfb3ZlcnJpZGVfY29uZl9maWxlbmFtZSBtZHNkX292ZXJyaWRlX2NvbmZfZmlsZQoKICAgIGxvY2FsIC1yIGRlZmF1bHRfbWRzZF9maWxlbmFtZT0iL2V0Yy9kZWZhdWx0L21kc2QiCiAgICBsb2NhbCAtciBkZWZhdWx0X21kc2RfZmlsZT0iTURTRF9ST0xFX1BSRUZJWD0vdmFyL3J1bi9tZHNkL2RlZmF1bHQKTURTRF9PUFRJT05TPVwiLUEgLWQgLXIgXCRNRFNEX1JPTEVfUFJFRklYXCIKCmV4cG9ydCBNT05JVE9SSU5HX0dDU19FTlZJUk9OTUVOVD0nJE1EU0RFTlZJUk9OTUVOVCcKZXhwb3J0IE1PTklUT1JJTkdfR0NTX0FDQ09VTlQ9JyRSUE1EU0RBQ0NPVU5UJwpleHBvcnQgTU9OSVRPUklOR19HQ1NfUkVHSU9OPSckTE9DQVRJT04nCmV4cG9ydCBNT05JVE9SSU5HX0dDU19BVVRIX0lEX1RZUEU9QXV0aEtleVZhdWx0CmV4cG9ydCBNT05JVE9SSU5HX0dDU19BVVRIX0lEPSckTURTRENFUlRJRklDQVRFU0FOJwpleHBvcnQgTU9OSVRPUklOR19HQ1NfTkFNRVNQQUNFPSckUlBNRFNETkFNRVNQQUNFJwpleHBvcnQgTU9OSVRPUklOR19DT05GSUdfVkVSU0lPTj0nJFJQTURTRENPTkZJR1ZFUlNJT04nCmV4cG9ydCBNT05JVE9SSU5HX1VTRV9HRU5FVkFfQ09ORklHX1NFUlZJQ0U9dHJ1ZQoKZXhwb3J0IE1PTklUT1JJTkdfVEVOQU5UPSckTE9DQVRJT04nCmV4cG9ydCBNT05JVE9SSU5HX1JPTEU9cnAKZXhwb3J0IE1PTklUT1JJTkdfUk9MRV9JTlNUQU5DRT1cIiQoaG9zdG5hbWUpXCIKCmV4cG9ydCBNRFNEX01TR1BBQ0tfU09SVF9DT0xVTU5TPTFcIiIKCiAgICB3cml0ZV9maWxlIGRlZmF1bHRfbWRzZF9maWxlbmFtZSBkZWZhdWx0X21kc2RfZmlsZQoKfQoKIyBydW5fYXpzZWNkX2NvbmZpZ19zY2FuCnJ1bl9henNlY2RfY29uZmlnX3NjYW4oKSB7CiAgICBsb2NhbCAtYXIgY29uZmlncz0oCiAgICAgICAgImJhc2VsaW5lIgogICAgICAgICJjbGFtYXYiCiAgICAgICAgInNvZnR3YXJlIgogICAgKQoKICAgIGxvZyAiU2Nhbm5pbmcgY29uZmlndXJhdGlvbiBmaWxlcyAke2NvbmZpZ3NbKl19IgogICAgIyBzaGVsbGNoZWNrIGRpc2FibGU9U0MyMDY4CiAgICBmb3Igc2NhbiBpbiAke2NvbmZpZ3NbQF19OyBkbwogICAgICAgIGxvZyAiU2Nhbm5pbmcgY29uZmlnIGZpbGUgJHNjYW4gbm93IgogICAgICAgIC91c3IvbG9jYWwvYmluL2F6c2VjZCBjb25maWcgLXMgIiRzY2FuIiAtZCBQMUQKICAgIGRvbmUKfQoKIyB3cml0ZV9maWxlCiMgQXJncwojIDEpIGZpbGVuYW1lIC0gc3RyaW5nCiMgMikgZmlsZV9jb250ZW50cyAtIHN0cmluZwojIDMpIGNsb2JiZXIgLSBib29sZWFuOyBvcHRpb25hbCAtIGRlZmF1bHRzIHRvIGZhbHNlCndyaXRlX2ZpbGUoKSB7CiAgICBsb2NhbCAtbiBmaWxlbmFtZT0iJDEiCiAgICBsb2NhbCAtbiBmaWxlX2NvbnRlbnRzPSIkMiIKICAgIGxvY2FsIC1yIGNsb2JiZXI9IiR7MzotZmFsc2V9IgoKICAgIGlmICRjbG9iYmVyOyB0aGVuCiAgICAgICAgbG9nICJPdmVyd3JpdGluZyBmaWxlICRmaWxlbmFtZSIKICAgICAgICBlY2hvICIkZmlsZV9jb250ZW50cyIgPiAiJGZpbGVuYW1lIgogICAgZWxzZQogICAgICAgIGxvZyAiQXBwZW5kaW5nIHRvICRmaWxlbmFtZSIKICAgICAgICBlY2hvICIkZmlsZV9jb250ZW50cyIgPj4gIiRmaWxlbmFtZSIKICAgIGZpCn0KCiMgcmVib290X3ZtIHJlc3RvcmVzIGFsbCBzZWxpbnV4IGZpbGUgY29udGV4dHMsIHdhaXRzIDMwIHNlY29uZHMgdGhlbiByZWJvb3RzCnJlYm9vdF92bSgpIHsKICAgIGNvbmZpZ3VyZV9zZWxpbnV4ICJ0cnVlIgogICAgKHNsZWVwIDMwICYmIGxvZyAicmVib290aW5nIHZtIG5vdyI7IHJlYm9vdCkgJgp9CgojIGxvZyBpcyBhIHdyYXBwZXIgZm9yIGVjaG8gdGhhdCBpbmNsdWRlcyB0aGUgZnVuY3Rpb24gbmFtZQpsb2coKSB7CiAgICBsb2NhbCAtciBtc2c9IiR7MTotImxvZyBtZXNzYWdlIGlzIGVtcHR5In0iCiAgICBsb2NhbCAtciBzdGFja19sZXZlbD0iJHsyOi0xfSIKICAgIGVjaG8gIiR7RlVOQ05BTUVbJHtzdGFja19sZXZlbH1dfTogJHttc2d9Igp9CgojIGFib3J0IGlzIGEgd3JhcHBlciBmb3IgbG9nIHRoYXQgZXhpdHMgd2l0aCBhbiBlcnJvciBjb2RlCmFib3J0KCkgewogICAgbG9jYWwgLXJpIG9yaWdpbl9zdGFja2xldmVsPTIKICAgIGxvZyAiJHsxfSIgIiRvcmlnaW5fc3RhY2tsZXZlbCIKICAgIGV4aXQgMQp9CgpleHBvcnQgQVpVUkVfQ0xPVURfTkFNRT0iJHtBWlVSRUNMT1VETkFNRTo/IkZhaWxlZCB0byBjYXJyeSBvdmVyIHZhcmlhYmxlcyJ9IgoKbWFpbgo=')))]" + "script": "[base64(concat(base64ToString('c2V0IC1leAoK'),'ACRRESOURCEID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('acrResourceId')),''')\n','ADMINAPICLIENTCERTCOMMONNAME=$(base64 -d \u003c\u003c\u003c''',base64(parameters('adminApiClientCertCommonName')),''')\n','ARMAPICLIENTCERTCOMMONNAME=$(base64 -d \u003c\u003c\u003c''',base64(parameters('armApiClientCertCommonName')),''')\n','ARMCLIENTID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('armClientId')),''')\n','AZURECLOUDNAME=$(base64 -d \u003c\u003c\u003c''',base64(parameters('azureCloudName')),''')\n','AZURESECPACKQUALYSURL=$(base64 -d \u003c\u003c\u003c''',base64(parameters('azureSecPackQualysUrl')),''')\n','AZURESECPACKVSATENANTID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('azureSecPackVSATenantId')),''')\n','BILLINGE2ESTORAGEACCOUNTID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('billingE2EStorageAccountId')),''')\n','CLUSTERMDMACCOUNT=$(base64 -d \u003c\u003c\u003c''',base64(parameters('clusterMdmAccount')),''')\n','CLUSTERMDSDACCOUNT=$(base64 -d \u003c\u003c\u003c''',base64(parameters('clusterMdsdAccount')),''')\n','CLUSTERMDSDCONFIGVERSION=$(base64 -d \u003c\u003c\u003c''',base64(parameters('clusterMdsdConfigVersion')),''')\n','CLUSTERMDSDNAMESPACE=$(base64 -d \u003c\u003c\u003c''',base64(parameters('clusterMdsdNamespace')),''')\n','CLUSTERPARENTDOMAINNAME=$(base64 -d \u003c\u003c\u003c''',base64(parameters('clusterParentDomainName')),''')\n','DATABASEACCOUNTNAME=$(base64 -d \u003c\u003c\u003c''',base64(parameters('databaseAccountName')),''')\n','DBTOKENCLIENTID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('dbtokenClientId')),''')\n','FLUENTBITIMAGE=$(base64 -d \u003c\u003c\u003c''',base64(parameters('fluentbitImage')),''')\n','FPCLIENTID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('fpClientId')),''')\n','FPSERVICEPRINCIPALID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('fpServicePrincipalId')),''')\n','GATEWAYDOMAINS=$(base64 -d \u003c\u003c\u003c''',base64(parameters('gatewayDomains')),''')\n','GATEWAYRESOURCEGROUPNAME=$(base64 -d \u003c\u003c\u003c''',base64(parameters('gatewayResourceGroupName')),''')\n','GATEWAYSERVICEPRINCIPALID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('gatewayServicePrincipalId')),''')\n','KEYVAULTDNSSUFFIX=$(base64 -d \u003c\u003c\u003c''',base64(parameters('keyvaultDNSSuffix')),''')\n','KEYVAULTPREFIX=$(base64 -d \u003c\u003c\u003c''',base64(parameters('keyvaultPrefix')),''')\n','MDMFRONTENDURL=$(base64 -d \u003c\u003c\u003c''',base64(parameters('mdmFrontendUrl')),''')\n','MDSDENVIRONMENT=$(base64 -d \u003c\u003c\u003c''',base64(parameters('mdsdEnvironment')),''')\n','PORTALACCESSGROUPIDS=$(base64 -d \u003c\u003c\u003c''',base64(parameters('portalAccessGroupIds')),''')\n','PORTALCLIENTID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('portalClientId')),''')\n','PORTALELEVATEDGROUPIDS=$(base64 -d \u003c\u003c\u003c''',base64(parameters('portalElevatedGroupIds')),''')\n','RPFEATURES=$(base64 -d \u003c\u003c\u003c''',base64(parameters('rpFeatures')),''')\n','RPIMAGE=$(base64 -d \u003c\u003c\u003c''',base64(parameters('rpImage')),''')\n','RPMDMACCOUNT=$(base64 -d \u003c\u003c\u003c''',base64(parameters('rpMdmAccount')),''')\n','RPMDSDACCOUNT=$(base64 -d \u003c\u003c\u003c''',base64(parameters('rpMdsdAccount')),''')\n','RPMDSDCONFIGVERSION=$(base64 -d \u003c\u003c\u003c''',base64(parameters('rpMdsdConfigVersion')),''')\n','RPMDSDNAMESPACE=$(base64 -d \u003c\u003c\u003c''',base64(parameters('rpMdsdNamespace')),''')\n','RPPARENTDOMAINNAME=$(base64 -d \u003c\u003c\u003c''',base64(parameters('rpParentDomainName')),''')\n','CLUSTERSINSTALLVIAHIVE=$(base64 -d \u003c\u003c\u003c''',base64(parameters('clustersInstallViaHive')),''')\n','CLUSTERSADOPTBYHIVE=$(base64 -d \u003c\u003c\u003c''',base64(parameters('clustersAdoptByHive')),''')\n','CLUSTERDEFAULTINSTALLERPULLSPEC=$(base64 -d \u003c\u003c\u003c''',base64(parameters('clusterDefaultInstallerPullspec')),''')\n','USECHECKACCESS=$(base64 -d \u003c\u003c\u003c''',base64(parameters('useCheckAccess')),''')\n','ADMINAPICABUNDLE=''',parameters('adminApiCaBundle'),'''\n','ARMAPICABUNDLE=''',parameters('armApiCaBundle'),'''\n','MDMIMAGE=''/genevamdm:2.2024.328.1744-c5fb79-20240328t1935''\n','LOCATION=$(base64 -d \u003c\u003c\u003c''',base64(resourceGroup().location),''')\n','SUBSCRIPTIONID=$(base64 -d \u003c\u003c\u003c''',base64(subscription().subscriptionId),''')\n','RESOURCEGROUPNAME=$(base64 -d \u003c\u003c\u003c''',base64(resourceGroup().name),''')\n','\n',base64ToString('IyEvYmluL2Jhc2gKCnNldCAtbyBlcnJleGl0IFwKICAgIC1vIG5vdW5zZXQKCmlmIFsgIiR7REVCVUc6LWZhbHNlfSIgPT0gdHJ1ZSBdOyB0aGVuCiAgICBzZXQgLXgKZmkKCm1haW4oKSB7CiAgICBwYXJzZV9ydW5fb3B0aW9ucyAiJEAiCgoKICAgIGNvbmZpZ3VyZV9zc2hkCiAgICBjb25maWd1cmVfYW5kX2luc3RhbGxfZG5mX3BrZ3NfcmVwb3MKICAgIGNvbmZpZ3VyZV9kaXNrX3BhcnRpdGlvbnMKICAgIGNvbmZpZ3VyZV9sb2dyb3RhdGUKICAgIGNvbmZpZ3VyZV9zZWxpbnV4CgogICAgbWtkaXIgLXAgL3Zhci9sb2cvam91cm5hbAogICAgbWtkaXIgLXAgL3Zhci9saWIvd2FhZ2VudC9NaWNyb3NvZnQuQXp1cmUuS2V5VmF1bHQuU3RvcmUKCiAgICBjb25maWd1cmVfZmlyZXdhbGxkX3J1bGVzCiAgICBwdWxsX2NvbnRhaW5lcl9pbWFnZXMKICAgIGNvbmZpZ3VyZV9zeXN0ZW1fc2VydmljZXMKICAgIHJlYm9vdF92bQp9Cgp1c2FnZSgpIHsKICAgIGxvY2FsIC1uIG9wdGlvbnM9IiQxIgogICAgbG9nICIkKGJhc2VuYW1lICIkMCIpIFskb3B0aW9uc10KICAgICAgICAtZCBDb25maWd1cmUgRGlzayBQYXJ0aXRpb25zCiAgICAgICAgLXAgQ29uZmlndXJlIHJwbSByZXBvc2l0b3JpZXMsIGltcG9ydCByZXF1aXJlZCBycG0ga2V5cywgdXBkYXRlICYgaW5zdGFsbCBwYWNrYWdlcyB3aXRoIGRuZgogICAgICAgIC1sIENvbmZpZ3VyZSBsb2dyb3RhdGUuY29uZgogICAgICAgIC1zIE1ha2Ugc2VsaW51eCBtb2RpZmljYXRpb25zIHJlcXVpcmVkIGZvciBBUk8gUlAKICAgICAgICAtciBDb25maWd1cmUgc3NoZCAtIEFsbG93IHBhc3N3b3JkIGF1dGhlbnRpY2FpdG9uCiAgICAgICAgLWYgQ29uZmlndXJlIGZpcmV3YWxsZCBkZWZhdWx0IHpvbmUgcnVsZXMKICAgICAgICAtdSBDb25maWd1cmUgc3lzdGVtZCB1bml0IGZpbGVzIGZvciBBUk8gUlAKICAgICAgICAtaSBQdWxsIGNvbnRhaW5lciBpbWFnZXMKCiAgICAgICAgTm90ZTogc3RlcHMgd2lsbCBiZSBleGVjdXRlZCBpbiB0aGUgb3JkZXIgdGhhdCBmbGFncyBhcmUgcHJvdmlkZWQKICAgICIKfQoKIyBwYXJzZV9ydW5fb3B0aW9ucyB0YWtlcyBhbGwgYXJndWVtZW50cyBwYXNzZWQgdG8gbWFpbiBhbmQgcGFyc2VzIHRoZW0KIyBhbGxvd2luZyBpbmRpdmlkdWFsIHN0ZXAocykgdG8gYmUgcmFuLCByYXRoZXIgdGhhbiBhbGwgc3RlcHMKIwojIFRoaXMgaXMgdXNlZnVsIGZvciBsb2NhbCB0ZXN0aW5nLCBvciBwb3NzaWJseSBtb2RpZnlpbmcgdGhlIGJvb3RzdHJhcCBleGVjdXRpb24gdmlhIGVudmlyb25tZW50IHZhcmlhYmxlcyBpbiB0aGUgZGVwbG95bWVudCBwaXBlbGluZQpwYXJzZV9ydW5fb3B0aW9ucygpIHsKICAgICMgc2hlbGxjaGVjayBkaXNhYmxlPVNDMjIwNgogICAgbG9jYWwgLWEgb3B0aW9ucz0oJHsxOi19KQogICAgaWYgWyAiJHsjb3B0aW9uc1tAXX0iIC1lcSAwIF07IHRoZW4KICAgICAgICBsb2cgIlJ1bm5pbmcgYWxsIHN0ZXBzIgogICAgICAgIHJldHVybiAwCiAgICBmaQoKICAgIGxvY2FsIE9QVElORAogICAgbG9jYWwgLXIgYWxsb3dlZF9vcHRpb25zPSJkcGxzcmZ1aSIKICAgIHdoaWxlIGdldG9wdHMgJHthbGxvd2VkX29wdGlvbnN9IG9wdGlvbnM7IGRvCiAgICAgICAgY2FzZSAiJHtvcHRpb25zfSIgaW4KICAgICAgICAgICAgZCkKICAgICAgICAgICAgICAgIGxvZyAiUnVubmluZyBzdGVwIGNvbmZpZ3VyZV9kaXNrX3BhcnRpdGlvbnMiCiAgICAgICAgICAgICAgICBjb25maWd1cmVfZGlza19wYXJ0aXRpb25zCiAgICAgICAgICAgICAgICA7OwogICAgICAgICAgICBwKQogICAgICAgICAgICAgICAgbG9nICJSdW5uaW5nIHN0ZXAgY29uZmlndXJlX2FuZF9pbnN0YWxsX2RuZl9wa2dzX3JlcG9zIgogICAgICAgICAgICAgICAgY29uZmlndXJlX2FuZF9pbnN0YWxsX2RuZl9wa2dzX3JlcG9zCiAgICAgICAgICAgICAgICA7OwogICAgICAgICAgICBsKQogICAgICAgICAgICAgICAgbG9nICJSdW5uaW5nIGNvbmZpZ3VyZV9sb2dyb3RhdGUiCiAgICAgICAgICAgICAgICBjb25maWd1cmVfbG9ncm90YXRlCiAgICAgICAgICAgICAgICA7OwogICAgICAgICAgICBzKQogICAgICAgICAgICAgICAgbG9nICJSdW5uaW5nIGNvbmZpZ3VyZV9zZWxpbnV4IgogICAgICAgICAgICAgICAgY29uZmlndXJlX3NlbGludXgKICAgICAgICAgICAgICAgIDs7CiAgICAgICAgICAgIHIpCiAgICAgICAgICAgICAgICBsb2cgIlJ1bm5pbmcgY29uZmlndXJlX3NzaGQiCiAgICAgICAgICAgICAgICBjb25maWd1cmVfc3NoZAogICAgICAgICAgICAgICAgOzsKICAgICAgICAgICAgZikKICAgICAgICAgICAgICAgIGxvZyAiUnVubmluZyBjb25maWd1cmVfZmlyZXdhbGxkX3J1bGVzIgogICAgICAgICAgICAgICAgY29uZmlndXJlX2ZpcmV3YWxsZF9ydWxlcwogICAgICAgICAgICAgICAgOzsKICAgICAgICAgICAgdSkKICAgICAgICAgICAgICAgIGxvZyAiUnVubmluZyBwdWxsX2NvbnRhaW5lcl9pbWFnZXMgJiBjb25maWd1cmVfc3lzdGVtX3NlcnZpY2VzIgogICAgICAgICAgICAgICAgY29uZmlndXJlX3N5c3RlbV9zZXJ2aWNlcwogICAgICAgICAgICAgICAgOzsKICAgICAgICAgICAgaSkKICAgICAgICAgICAgICAgIGxvZyAiUnVubmluZyBwdWxsX2NvbnRhaW5lcl9pbWFnZXMiCiAgICAgICAgICAgICAgICBwdWxsX2NvbnRhaW5lcl9pbWFnZXMgCiAgICAgICAgICAgICAgICA7OwogICAgICAgICAgICAqKQogICAgICAgICAgICAgICAgdXNhZ2UgYWxsb3dlZF9vcHRpb25zCiAgICAgICAgICAgICAgICBhYm9ydCAiVW5rb3duIG9wdGlvbiBwcm92aWRlZCIKICAgICAgICAgICAgICAgIDs7CiAgICAgICAgZXNhYwogICAgZG9uZQogICAgCiAgICBleGl0IDAKfQoKIyBXZSBuZWVkIHRvIGNvbmZpZ3VyZSBQYXNzd29yZEF1dGhlbnRpY2F0aW9uIHRvIHllcyBpbiBvcmRlciBmb3IgdGhlIFZNU1MgQWNjZXNzIEpJVCB0byB3b3JrCmNvbmZpZ3VyZV9zc2hkKCkgewogICAgbG9nICJzdGFydGluZyIKICAgIGxvZyAic2V0dGluZyBzc2ggcGFzc3dvcmQgYXV0aGVudGljYXRpb24iCiAgICBzZWQgLWkgJ3MvUGFzc3dvcmRBdXRoZW50aWNhdGlvbiBuby9QYXNzd29yZEF1dGhlbnRpY2F0aW9uIHllcy9nJyAvZXRjL3NzaC9zc2hkX2NvbmZpZwoKICAgIHN5c3RlbWN0bCByZWxvYWQgc3NoZC5zZXJ2aWNlCiAgICBzeXN0ZW1jdGwgaXMtYWN0aXZlIC0tcXVpZXQgc3NoZCB8fCBhYm9ydCAic3NoZCBmYWlsZWQgdG8gcmVsb2FkIgp9CgojIGNvbmZpZ3VyZV9hbmRfaW5zdGFsbF9kbmZfcGtnc19yZXBvcwpjb25maWd1cmVfYW5kX2luc3RhbGxfZG5mX3BrZ3NfcmVwb3MoKSB7CiAgICBsb2cgInN0YXJ0aW5nIgoKICAgICMgdHJhbnNhY3Rpb24gYXR0ZW1wdCByZXRyeSB0aW1lIGluIHNlY29uZHMKICAgIGxvY2FsIC1yaSByZXRyeV93YWl0X3RpbWU9NjAKICAgIGNvbmZpZ3VyZV9yaHVpX3JlcG8gcmV0cnlfd2FpdF90aW1lCiAgICBjcmVhdGVfYXp1cmVfcnBtX3JlcG9zIHJldHJ5X3dhaXRfdGltZQoKICAgIGxvY2FsIC1hciBleGNsdWRlX3BrZ3M9KAogICAgICAgICIteCBXQUxpbnV4QWdlbnQiCiAgICAgICAgIi14IFdBTGludXhBZ2VudC11ZGV2IgogICAgKQoKICAgIGRuZl91cGRhdGVfcGtncyBleGNsdWRlX3BrZ3MgcmV0cnlfd2FpdF90aW1lCgogICAgbG9jYWwgLXJhIHJwbV9rZXlzPSgKICAgICAgICBodHRwczovL2RsLmZlZG9yYXByb2plY3Qub3JnL3B1Yi9lcGVsL1JQTS1HUEctS0VZLUVQRUwtOAogICAgICAgIGh0dHBzOi8vcGFja2FnZXMubWljcm9zb2Z0LmNvbS9rZXlzL21pY3Jvc29mdC5hc2MKICAgICkKCiAgICBycG1faW1wb3J0X2tleXMgcnBtX2tleXMgcmV0cnlfd2FpdF90aW1lCgogICAgbG9jYWwgLXJhIHJlcG9fcnBtX3BrZ3M9KAogICAgICAgIGh0dHBzOi8vZGwuZmVkb3JhcHJvamVjdC5vcmcvcHViL2VwZWwvZXBlbC1yZWxlYXNlLWxhdGVzdC04Lm5vYXJjaC5ycG0KICAgICkKCiAgICBsb2NhbCAtcmEgaW5zdGFsbF9wa2dzPSgKICAgICAgICBjbGFtYXYKICAgICAgICBhenNlYy1jbGFtYXYKICAgICAgICBhenNlYy1tb25pdG9yCiAgICAgICAgYXp1cmUtY2xpCiAgICAgICAgYXp1cmUtbWRzZAogICAgICAgIGF6dXJlLXNlY3VyaXR5CiAgICAgICAgcG9kbWFuCiAgICAgICAgcG9kbWFuLWRvY2tlcgogICAgICAgIG9wZW5zc2wtcGVybAogICAgICAgICMgaGFjayAtIHdlIGFyZSBpbnN0YWxsaW5nIHB5dGhvbjMgb24gaG9zdHMgZHVlIHRvIGFuIGlzc3VlIHdpdGggQXp1cmUgTGludXggRXh0ZW5zaW9ucyBodHRwczovL2dpdGh1Yi5jb20vQXp1cmUvYXp1cmUtbGludXgtZXh0ZW5zaW9ucy9wdWxsLzE1MDUKICAgICAgICBweXRob24zCiAgICApCgogICAgZG5mX2luc3RhbGxfcGtncyByZXBvX3JwbV9wa2dzIHJldHJ5X3dhaXRfdGltZQogICAgZG5mX2luc3RhbGxfcGtncyBpbnN0YWxsX3BrZ3MgcmV0cnlfd2FpdF90aW1lCn0KCiMgY29uZmlndXJlX3JodWlfcmVwbwpjb25maWd1cmVfcmh1aV9yZXBvKCkgewogICAgbG9nICJzdGFydGluZyIKCiAgICBsb2NhbCAtcmEgY21kPSgKICAgICAgICBkbmYKICAgICAgICB1cGRhdGUKICAgICAgICAteQogICAgICAgIC0tZGlzYWJsZXJlcG89JyonCiAgICAgICAgLS1lbmFibGVyZXBvPSdyaHVpLW1pY3Jvc29mdC1henVyZSonCiAgICApCgogICAgbG9nICJydW5uaW5nIFJIVUkgcGFja2FnZSB1cGRhdGVzIgogICAgcmV0cnkgY21kICIkMSIKfQoKIyByZXRyeSBBZGRpbmcgcmV0cnkgbG9naWMgdG8geXVtIGNvbW1hbmRzIGluIG9yZGVyIHRvIGF2b2lkIHN0YWxsaW5nIG91dCBvbiByZXNvdXJjZSBsb2NrcwpyZXRyeSgpIHsKICAgIGxvY2FsIC1uIGNtZF9yZXRyeT0iJDEiCiAgICBsb2NhbCAtbiB3YWl0X3RpbWU9IiQyIgoKICAgIGZvciBhdHRlbXB0IGluIHsxLi41fTsgZG8KICAgICAgICBsb2cgImF0dGVtcHQgIyR7YXR0ZW1wdH0gLSAke0ZVTkNOQU1FWzJdfSIKICAgICAgICAke2NtZF9yZXRyeVtAXX0gJgoKICAgICAgICB3YWl0ICQhICYmIGJyZWFrCiAgICAgICAgaWYgW1sgJHthdHRlbXB0fSAtbHQgNSBdXTsgdGhlbgogICAgICAgICAgICBzbGVlcCAiJHdhaXRfdGltZSIKICAgICAgICBlbHNlCiAgICAgICAgICAgIGFib3J0ICJhdHRlbXB0ICMke2F0dGVtcHR9IC0gRmFpbGVkIHRvIHVwZGF0ZSBwYWNrYWdlcyIKICAgICAgICBmaQogICAgZG9uZQp9CgojIGRuZl91cGRhdGVfcGtncwpkbmZfdXBkYXRlX3BrZ3MoKSB7CiAgICBsb2NhbCAtbiBleGNsdWRlcz0iJDEiCiAgICBsb2cgInN0YXJ0aW5nIgoKICAgIGxvY2FsIC1yYSBjbWQ9KAogICAgICAgIGRuZgogICAgICAgIC15CiAgICAgICAgJHtleGNsdWRlc1tAXX0KICAgICAgICB1cGRhdGUKICAgICAgICAtLWFsbG93ZXJhc2luZwogICAgKQoKICAgIGxvZyAiVXBkYXRpbmcgYWxsIHBhY2thZ2VzIgogICAgcmV0cnkgY21kICIkMiIKfQoKIyBkbmZfaW5zdGFsbF9wa2dzCmRuZl9pbnN0YWxsX3BrZ3MoKSB7CiAgICBsb2NhbCAtbiBwa2dzPSIkMSIKICAgIGxvZyAic3RhcnRpbmciCgogICAgbG9jYWwgLXJhIGNtZD0oCiAgICAgICAgZG5mCiAgICAgICAgLXkKICAgICAgICBpbnN0YWxsCiAgICAgICAgJHtwa2dzW0BdfQogICAgKQoKICAgIGxvZyAiQXR0ZW1wdGluZyB0byBpbnN0YWxsIHBhY2thZ2VzOiAke3BrZ3NbKl19IgogICAgcmV0cnkgY21kICIkMiIKfQoKIyBycG1faW1wb3J0X2tleXMKcnBtX2ltcG9ydF9rZXlzKCkgewogICAgbG9jYWwgLW4ga2V5cz0iJDEiCiAgICBsb2cgInN0YXJ0aW5nIgoKCiAgICAjIHNoZWxsY2hlY2sgZGlzYWJsZT1TQzIwNjgKICAgIGZvciBrZXkgaW4gJHtrZXlzW0BdfTsgZG8KICAgICAgICBpZiBbICR7I2tleXNbQF19IC1lcSAwIF07IHRoZW4KICAgICAgICAgICAgYnJlYWsKICAgICAgICBmaQogICAgICAgICAgICBsb2NhbCAtYSBjbWQ9KAogICAgICAgICAgICAgICAgcnBtCiAgICAgICAgICAgICAgICAtLWltcG9ydAogICAgICAgICAgICAgICAgLXYKICAgICAgICAgICAgICAgICIka2V5IgogICAgICAgICAgICApCgogICAgICAgICAgICBsb2cgImF0dGVtcHQgIyRhdHRlbXB0IC0gaW1wb3J0aW5nIHJwbSByZXBvc2l0b3J5IGtleSAka2V5IgogICAgICAgICAgICByZXRyeSBjbWQgIiQyIiAmJiB1bnNldCBrZXkKICAgIGRvbmUKfQoKIyBjb25maWd1cmVfZGlza19wYXJ0aXRpb25zCmNvbmZpZ3VyZV9kaXNrX3BhcnRpdGlvbnMoKSB7CiAgICBsb2cgInN0YXJ0aW5nIgogICAgbG9nICJleHRlbmRpbmcgcGFydGl0aW9uIHRhYmxlIgoKICAgICMgTGludXggYmxvY2sgZGV2aWNlcyBhcmUgaW5jb25zaXN0ZW50bHkgbmFtZWQKICAgICMgaXQncyBkaWZmaWN1bHQgdG8gdGllIHRoZSBsdm0gcHYgdG8gdGhlIHBoeXNpY2FsIGRpc2sgdXNpbmcgL2Rldi9kaXNrIGZpbGVzLCB3aGljaCBpcyB3aHkgbHZzIGlzIHVzZWQgaGVyZQogICAgcGh5c2ljYWxfZGlzaz0iJChsdnMgLW8gZGV2aWNlcyAtYSB8IGhlYWQgLW4yIHwgdGFpbCAtbjEgfCBjdXQgLWQgJyAnIC1mIDMgfCBjdXQgLWQgXCggLWYgMSB8IHRyIC1kICdbOmRpZ2l0Ol0nKSIKICAgIGdyb3dwYXJ0ICIkcGh5c2ljYWxfZGlzayIgMgoKICAgIGxvZyAiZXh0ZW5kaW5nIGZpbGVzeXN0ZW1zIgogICAgbG9nICJleHRlbmRpbmcgcm9vdCBsdm0iCiAgICBsdmV4dGVuZCAtbCArMjAlRlJFRSAvZGV2L3Jvb3R2Zy9yb290bHYKICAgIGxvZyAiZ3Jvd2luZyByb290IGZpbGVzeXN0ZW0iCiAgICB4ZnNfZ3Jvd2ZzIC8KCiAgICBsb2cgImV4dGVuZGluZyB2YXIgbHZtIgogICAgbHZleHRlbmQgLWwgKzEwMCVGUkVFIC9kZXYvcm9vdHZnL3Zhcmx2CiAgICBsb2cgImdyb3dpbmcgdmFyIGZpbGVzeXN0ZW0iCiAgICB4ZnNfZ3Jvd2ZzIC92YXIKfQoKIyBjb25maWd1cmVfbG9ncm90YXRlIGNsb2JiZXJzIC9ldGMvbG9ncm90YXRlLmNvbmYKY29uZmlndXJlX2xvZ3JvdGF0ZSgpIHsKICAgIGxvZyAic3RhcnRpbmciCgogICAgbG9jYWwgLXIgbG9ncm90YXRlX2NvbmZfZmlsZW5hbWU9Jy9ldGMvbG9ncm90YXRlLmNvbmYnCiAgICBsb2NhbCAtciBsb2dyb3RhdGVfY29uZl9maWxlPScjIHNlZSAibWFuIGxvZ3JvdGF0ZSIgZm9yIGRldGFpbHMKIyByb3RhdGUgbG9nIGZpbGVzIHdlZWtseQp3ZWVrbHkKCiMga2VlcCAyIHdlZWtzIHdvcnRoIG9mIGJhY2tsb2dzCnJvdGF0ZSAyCgojIGNyZWF0ZSBuZXcgKGVtcHR5KSBsb2cgZmlsZXMgYWZ0ZXIgcm90YXRpbmcgb2xkIG9uZXMKY3JlYXRlCgojIHVzZSBkYXRlIGFzIGEgc3VmZml4IG9mIHRoZSByb3RhdGVkIGZpbGUKZGF0ZWV4dAoKIyB1bmNvbW1lbnQgdGhpcyBpZiB5b3Ugd2FudCB5b3VyIGxvZyBmaWxlcyBjb21wcmVzc2VkCmNvbXByZXNzCgojIFJQTSBwYWNrYWdlcyBkcm9wIGxvZyByb3RhdGlvbiBpbmZvcm1hdGlvbiBpbnRvIHRoaXMgZGlyZWN0b3J5CmluY2x1ZGUgL2V0Yy9sb2dyb3RhdGUuZAoKIyBubyBwYWNrYWdlcyBvd24gd3RtcCBhbmQgYnRtcCAtLSB3ZSB3aWxsIHJvdGF0ZSB0aGVtIGhlcmUKL3Zhci9sb2cvd3RtcCB7CiAgICBtb250aGx5CiAgICBjcmVhdGUgMDY2NCByb290IHV0bXAKICAgICAgICBtaW5zaXplIDFNCiAgICByb3RhdGUgMQp9CgovdmFyL2xvZy9idG1wIHsKICAgIG1pc3NpbmdvawogICAgbW9udGhseQogICAgY3JlYXRlIDA2MDAgcm9vdCB1dG1wCiAgICByb3RhdGUgMQp9JwoKICAgIHdyaXRlX2ZpbGUgbG9ncm90YXRlX2NvbmZfZmlsZW5hbWUgbG9ncm90YXRlX2NvbmZfZmlsZSB0cnVlCn0KCiMgY3JlYXRlX2F6dXJlX3JwbV9yZXBvcyBjcmVhdGVzIC9ldGMveXVtLnJlcG9zLmQvYXp1cmUucmVwbyByZXBvc2l0b3J5IGZpbGUKY3JlYXRlX2F6dXJlX3JwbV9yZXBvcygpIHsKICAgIGxvZyAic3RhcnRpbmciCgogICAgbG9jYWwgLXIgYXp1cmVfcmVwb19maWxlbmFtZT0nL2V0Yy95dW0ucmVwb3MuZC9henVyZS5yZXBvJwogICAgbG9jYWwgLXIgYXp1cmVfcmVwb19maWxlPSdbYXp1cmUtY2xpXQpuYW1lPWF6dXJlLWNsaQpiYXNldXJsPWh0dHBzOi8vcGFja2FnZXMubWljcm9zb2Z0LmNvbS95dW1yZXBvcy9henVyZS1jbGkKZW5hYmxlZD15ZXMKZ3BnY2hlY2s9eWVzCgpbYXp1cmVjb3JlXQpuYW1lPWF6dXJlY29yZQpiYXNldXJsPWh0dHBzOi8vcGFja2FnZXMubWljcm9zb2Z0LmNvbS95dW1yZXBvcy9henVyZWNvcmUKZW5hYmxlZD15ZXMKZ3BnY2hlY2s9bm8nCgogICAgd3JpdGVfZmlsZSBhenVyZV9yZXBvX2ZpbGVuYW1lIGF6dXJlX3JlcG9fZmlsZSB0cnVlCn0KCiMgY29uZmlndXJlX3NlbGludXgKY29uZmlndXJlX3NlbGludXgoKSB7CiAgICBsb2cgInN0YXJ0aW5nIgoKICAgIGxvY2FsIC1yIHJlbGFiZWw9IiR7MTotZmFsc2V9IgoKICAgIGFscmVhZHlfZGVmaW5lZF9pZ25vcmVfZXJyb3I9IkZpbGUgY29udGV4dCBmb3IgL3Zhci9sb2cvam91cm5hbCgvLiopPyBhbHJlYWR5IGRlZmluZWQiCiAgICBzZW1hbmFnZSBmY29udGV4dCAtYSAtdCB2YXJfbG9nX3QgIi92YXIvbG9nL2pvdXJuYWwoLy4qKT8iIHx8IGxvZyAiJGFscmVhZHlfZGVmaW5lZF9pZ25vcmVfZXJyb3IiCiAgICBjaGNvbiAtUiBzeXN0ZW1fdTpvYmplY3Rfcjp2YXJfbG9nX3Q6czAgL3Zhci9vcHQvbWljcm9zb2Z0L2xpbnV4bW9uYWdlbnQKCiAgICBpZiAiJHJlbGFiZWwiOyB0aGVuCiAgICAgICAgcmVzdG9yZWNvbiAtUkYgL3Zhci9sb2cvKiB8fCBsb2cgIiRhbHJlYWR5X2RlZmluZWRfaWdub3JlX2Vycm9yIgogICAgZmkKfQoKIyBjb25maWd1cmVfZmlyZXdhbGxkX3J1bGVzCmNvbmZpZ3VyZV9maXJld2FsbGRfcnVsZXMoKSB7CiAgICBsb2cgInN0YXJ0aW5nIgoKICAgICMgaHR0cHM6Ly9hY2Nlc3MucmVkaGF0LmNvbS9zZWN1cml0eS9jdmUvY3ZlLTIwMjAtMTM0MDEKICAgIGxvY2FsIC1yIHByZWZpeD0iL2V0Yy9zeXNjdGwuZCIKICAgIGxvY2FsIC1yIGRpc2FibGVfYWNjZXB0X3JhX2NvbmZfZmlsZW5hbWU9IiRwcmVmaXgvMDItZGlzYWJsZS1hY2NlcHQtcmEuY29uZiIKICAgIGxvY2FsIC1yIGRpc2FibGVfYWNjZXB0X3JhX2NvbmZfZmlsZT0ibmV0LmlwdjYuY29uZi5hbGwuYWNjZXB0X3JhPTAiCgogICAgd3JpdGVfZmlsZSBkaXNhYmxlX2FjY2VwdF9yYV9jb25mX2ZpbGVuYW1lIGRpc2FibGVfYWNjZXB0X3JhX2NvbmZfZmlsZSB0cnVlCgogICAgbG9jYWwgLXIgZGlzYWJsZV9jb3JlX2ZpbGVuYW1lPSIkcHJlZml4LzAxLWRpc2FibGUtY29yZS5jb25mIgogICAgbG9jYWwgLXIgZGlzYWJsZV9jb3JlX2ZpbGU9Imtlcm5lbC5jb3JlX3BhdHRlcm4gPSB8L2Jpbi90cnVlCiAgICAiCiAgICB3cml0ZV9maWxlIGRpc2FibGVfY29yZV9maWxlbmFtZSBkaXNhYmxlX2NvcmVfZmlsZSB0cnVlCgogICAgc3lzY3RsIC0tc3lzdGVtCgogICAgbG9jYWwgLXJhIGVuYWJsZV9wb3J0cz0oCiAgICAgICAgIjQ0My90Y3AiCiAgICAgICAgIjQ0NC90Y3AiCiAgICAgICAgIjQ0NS90Y3AiCiAgICAgICAgIjIyMjIvdGNwIgogICAgKQoKICAgIGxvZyAiRW5hYmxpbmcgcG9ydHMgJHtlbmFibGVfcG9ydHNbKl19IG9uIGRlZmF1bHQgZmlyZXdhbGxkIHpvbmUiCiAgICAjIHNoZWxsY2hlY2sgZGlzYWJsZT1TQzIwNjgKICAgIGZvciBwb3J0IGluICR7ZW5hYmxlX3BvcnRzW0BdfTsgZG8KICAgICAgICBsb2cgIkVuYWJsaW5nIHBvcnQgJHBvcnQgbm93IgogICAgICAgIGZpcmV3YWxsLWNtZCAiLS1hZGQtcG9ydD0kcG9ydCIKICAgIGRvbmUKCiAgICBmaXJld2FsbC1jbWQgLS1ydW50aW1lLXRvLXBlcm1hbmVudAp9CgojIHB1bGxfY29udGFpbmVyX2ltYWdlcwpwdWxsX2NvbnRhaW5lcl9pbWFnZXMoKSB7CiAgICBsb2cgInN0YXJ0aW5nIgoKICAgICMgVGhlIG1hbmFnZWQgaWRlbnRpdHkgdGhhdCB0aGUgVk0gcnVucyBhcyBvbmx5IGhhcyBhIHNpbmdsZSByb2xlYXNzaWdubWVudC4KICAgICMgVGhpcyByb2xlIGFzc2lnbm1lbnQgaXMgQUNSUHVsbCB3aGljaCBpcyBub3QgbmVjZXNzYXJpbHkgcHJlc2VudCBpbiB0aGUKICAgICMgc3Vic2NyaXB0aW9uIHdlJ3JlIGRlcGxveWluZyBpbnRvLiAgSWYgdGhlIGlkZW50aXR5IGRvZXMgbm90IGhhdmUgYW55CiAgICAjIHJvbGUgYXNzaWdubWVudHMgc2NvcGVkIG9uIHRoZSBzdWJzY3JpcHRpb24gd2UncmUgZGVwbG95aW5nIGludG8sIGl0IHdpbGwKICAgICMgbm90IHNob3cgb24gYXogbG9naW4gLWksIHdoaWNoIGlzIHdoeSB0aGUgYmVsb3cgbGluZSBpcyBjb21tZW50ZWQuCiAgICAjIGF6IGFjY291bnQgc2V0IC1zICIkU1VCU0NSSVBUSU9OSUQiCiAgICBheiBsb2dpbiAtaSAtLWFsbG93LW5vLXN1YnNjcmlwdGlvbnMKCiAgICAjIFN1cHByZXNzIGVtdWxhdGlvbiBvdXRwdXQgZm9yIHBvZG1hbiBpbnN0ZWFkIG9mIGRvY2tlciBmb3IgYXogYWNyIGNvbXBhdGFiaWxpdHkKICAgIG1rZGlyIC1wIC9ldGMvY29udGFpbmVycy8KICAgIG1rZGlyIC1wIC9yb290Ly5kb2NrZXIKICAgIHRvdWNoIC9ldGMvY29udGFpbmVycy9ub2RvY2tlcgoKCSMgVGhpcyBuYW1lIGlzIHVzZWQgaW4gdGhlIGNhc2UgdGhhdCBheiBhY3IgbG9naW4gc2VhcmNoZXMgZm9yIHRoaXMgaW4gaXQncyBlbnZpcm9ubWVudAogICAgbG9jYWwgLXIgUkVHSVNUUllfQVVUSF9GSUxFPSIvcm9vdC8uZG9ja2VyL2NvbmZpZy5qc29uIgogICAgCiAgICBsb2cgImxvZ2dpbmcgaW50byBwcm9kIGFjciIKICAgIGF6IGFjciBsb2dpbiAtLW5hbWUgIiQoc2VkIC1lICdzfC4qL3x8JyA8PDwiJEFDUlJFU09VUkNFSUQiKSIKCiAgICBNRE1JTUFHRT0iJHtSUElNQUdFJSUvKn0vJHtNRE1JTUFHRSMjKi99IgogICAgZG9ja2VyIHB1bGwgIiRNRE1JTUFHRSIKICAgIGRvY2tlciBwdWxsICIkUlBJTUFHRSIKICAgIGRvY2tlciBwdWxsICIkRkxVRU5UQklUSU1BR0UiCgogICAgYXogbG9nb3V0Cn0KCiMgY29uZmlndXJlX3N5c3RlbV9zZXJ2aWNlcyBjcmVhdGVzLCBjb25maWd1cmVzLCBhbmQgZW5hYmxlcyB0aGUgZm9sbG93aW5nIHN5c3RlbWQgc2VydmljZXMgYW5kIHRpbWVycwojIHNlcnZpY2VzCiMgICBmbHVlbnRiaXQKIyAgIG1kbQojICAgbWRzZAojICAgYXJwLXJwCiMgICBhcm8tZGJ0b2tlbgojICAgYXJvLW1vbml0b3IKIyAgIGFyby1wb3J0YWwKY29uZmlndXJlX3N5c3RlbV9zZXJ2aWNlcygpIHsKICAgIGNvbmZpZ3VyZV9zZXJ2aWNlX2ZsdWVudGJpdAogICAgY29uZmlndXJlX3NlcnZpY2VfbWRtCiAgICBjb25maWd1cmVfdGltZXJzX21kbV9tZHNkCiAgICBjb25maWd1cmVfc2VydmljZV9hcm9fcnAKICAgIGNvbmZpZ3VyZV9zZXJ2aWNlX2Fyb19kYnRva2VuCiAgICBjb25maWd1cmVfc2VydmljZV9hcm9fbW9uaXRvcgogICAgY29uZmlndXJlX3NlcnZpY2VfYXJvX3BvcnRhbAogICAgY29uZmlndXJlX3NlcnZpY2VfbWRzZAp9CgojIGVuYWJsZV9hcm9fc2VydmljZXMgZW5hYmxlcyBhbGwgc2VydmljZXMgcmVxdWlyZWQgZm9yIGFybyBycAplbmFibGVfYXJvX3NlcnZpY2VzKCkgewogICAgbG9nICJzdGFydGluZyIKCiAgICBsb2NhbCAtcmEgYXJvX3NlcnZpY2VzPSgKICAgICAgICAiYXJvLWRidG9rZW4iCiAgICAgICAgImFyby1tb25pdG9yIgogICAgICAgICJhcm8tcG9ydGFsIgogICAgICAgICJhcm8tcnAiCiAgICAgICAgImF1b21zIgogICAgICAgICJhenNlY2QiCiAgICAgICAgImF6c2VjbW9uZCIKICAgICAgICAibWRzZCIKICAgICAgICAibWRtIgogICAgICAgICJjaHJvbnlkIgogICAgICAgICJmbHVlbnRiaXQiCiAgICApCiAgICBsb2cgImVuYWJsaW5nIGFybyBzZXJ2aWNlcyAke2Fyb19zZXJ2aWNlc1sqXX0iCiAgICAjIHNoZWxsY2hlY2sgZGlzYWJsZT1TQzIwNjgKICAgIGZvciBzZXJ2aWNlIGluICR7YXJvX3NlcnZpY2VzW0BdfTsgZG8KICAgICAgICBsb2cgIkVuYWJsaW5nICRzZXJ2aWNlIG5vdyIKICAgICAgICBzeXN0ZW1jdGwgZW5hYmxlICIkc2VydmljZS5zZXJ2aWNlIgogICAgZG9uZQp9CgojIGNvbmZpZ3VyZV9zZXJ2aWNlX2ZsdWVudGJpdApjb25maWd1cmVfc2VydmljZV9mbHVlbnRiaXQoKSB7CiAgICBsb2cgInN0YXJ0aW5nIgogICAgbG9nICJjb25maWd1cmluZyBmbHVlbnRiaXQgc2VydmljZSIKCiAgICBta2RpciAtcCAvZXRjL2ZsdWVudGJpdC8KICAgIG1rZGlyIC1wIC92YXIvbGliL2ZsdWVudAoKICAgIGxvY2FsIC1yIGZsdWVudGJpdF9jb25mX2ZpbGVuYW1lPScvZXRjL2ZsdWVudGJpdC9mbHVlbnRiaXQuY29uZicKICAgIGxvY2FsIC1yIGZsdWVudGJpdF9jb25mX2ZpbGU9IltJTlBVVF0KTmFtZSBzeXN0ZW1kClRhZyBqb3VybmFsZApTeXN0ZW1kX0ZpbHRlciBfQ09NTT1hcm8KREIgL3Zhci9saWIvZmx1ZW50L2pvdXJuYWxkYgoKW0ZJTFRFUl0KCU5hbWUgbW9kaWZ5CglNYXRjaCBqb3VybmFsZAoJUmVtb3ZlX3dpbGRjYXJkIF8KCVJlbW92ZSBUSU1FU1RBTVAKCltGSUxURVJdCglOYW1lIHJld3JpdGVfdGFnCglNYXRjaCBqb3VybmFsZAoJUnVsZSAkTE9HS0lORCBhc3luY3FvcyBhc3luY3FvcyB0cnVlCgpbRklMVEVSXQoJTmFtZSBtb2RpZnkKCU1hdGNoIGFzeW5jcW9zCglSZW1vdmUgQ0xJRU5UX1BSSU5DSVBBTF9OQU1FCglSZW1vdmUgRklMRQoJUmVtb3ZlIENPTVBPTkVOVAoKW0ZJTFRFUl0KCU5hbWUgcmV3cml0ZV90YWcKCU1hdGNoIGpvdXJuYWxkCglSdWxlICRMT0dLSU5EIGlmeGF1ZGl0IGlmeGF1ZGl0IGZhbHNlCgpbT1VUUFVUXQoJTmFtZSBmb3J3YXJkCglNYXRjaCAqCglQb3J0IDI5MjMwIgoKICAgIHdyaXRlX2ZpbGUgZmx1ZW50Yml0X2NvbmZfZmlsZW5hbWUgZmx1ZW50Yml0X2NvbmZfZmlsZSB0cnVlCgogICAgbG9jYWwgLXIgc3lzY29uZmlnX2ZsdWVudGJpdF9maWxlbmFtZT0nL2V0Yy9zeXNjb25maWcvZmx1ZW50Yml0JwogICAgbG9jYWwgLXIgc3lzY29uZmlnX2ZsdWVudGJpdF9maWxlPSJGTFVFTlRCSVRJTUFHRT0kRkxVRU5UQklUSU1BR0UiCgogICAgd3JpdGVfZmlsZSBzeXNjb25maWdfZmx1ZW50Yml0X2ZpbGVuYW1lIHN5c2NvbmZpZ19mbHVlbnRiaXRfZmlsZSB0cnVlCgogICAgbG9jYWwgLXIgZmx1ZW50Yml0X3NlcnZpY2VfZmlsZW5hbWU9Jy9ldGMvc3lzdGVtZC9zeXN0ZW0vZmx1ZW50Yml0LnNlcnZpY2UnCgogICAgbG9jYWwgLXIgZmx1ZW50Yml0X3NlcnZpY2VfZmlsZT0iW1VuaXRdCkFmdGVyPW5ldHdvcmstb25saW5lLnRhcmdldApXYW50cz1uZXR3b3JrLW9ubGluZS50YXJnZXQKU3RhcnRMaW1pdEludGVydmFsU2VjPTAKCltTZXJ2aWNlXQpSZXN0YXJ0U2VjPTFzCkVudmlyb25tZW50RmlsZT0vZXRjL3N5c2NvbmZpZy9mbHVlbnRiaXQKRXhlY1N0YXJ0UHJlPS0vdXNyL2Jpbi9kb2NrZXIgcm0gLWYgJU4KRXhlY1N0YXJ0PS91c3IvYmluL2RvY2tlciBydW4gXAogIC0tc2VjdXJpdHktb3B0IGxhYmVsPWRpc2FibGUgXAogIC0tZW50cnlwb2ludCAvb3B0L3RkLWFnZW50LWJpdC9iaW4vdGQtYWdlbnQtYml0IFwKICAtLW5ldD1ob3N0IFwKICAtLWhvc3RuYW1lICVIIFwKICAtLW5hbWUgJU4gXAogIC0tcm0gXAogIC0tY2FwLWRyb3AgbmV0X3JhdyBcCiAgLXYgL2V0Yy9mbHVlbnRiaXQvZmx1ZW50Yml0LmNvbmY6L2V0Yy9mbHVlbnRiaXQvZmx1ZW50Yml0LmNvbmYgXAogIC12IC92YXIvbGliL2ZsdWVudDovdmFyL2xpYi9mbHVlbnQ6eiBcCiAgLXYgL3Zhci9sb2cvam91cm5hbDovdmFyL2xvZy9qb3VybmFsOnJvIFwKICAtdiAvZXRjL21hY2hpbmUtaWQ6L2V0Yy9tYWNoaW5lLWlkOnJvIFwKICAkRkxVRU5UQklUSU1BR0UgXAogIC1jIC9ldGMvZmx1ZW50Yml0L2ZsdWVudGJpdC5jb25mCgpFeGVjU3RvcD0vdXNyL2Jpbi9kb2NrZXIgc3RvcCAlTgpSZXN0YXJ0PWFsd2F5cwpSZXN0YXJ0U2VjPTUKU3RhcnRMaW1pdEludGVydmFsPTAKCltJbnN0YWxsXQpXYW50ZWRCeT1tdWx0aS11c2VyLnRhcmdldCIKCiAgICB3cml0ZV9maWxlIGZsdWVudGJpdF9jb25mX2ZpbGVuYW1lIGZsdWVudGJpdF9jb25mX2ZpbGUgdHJ1ZQp9CgojIGNvbmZpZ3VyZV9jZXJ0cwpjb25maWd1cmVfY2VydHMoKSB7CiAgICBsb2cgInN0YXJ0aW5nIgoKICAgIG1rZGlyIC9ldGMvYXJvLXJwCiAgICBiYXNlNjQgLWQgPDw8IiRBRE1JTkFQSUNBQlVORExFIiA+L2V0Yy9hcm8tcnAvYWRtaW4tY2EtYnVuZGxlLnBlbQogICAgaWYgW1sgLW4gIiRBUk1BUElDQUJVTkRMRSIgXV07IHRoZW4KICAgIGJhc2U2NCAtZCA8PDwiJEFSTUFQSUNBQlVORExFIiA+L2V0Yy9hcm8tcnAvYXJtLWNhLWJ1bmRsZS5wZW0KICAgIGZpCiAgICBjaG93biAtUiAxMDAwOjEwMDAgL2V0Yy9hcm8tcnAKCiAgICAjIHNldHRpbmcgTU9OSVRPUklOR19HQ1NfQVVUSF9JRF9UWVBFPUF1dGhLZXlWYXVsdCBzZWVtcyB0byBoYXZlIGNhdXNlZCBtZHNkIG5vdAogICAgIyB0byBob25vdXIgU1NMX0NFUlRfRklMRSBhbnkgbW9yZSwgaGVhdmVuIG9ubHkga25vd3Mgd2h5LgogICAgbWtkaXIgLXAgL3Vzci9saWIvc3NsL2NlcnRzCiAgICBjc3BsaXQgLWYgL3Vzci9saWIvc3NsL2NlcnRzL2NlcnQtIC1iICUwM2QucGVtIC9ldGMvcGtpL3Rscy9jZXJ0cy9jYS1idW5kbGUuY3J0IC9eJC8xICJ7Kn0iID4vZGV2L251bGwKICAgIGNfcmVoYXNoIC91c3IvbGliL3NzbC9jZXJ0cwoKIyB3ZSBsZWF2ZSBjbGllbnRJZCBibGFuayBhcyBsb25nIGFzIG9ubHkgMSBtYW5hZ2VkIGlkZW50aXR5IGFzc2lnbmVkIHRvIHZtc3MKIyBpZiB3ZSBoYXZlIG1vcmUgdGhhbiAxLCB3ZSB3aWxsIG5lZWQgdG8gcG9wdWxhdGUgd2l0aCBjbGllbnRJZCB1c2VkIGZvciBvZmYtbm9kZSBzY2FubmluZwogICAgbG9jYWwgLXIgbm9kZXNjYW5fYWdlbnRfZmlsZW5hbWU9Ii9ldGMvZGVmYXVsdC92c2Etbm9kZXNjYW4tYWdlbnQuY29uZmlnIgogICAgbG9jYWwgLXIgbm9kZXNjYW5fYWdlbnRfZmlsZT0iewogICAgXCJOaWNlXCI6IDE5LAogICAgXCJUaW1lb3V0XCI6IDEwODAwLAogICAgXCJDbGllbnRJZFwiOiBcIlwiLAogICAgXCJUZW5hbnRJZFwiOiAkQVpVUkVTRUNQQUNLVlNBVEVOQU5USUQsCiAgICBcIlF1YWx5c1N0b3JlQmFzZVVybFwiOiAkQVpVUkVTRUNQQUNLUVVBTFlTVVJMLAogICAgXCJQcm9jZXNzVGltZW91dFwiOiAzMDAsCiAgICBcIkNvbW1hbmREZWxheVwiOiAwCiAgfSIKCiAgICB3cml0ZV9maWxlIG5vZGVzY2FuX2FnZW50X2ZpbGVuYW1lIG5vZGVzY2FuX2FnZW50X2ZpbGUgdHJ1ZQp9CgojIGNvbmZpZ3VyZV9zZXJ2aWNlX21kbQpjb25maWd1cmVfc2VydmljZV9tZG0oKSB7CiAgICBsb2cgInN0YXJ0aW5nIgogICAgbG9nICJjb25maWd1cmluZyBtZG0gc2VydmljZSIKCiAgICBsb2NhbCAtciBzeXNjb25maWdfbWRtX2ZpbGVuYW1lPSIvZXRjL3N5c2NvbmZpZy9tZG0iCiAgICBsb2NhbCAtciBzeXNjb25maWdfbWRtX2ZpbGU9Ik1ETUZST05URU5EVVJMPSckTURNRlJPTlRFTkRVUkwnCk1ETUlNQUdFPSckTURNSU1BR0UnCk1ETVNPVVJDRUVOVklST05NRU5UPSckTE9DQVRJT04nCk1ETVNPVVJDRVJPTEU9cnAKTURNU09VUkNFUk9MRUlOU1RBTkNFPVwiJChob3N0bmFtZSlcIiIKCiAgICB3cml0ZV9maWxlIHN5c2NvbmZpZ19tZG1fZmlsZW5hbWUgc3lzY29uZmlnX21kbV9maWxlIHRydWUKCiAgICBta2RpciAtcCAvdmFyL2V0dwogICAgbG9jYWwgLXIgbWRtX3NlcnZpY2VfZmlsZW5hbWU9Ii9ldGMvc3lzdGVtZC9zeXN0ZW0vbWRtLnNlcnZpY2UiCiAgICBsb2NhbCAtciBtZG1fc2VydmljZV9maWxlPSJbVW5pdF0KQWZ0ZXI9bmV0d29yay1vbmxpbmUudGFyZ2V0CldhbnRzPW5ldHdvcmstb25saW5lLnRhcmdldAoKW1NlcnZpY2VdCkVudmlyb25tZW50RmlsZT0vZXRjL3N5c2NvbmZpZy9tZG0KRXhlY1N0YXJ0UHJlPS0vdXNyL2Jpbi9kb2NrZXIgcm0gLWYgJU4KRXhlY1N0YXJ0PS91c3IvYmluL2RvY2tlciBydW4gXAogIC0tZW50cnlwb2ludCAvdXNyL3NiaW4vTWV0cmljc0V4dGVuc2lvbiBcCiAgLS1ob3N0bmFtZSAlSCBcCiAgLS1uYW1lICVOIFwKICAtLXJtIFwKICAtLWNhcC1kcm9wIG5ldF9yYXcgXAogIC1tIDJnIFwKICAtdiAvZXRjL21kbS5wZW06L2V0Yy9tZG0ucGVtIFwKICAtdiAvdmFyL2V0dzovdmFyL2V0dzp6IFwKICAkTURNSU1BR0UgXAogIC1DZXJ0RmlsZSAvZXRjL21kbS5wZW0gXAogIC1Gcm9udEVuZFVybCAkTURNRlJPTlRFTkRVUkwgXAogIC1Mb2dnZXIgQ29uc29sZSBcCiAgLUxvZ0xldmVsIFdhcm5pbmcgXAogIC1Qcml2YXRlS2V5RmlsZSAvZXRjL21kbS5wZW0gXAogIC1Tb3VyY2VFbnZpcm9ubWVudCAkTURNU09VUkNFRU5WSVJPTk1FTlQgXAogIC1Tb3VyY2VSb2xlICRNRE1TT1VSQ0VST0xFIFwKICAtU291cmNlUm9sZUluc3RhbmNlICRNRE1TT1VSQ0VST0xFSU5TVEFOQ0UKRXhlY1N0b3A9L3Vzci9iaW4vZG9ja2VyIHN0b3AgJU4KUmVzdGFydD1hbHdheXMKUmVzdGFydFNlYz0xClN0YXJ0TGltaXRJbnRlcnZhbD0wCgpbSW5zdGFsbF0KV2FudGVkQnk9bXVsdGktdXNlci50YXJnZXQiCgogICAgd3JpdGVfZmlsZSBtZG1fc2VydmljZV9maWxlbmFtZSBtZG1fc2VydmljZV9maWxlIHRydWUKfQoKIyBjb25maWd1cmVfdGltZXJzX21kbV9tZHNkCmNvbmZpZ3VyZV90aW1lcnNfbWRtX21kc2QoKSB7CiAgICBsb2cgInN0YXJ0aW5nIgoKICAgIGZvciB2YXIgaW4gIm1kc2QiICJtZG0iOyBkbwogICAgICAgIGxvY2FsIGRvd25sb2FkX2NyZWRzX3NlcnZpY2VfZmlsZW5hbWU9Ii9ldGMvc3lzdGVtZC9zeXN0ZW0vZG93bmxvYWQtJHZhci1jcmVkZW50aWFscy5zZXJ2aWNlIgogICAgICAgIGxvY2FsIGRvd25sb2FkX2NyZWRzX3NlcnZpY2VfZmlsZT0iW1VuaXRdCkRlc2NyaXB0aW9uPVBlcmlvZGljICR2YXIgY3JlZGVudGlhbHMgcmVmcmVzaAoKW1NlcnZpY2VdClR5cGU9b25lc2hvdApFeGVjU3RhcnQ9L3Vzci9sb2NhbC9iaW4vZG93bmxvYWQtY3JlZGVudGlhbHMuc2ggJHZhciIKCiAgICAgICAgd3JpdGVfZmlsZSBkb3dubG9hZF9jcmVkc19zZXJ2aWNlX2ZpbGVuYW1lIGRvd25sb2FkX2NyZWRzX3NlcnZpY2VfZmlsZSB0cnVlCgogICAgICAgIGxvY2FsIGRvd25sb2FkX2NyZWRzX3RpbWVyX2ZpbGVuYW1lPSIvZXRjL3N5c3RlbWQvc3lzdGVtL2Rvd25sb2FkLSR2YXItY3JlZGVudGlhbHMudGltZXIiCiAgICAgICAgbG9jYWwgZG93bmxvYWRfY3JlZHNfdGltZXJfZmlsZT0iW1VuaXRdCkRlc2NyaXB0aW9uPVBlcmlvZGljICR2YXIgY3JlZGVudGlhbHMgcmVmcmVzaApBZnRlcj1uZXR3b3JrLW9ubGluZS50YXJnZXQKV2FudHM9bmV0d29yay1vbmxpbmUudGFyZ2V0CgpbVGltZXJdCk9uQm9vdFNlYz0wbWluCk9uQ2FsZW5kYXI9MC8xMjowMDowMApBY2N1cmFjeVNlYz01cwoKW0luc3RhbGxdCldhbnRlZEJ5PXRpbWVycy50YXJnZXQiCgogICAgICAgIHdyaXRlX2ZpbGUgZG93bmxvYWRfY3JlZHNfdGltZXJfZmlsZW5hbWUgZG93bmxvYWRfY3JlZHNfdGltZXJfZmlsZSB0cnVlCiAgICBkb25lCgogICAgbG9jYWwgLXIgZG93bmxvYWRfY3JlZHNfc2NyaXB0X2ZpbGVuYW1lPSIvdXNyL2xvY2FsL2Jpbi9kb3dubG9hZC1jcmVkZW50aWFscy5zaCIKICAgIGxvY2FsIC1yIGRvd25sb2FkX2NyZWRzX3NjcmlwdF9maWxlPSIjIS9iaW4vYmFzaApzZXQgLWV1CgpDT01QT05FTlQ9XCQxCmVjaG8gXCJEb3dubG9hZCBcJENPTVBPTkVOVCBjcmVkZW50aWFsc1wiCgpURU1QX0RJUj1cIlwkKG1rdGVtcCAtZClcIgpleHBvcnQgQVpVUkVfQ09ORklHX0RJUj1cIlwkKG1rdGVtcCAtZClcIgoKZWNobyBcIkxvZ2dpbmcgaW50byBBenVyZS4uLlwiClJFVFJJRVM9Mwp3aGlsZSBbWyBcJFJFVFJJRVMgLWd0IDAgXV07IGRvCiAgICBpZiBheiBsb2dpbiAtaSAtLWFsbG93LW5vLXN1YnNjcmlwdGlvbnMKICAgIHRoZW4KICAgICAgICBlY2hvIFwiYXogbG9naW4gc3VjY2Vzc2Z1bFwiCiAgICAgICAgYnJlYWsKICAgIGVsc2UKICAgICAgICBlY2hvIFwiYXogbG9naW4gZmFpbGVkLiBSZXRyeWluZy4uLlwiCiAgICAgICAgbGV0IFJFVFJJRVMtPTEKICAgICAgICBzbGVlcCA1CiAgICBmaQpkb25lCgp0cmFwIFwiY2xlYW51cFwiIEVYSVQKCmNsZWFudXAoKSB7CiAgYXogbG9nb3V0CiAgW1sgXCRURU1QX0RJUiA9fiAvdG1wLy4rIF1dICYmIHJtIC1yZiBcJFRFTVBfRElSCiAgW1sgXCRBWlVSRV9DT05GSUdfRElSID1+IC90bXAvLisgXV0gJiYgcm0gLXJmIFwkQVpVUkVfQ09ORklHX0RJUgp9CgppZiBbWyBcJENPTVBPTkVOVCA9IFwibWRtXCIgXV07IHRoZW4KICBDVVJSRU5UX0NFUlRfRklMRT1cIi9ldGMvbWRtLnBlbVwiCmVsaWYgW1sgXCRDT01QT05FTlRcID0gXCJtZHNkXCIgXV07IHRoZW4KICBDVVJSRU5UX0NFUlRfRklMRT1cIi92YXIvbGliL3dhYWdlbnQvTWljcm9zb2Z0LkF6dXJlLktleVZhdWx0LlN0b3JlL21kc2QucGVtXCIKZWxzZQogIGVjaG8gSW52YWxpZCB1c2FnZSAmJiBleGl0IDEKZmkKClNFQ1JFVF9OQU1FPVwicnAtXCR7Q09NUE9ORU5UfVwiCk5FV19DRVJUX0ZJTEU9XCJcJFRFTVBfRElSL1wkQ09NUE9ORU5ULnBlbVwiCmZvciBhdHRlbXB0IGluIHsxLi41fTsgZG8KICBheiBrZXl2YXVsdCBcCiAgICBzZWNyZXQgXAogICAgZG93bmxvYWQgXAogICAgLS1maWxlIFwiXCRORVdfQ0VSVF9GSUxFXCIgXAogICAgLS1pZCBcImh0dHBzOi8vJEtFWVZBVUxUUFJFRklYLXN2Yy4kS0VZVkFVTFRETlNTVUZGSVgvc2VjcmV0cy9cJFNFQ1JFVF9OQU1FXCIgXAogICAgJiYgYnJlYWsKICBpZiBbWyBcJGF0dGVtcHQgLWx0IDUgXV07IHRoZW4gc2xlZXAgMTA7IGVsc2UgZXhpdCAxOyBmaQpkb25lCgppZiBbIC1mIFwkTkVXX0NFUlRfRklMRSBdOyB0aGVuCiAgaWYgW1sgXCRDT01QT05FTlQgPSBcIm1kc2RcIiBdXTsgdGhlbgogICAgY2hvd24gc3lzbG9nOnN5c2xvZyBcJE5FV19DRVJUX0ZJTEUKICBlbHNlCiAgICBzZWQgLWkgLW5lICcxLC9FTkQgQ0VSVElGSUNBVEUvIHAnIFwkTkVXX0NFUlRfRklMRQogIGZpCgogIG5ld19jZXJ0X3NuPVwiXCQob3BlbnNzbCB4NTA5IC1pbiBcIlwkTkVXX0NFUlRfRklMRVwiIC1ub291dCAtc2VyaWFsIHwgYXdrIC1GPSAne3ByaW50IFwkMn0nKVwiCiAgY3VycmVudF9jZXJ0X3NuPVwiXCQob3BlbnNzbCB4NTA5IC1pbiBcIlwkQ1VSUkVOVF9DRVJUX0ZJTEVcIiAtbm9vdXQgLXNlcmlhbCB8IGF3ayAtRj0gJ3twcmludCBcJDJ9JylcIgogIGlmIFtbICEgLXogXCRuZXdfY2VydF9zbiBdXSAmJiBbWyBcJG5ld19jZXJ0X3NuICE9IFwiXCRjdXJyZW50X2NlcnRfc25cIiBdXTsgdGhlbgogICAgZWNobyB1cGRhdGluZyBjZXJ0aWZpY2F0ZSBmb3IgXCRDT01QT05FTlQKICAgIGNobW9kIDA2MDAgXCRORVdfQ0VSVF9GSUxFCiAgICBtdiBcJE5FV19DRVJUX0ZJTEUgXCRDVVJSRU5UX0NFUlRfRklMRQogIGZpCmVsc2UKICBlY2hvIEZhaWxlZCB0byByZWZyZXNoIGNlcnRpZmljYXRlIGZvciBcJENPTVBPTkVOVCAmJiBleGl0IDEKZmkiCgogICAgd3JpdGVfZmlsZSBkb3dubG9hZF9jcmVkc19zY3JpcHRfZmlsZW5hbWUgZG93bmxvYWRfY3JlZHNfc2NyaXB0X2ZpbGUgdHJ1ZQoKICAgIGNobW9kIHUreCAvdXNyL2xvY2FsL2Jpbi9kb3dubG9hZC1jcmVkZW50aWFscy5zaAoKICAgIHN5c3RlbWN0bCBlbmFibGUgZG93bmxvYWQtbWRzZC1jcmVkZW50aWFscy50aW1lcgogICAgc3lzdGVtY3RsIGVuYWJsZSBkb3dubG9hZC1tZG0tY3JlZGVudGlhbHMudGltZXIKCiAgICAvdXNyL2xvY2FsL2Jpbi9kb3dubG9hZC1jcmVkZW50aWFscy5zaCBtZHNkCiAgICAvdXNyL2xvY2FsL2Jpbi9kb3dubG9hZC1jcmVkZW50aWFscy5zaCBtZG0KCiAgICBsb2NhbCAtciBNRFNEQ0VSVElGSUNBVEVTQU49IiQob3BlbnNzbCB4NTA5IC1pbiAvdmFyL2xpYi93YWFnZW50L01pY3Jvc29mdC5BenVyZS5LZXlWYXVsdC5TdG9yZS9tZHNkLnBlbSAtbm9vdXQgLXN1YmplY3QgfCBzZWQgLWUgJ3MvLipDTiA9IC8vJykiCiAgICBsb2NhbCAtciB3YXRjaF9tZG1fY3JlZHNfc2VydmljZV9maWxlbmFtZT0iL2V0Yy9zeXN0ZW1kL3N5c3RlbS93YXRjaC1tZG0tY3JlZGVudGlhbHMuc2VydmljZSIKICAgIGxvY2FsIC1yIHdhdGNoX21kbV9jcmVkc19zZXJ2aWNlX2ZpbGU9IltVbml0XQpEZXNjcmlwdGlvbj1XYXRjaCBmb3IgY2hhbmdlcyBpbiBtZG0ucGVtIGFuZCByZXN0YXJ0cyB0aGUgbWRtIHNlcnZpY2UKCltTZXJ2aWNlXQpUeXBlPW9uZXNob3QKRXhlY1N0YXJ0PS91c3IvYmluL3N5c3RlbWN0bCByZXN0YXJ0IG1kbS5zZXJ2aWNlCgpbSW5zdGFsbF0KV2FudGVkQnk9bXVsdGktdXNlci50YXJnZXQiCgogICAgd3JpdGVfZmlsZSB3YXRjaF9tZG1fY3JlZHNfc2VydmljZV9maWxlbmFtZSB3YXRjaF9tZG1fY3JlZHNfc2VydmljZV9maWxlIHRydWUKCiAgICBsb2NhbCAtciB3YXRjaF9tZG1fY3JlZHNfcGF0aF9maWxlbmFtZT0nL2V0Yy9zeXN0ZW1kL3N5c3RlbS93YXRjaC1tZG0tY3JlZGVudGlhbHMucGF0aCcKICAgIGxvY2FsIC1yIHdhdGNoX21kbV9jcmVkc19wYXRoX2ZpbGU9J1tQYXRoXQpQYXRoTW9kaWZpZWQ9L2V0Yy9tZG0ucGVtCgpbSW5zdGFsbF0KV2FudGVkQnk9bXVsdGktdXNlci50YXJnZXQnCgogICAgd3JpdGVfZmlsZSB3YXRjaF9tZG1fY3JlZHNfcGF0aF9maWxlbmFtZSB3YXRjaF9tZG1fY3JlZHNfcGF0aF9maWxlIHRydWUKCiAgICBsb2NhbCAtciB3YXRjaF9tZG1fY3JlZHM9J3dhdGNoLW1kbS1jcmVkZW50aWFscy5wYXRoJwogICAgc3lzdGVtY3RsIGVuYWJsZSAiJHdhdGNoX21kbV9jcmVkcyIgfHwgYWJvcnQgImZhaWxlZCB0byBlbmFibGUgJHdhdGNoX21kbV9jcmVkcyIKICAgIHN5c3RlbWN0bCBzdGFydCAiJHdhdGNoX21kbV9jcmVkcyIgfHwgYWJvcnQgImZhaWxlZCB0byBzdGFydCAkd2F0Y2hfbWRtX2NyZWRzIgp9CgojIGNvbmZpZ3VyZV9zZXJ2aWNlX2Fyb19ycApjb25maWd1cmVfc2VydmljZV9hcm9fcnAoKSB7CiAgICBsb2cgInN0YXJ0aW5nIgoKICAgIGxvY2FsIC1yIGFyb19ycF9jb25mX2ZpbGVuYW1lPScvZXRjL3N5c2NvbmZpZy9hcm8tcnAnCiAgICBsb2NhbCAtciBhcm9fcnBfY29uZl9maWxlPSJBQ1JfUkVTT1VSQ0VfSUQ9JyRBQ1JSRVNPVVJDRUlEJwpBRE1JTl9BUElfQ0xJRU5UX0NFUlRfQ09NTU9OX05BTUU9JyRBRE1JTkFQSUNMSUVOVENFUlRDT01NT05OQU1FJwpBUk1fQVBJX0NMSUVOVF9DRVJUX0NPTU1PTl9OQU1FPSckQVJNQVBJQ0xJRU5UQ0VSVENPTU1PTk5BTUUnCkFaVVJFX0FSTV9DTElFTlRfSUQ9JyRBUk1DTElFTlRJRCcKQVpVUkVfRlBfQ0xJRU5UX0lEPSckRlBDTElFTlRJRCcKQVpVUkVfRlBfU0VSVklDRV9QUklOQ0lQQUxfSUQ9JyRGUFNFUlZJQ0VQUklOQ0lQQUxJRCcKQklMTElOR19FMkVfU1RPUkFHRV9BQ0NPVU5UX0lEPSckQklMTElOR0UyRVNUT1JBR0VBQ0NPVU5USUQnCkNMVVNURVJfTURNX0FDQ09VTlQ9JyRDTFVTVEVSTURNQUNDT1VOVCcKQ0xVU1RFUl9NRE1fTkFNRVNQQUNFPVJQCkNMVVNURVJfTURTRF9BQ0NPVU5UPSckQ0xVU1RFUk1EU0RBQ0NPVU5UJwpDTFVTVEVSX01EU0RfQ09ORklHX1ZFUlNJT049JyRDTFVTVEVSTURTRENPTkZJR1ZFUlNJT04nCkNMVVNURVJfTURTRF9OQU1FU1BBQ0U9JyRDTFVTVEVSTURTRE5BTUVTUEFDRScKREFUQUJBU0VfQUNDT1VOVF9OQU1FPSckREFUQUJBU0VBQ0NPVU5UTkFNRScKRE9NQUlOX05BTUU9JyRMT0NBVElPTi4kQ0xVU1RFUlBBUkVOVERPTUFJTk5BTUUnCkdBVEVXQVlfRE9NQUlOUz0nJEdBVEVXQVlET01BSU5TJwpHQVRFV0FZX1JFU09VUkNFR1JPVVA9JyRHQVRFV0FZUkVTT1VSQ0VHUk9VUE5BTUUnCktFWVZBVUxUX1BSRUZJWD0nJEtFWVZBVUxUUFJFRklYJwpNRE1fQUNDT1VOVD0nJFJQTURNQUNDT1VOVCcKTURNX05BTUVTUEFDRT1SUApNRFNEX0VOVklST05NRU5UPSckTURTREVOVklST05NRU5UJwpSUF9GRUFUVVJFUz0nJFJQRkVBVFVSRVMnClJQSU1BR0U9JyRSUElNQUdFJwpBUk9fSU5TVEFMTF9WSUFfSElWRT0nJENMVVNURVJTSU5TVEFMTFZJQUhJVkUnCkFST19ISVZFX0RFRkFVTFRfSU5TVEFMTEVSX1BVTExTUEVDPSckQ0xVU1RFUkRFRkFVTFRJTlNUQUxMRVJQVUxMU1BFQycKQVJPX0FET1BUX0JZX0hJVkU9JyRDTFVTVEVSU0FET1BUQllISVZFJwpVU0VfQ0hFQ0tBQ0NFU1M9JyRVU0VDSEVDS0FDQ0VTUyciCgogICAgd3JpdGVfZmlsZSBhcm9fcnBfY29uZl9maWxlbmFtZSBhcm9fcnBfY29uZl9maWxlIHRydWUKCiAgICBsb2NhbCAtciBhcm9fcnBfc2VydmljZV9maWxlbmFtZT0nL2V0Yy9zeXN0ZW1kL3N5c3RlbS9hcm8tcnAuc2VydmljZScKICAgIGxvY2FsIC1yIGFyb19ycF9zZXJ2aWNlX2ZpbGU9IltVbml0XQpBZnRlcj1uZXR3b3JrLW9ubGluZS50YXJnZXQKV2FudHM9bmV0d29yay1vbmxpbmUudGFyZ2V0CgpbU2VydmljZV0KRW52aXJvbm1lbnRGaWxlPS9ldGMvc3lzY29uZmlnL2Fyby1ycApFeGVjU3RhcnRQcmU9LS91c3IvYmluL2RvY2tlciBybSAtZiAlTgpFeGVjU3RhcnQ9L3Vzci9iaW4vZG9ja2VyIHJ1biBcCiAgLS1ob3N0bmFtZSAlSCBcCiAgLS1uYW1lICVOIFwKICAtLXJtIFwKICAtLWNhcC1kcm9wIG5ldF9yYXcgXAogIC1lIEFDUl9SRVNPVVJDRV9JRCBcCiAgLWUgQURNSU5fQVBJX0NMSUVOVF9DRVJUX0NPTU1PTl9OQU1FIFwKICAtZSBBUk1fQVBJX0NMSUVOVF9DRVJUX0NPTU1PTl9OQU1FIFwKICAtZSBBWlVSRV9BUk1fQ0xJRU5UX0lEIFwKICAtZSBBWlVSRV9GUF9DTElFTlRfSUQgXAogIC1lIEJJTExJTkdfRTJFX1NUT1JBR0VfQUNDT1VOVF9JRCBcCiAgLWUgQ0xVU1RFUl9NRE1fQUNDT1VOVCBcCiAgLWUgQ0xVU1RFUl9NRE1fTkFNRVNQQUNFIFwKICAtZSBDTFVTVEVSX01EU0RfQUNDT1VOVCBcCiAgLWUgQ0xVU1RFUl9NRFNEX0NPTkZJR19WRVJTSU9OIFwKICAtZSBDTFVTVEVSX01EU0RfTkFNRVNQQUNFIFwKICAtZSBEQVRBQkFTRV9BQ0NPVU5UX05BTUUgXAogIC1lIERPTUFJTl9OQU1FIFwKICAtZSBHQVRFV0FZX0RPTUFJTlMgXAogIC1lIEdBVEVXQVlfUkVTT1VSQ0VHUk9VUCBcCiAgLWUgS0VZVkFVTFRfUFJFRklYIFwKICAtZSBNRE1fQUNDT1VOVCBcCiAgLWUgTURNX05BTUVTUEFDRSBcCiAgLWUgTURTRF9FTlZJUk9OTUVOVCBcCiAgLWUgUlBfRkVBVFVSRVMgXAogIC1lIEFST19JTlNUQUxMX1ZJQV9ISVZFIFwKICAtZSBBUk9fSElWRV9ERUZBVUxUX0lOU1RBTExFUl9QVUxMU1BFQyBcCiAgLWUgQVJPX0FET1BUX0JZX0hJVkUgXAogIC1lIFVTRV9DSEVDS0FDQ0VTUyBcCiAgLW0gMmcgXAogIC1wIDQ0Mzo4NDQzIFwKICAtdiAvZXRjL2Fyby1ycDovZXRjL2Fyby1ycCBcCiAgLXYgL3J1bi9zeXN0ZW1kL2pvdXJuYWw6L3J1bi9zeXN0ZW1kL2pvdXJuYWwgXAogIC12IC92YXIvZXR3Oi92YXIvZXR3OnogXAogICRSUElNQUdFIFwKICBycApFeGVjU3RvcD0vdXNyL2Jpbi9kb2NrZXIgc3RvcCAtdCAzNjAwICVOClRpbWVvdXRTdG9wU2VjPTM2MDAKUmVzdGFydD1hbHdheXMKUmVzdGFydFNlYz0xClN0YXJ0TGltaXRJbnRlcnZhbD0wCgpbSW5zdGFsbF0KV2FudGVkQnk9bXVsdGktdXNlci50YXJnZXQiCgogICAgd3JpdGVfZmlsZSBhcm9fcnBfc2VydmljZV9maWxlbmFtZSBhcm9fcnBfY29uZl9maWxlIHRydWUKfQoKIyBjb25maWd1cmVfc2VydmljZV9hcm9fZGJ0b2tlbgpjb25maWd1cmVfc2VydmljZV9hcm9fZGJ0b2tlbigpIHsKICAgIGxvZyAic3RhcnRpbmciCgogICAgbG9jYWwgLXIgYXJvX2RidG9rZW5fc2VydmljZV9jb25mX2ZpbGVuYW1lPScvZXRjL3N5c2NvbmZpZy9hcm8tZGJ0b2tlbicKICAgIGxvY2FsIC1yIGFyb19kYnRva2VuX3NlcnZpY2VfY29uZl9maWxlPSJEQVRBQkFTRV9BQ0NPVU5UX05BTUU9JyREQVRBQkFTRUFDQ09VTlROQU1FJwpBWlVSRV9EQlRPS0VOX0NMSUVOVF9JRD0nJERCVE9LRU5DTElFTlRJRCcKQVpVUkVfR0FURVdBWV9TRVJWSUNFX1BSSU5DSVBBTF9JRD0nJEdBVEVXQVlTRVJWSUNFUFJJTkNJUEFMSUQnCktFWVZBVUxUX1BSRUZJWD0nJEtFWVZBVUxUUFJFRklYJwpNRE1fQUNDT1VOVD0nJFJQTURNQUNDT1VOVCcKTURNX05BTUVTUEFDRT1EQlRva2VuClJQSU1BR0U9JyRSUElNQUdFJyIKCiAgICB3cml0ZV9maWxlIGFyb19kYnRva2VuX3NlcnZpY2VfY29uZl9maWxlbmFtZSBhcm9fZGJ0b2tlbl9zZXJ2aWNlX2NvbmZfZmlsZSB0cnVlCgogICAgbG9jYWwgLXIgYXJvX2RidG9rZW5fc2VydmljZV9maWxlbmFtZT0nL2V0Yy9zeXN0ZW1kL3N5c3RlbS9hcm8tZGJ0b2tlbi5zZXJ2aWNlJwogICAgbG9jYWwgLXIgYXJvX2RidG9rZW5fc2VydmljZV9maWxlPSJbVW5pdF0KQWZ0ZXI9bmV0d29yay1vbmxpbmUudGFyZ2V0CldhbnRzPW5ldHdvcmstb25saW5lLnRhcmdldAoKW1NlcnZpY2VdCkVudmlyb25tZW50RmlsZT0vZXRjL3N5c2NvbmZpZy9hcm8tZGJ0b2tlbgpFeGVjU3RhcnRQcmU9LS91c3IvYmluL2RvY2tlciBybSAtZiAlTgpFeGVjU3RhcnQ9L3Vzci9iaW4vZG9ja2VyIHJ1biBcCiAgLS1ob3N0bmFtZSAlSCBcCiAgLS1uYW1lICVOIFwKICAtLXJtIFwKICAtLWNhcC1kcm9wIG5ldF9yYXcgXAogIC1lIEFaVVJFX0dBVEVXQVlfU0VSVklDRV9QUklOQ0lQQUxfSUQgXAogIC1lIERBVEFCQVNFX0FDQ09VTlRfTkFNRSBcCiAgLWUgQVpVUkVfREJUT0tFTl9DTElFTlRfSUQgXAogIC1lIEtFWVZBVUxUX1BSRUZJWCBcCiAgLWUgTURNX0FDQ09VTlQgXAogIC1lIE1ETV9OQU1FU1BBQ0UgXAogIC1tIDJnIFwKICAtcCA0NDU6ODQ0NSBcCiAgLXYgL3J1bi9zeXN0ZW1kL2pvdXJuYWw6L3J1bi9zeXN0ZW1kL2pvdXJuYWwgXAogIC12IC92YXIvZXR3Oi92YXIvZXR3OnogXAogICRSUElNQUdFIFwKICBkYnRva2VuCkV4ZWNTdG9wPS91c3IvYmluL2RvY2tlciBzdG9wIC10IDM2MDAgJU4KVGltZW91dFN0b3BTZWM9MzYwMApSZXN0YXJ0PWFsd2F5cwpSZXN0YXJ0U2VjPTEKU3RhcnRMaW1pdEludGVydmFsPTAKCltJbnN0YWxsXQpXYW50ZWRCeT1tdWx0aS11c2VyLnRhcmdldCIKCiAgICB3cml0ZV9maWxlIGFyb19kYnRva2VuX3NlcnZpY2VfZmlsZW5hbWUgYXJvX2RidG9rZW5fc2VydmljZV9maWxlIHRydWUKfQoKIyBjb25maWd1cmVfc2VydmljZV9hcm9fbW9uaXRvcgpjb25maWd1cmVfc2VydmljZV9hcm9fbW9uaXRvcigpIHsKICAgIGxvZyAic3RhcnRpbmciCiAgICBsb2cgImNvbmZpZ3VyaW5nIGFyby1tb25pdG9yIHNlcnZpY2UiCgogICAgIyBET01BSU5fTkFNRSwgQ0xVU1RFUl9NRFNEX0FDQ09VTlQsIENMVVNURVJfTURTRF9DT05GSUdfVkVSU0lPTiwgR0FURVdBWV9ET01BSU5TLCBHQVRFV0FZX1JFU09VUkNFR1JPVVAsIE1EU0RfRU5WSVJPTk1FTlQgQ0xVU1RFUl9NRFNEX05BTUVTUEFDRQogICAgIyBhcmUgbm90IHVzZWQsIGJ1dCBjYW4ndCBlYXNpbHkgYmUgcmVmYWN0b3JlZCBvdXQuIFNob3VsZCBiZSByZXZpc2l0ZWQgaW4gdGhlIGZ1dHVyZS4KICAgIGxvY2FsIC1yIGFyb19tb25pdG9yX3NlcnZpY2VfY29uZl9maWxlbmFtZT0nL2V0Yy9zeXNjb25maWcvYXJvLW1vbml0b3InCiAgICBsb2NhbCAtciBhcm9fbW9uaXRvcl9zZXJ2aWNlX2NvbmZfZmlsZT0iQVpVUkVfRlBfQ0xJRU5UX0lEPSckRlBDTElFTlRJRCcKRE9NQUlOX05BTUU9JyRMT0NBVElPTi4kQ0xVU1RFUlBBUkVOVERPTUFJTk5BTUUnCkNMVVNURVJfTURTRF9BQ0NPVU5UPSckQ0xVU1RFUk1EU0RBQ0NPVU5UJwpDTFVTVEVSX01EU0RfQ09ORklHX1ZFUlNJT049JyRDTFVTVEVSTURTRENPTkZJR1ZFUlNJT04nCkdBVEVXQVlfRE9NQUlOUz0nJEdBVEVXQVlET01BSU5TJwpHQVRFV0FZX1JFU09VUkNFR1JPVVA9JyRHQVRFV0FZUkVTT1VSQ0VHUk9VUE5BTUUnCk1EU0RfRU5WSVJPTk1FTlQ9JyRNRFNERU5WSVJPTk1FTlQnCkNMVVNURVJfTURTRF9OQU1FU1BBQ0U9JyRDTFVTVEVSTURTRE5BTUVTUEFDRScKQ0xVU1RFUl9NRE1fQUNDT1VOVD0nJENMVVNURVJNRE1BQ0NPVU5UJwpDTFVTVEVSX01ETV9OQU1FU1BBQ0U9QkJNCkRBVEFCQVNFX0FDQ09VTlRfTkFNRT0nJERBVEFCQVNFQUNDT1VOVE5BTUUnCktFWVZBVUxUX1BSRUZJWD0nJEtFWVZBVUxUUFJFRklYJwpNRE1fQUNDT1VOVD0nJFJQTURNQUNDT1VOVCcKTURNX05BTUVTUEFDRT1CQk0KUlBJTUFHRT0nJFJQSU1BR0UnIgoKICAgIHdyaXRlX2ZpbGUgYXJvX21vbml0b3Jfc2VydmljZV9jb25mX2ZpbGVuYW1lIGFyb19tb25pdG9yX3NlcnZpY2VfY29uZl9maWxlIHRydWUKCiAgICBsb2NhbCAtciBhcm9fbW9uaXRvcl9zZXJ2aWNlX2ZpbGVuYW1lPScvZXRjL3N5c3RlbWQvc3lzdGVtL2Fyby1tb25pdG9yLnNlcnZpY2UnCiAgICBsb2NhbCAtciBhcm9fbW9uaXRvcl9zZXJ2aWNlX2ZpbGU9IltVbml0XQpBZnRlcj1uZXR3b3JrLW9ubGluZS50YXJnZXQKV2FudHM9bmV0d29yay1vbmxpbmUudGFyZ2V0CgpbU2VydmljZV0KRW52aXJvbm1lbnRGaWxlPS9ldGMvc3lzY29uZmlnL2Fyby1tb25pdG9yCkV4ZWNTdGFydFByZT0tL3Vzci9iaW4vZG9ja2VyIHJtIC1mICVOCkV4ZWNTdGFydD0vdXNyL2Jpbi9kb2NrZXIgcnVuIFwKICAtLWhvc3RuYW1lICVIIFwKICAtLW5hbWUgJU4gXAogIC0tcm0gXAogIC0tY2FwLWRyb3AgbmV0X3JhdyBcCiAgLWUgQVpVUkVfRlBfQ0xJRU5UX0lEIFwKICAtZSBET01BSU5fTkFNRSBcCiAgLWUgQ0xVU1RFUl9NRFNEX0FDQ09VTlQgXAogIC1lIENMVVNURVJfTURTRF9DT05GSUdfVkVSU0lPTiBcCiAgLWUgR0FURVdBWV9ET01BSU5TIFwKICAtZSBHQVRFV0FZX1JFU09VUkNFR1JPVVAgXAogIC1lIE1EU0RfRU5WSVJPTk1FTlQgXAogIC1lIENMVVNURVJfTURTRF9OQU1FU1BBQ0UgXAogIC1lIENMVVNURVJfTURNX0FDQ09VTlQgXAogIC1lIENMVVNURVJfTURNX05BTUVTUEFDRSBcCiAgLWUgREFUQUJBU0VfQUNDT1VOVF9OQU1FIFwKICAtZSBLRVlWQVVMVF9QUkVGSVggXAogIC1lIE1ETV9BQ0NPVU5UIFwKICAtZSBNRE1fTkFNRVNQQUNFIFwKICAtbSAyLjVnIFwKICAtdiAvcnVuL3N5c3RlbWQvam91cm5hbDovcnVuL3N5c3RlbWQvam91cm5hbCBcCiAgLXYgL3Zhci9ldHc6L3Zhci9ldHc6eiBcCiAgJFJQSU1BR0UgXAogIG1vbml0b3IKUmVzdGFydD1hbHdheXMKUmVzdGFydFNlYz0xClN0YXJ0TGltaXRJbnRlcnZhbD0wCgpbSW5zdGFsbF0KV2FudGVkQnk9bXVsdGktdXNlci50YXJnZXQiCgogICAgd3JpdGVfZmlsZSBhcm9fbW9uaXRvcl9zZXJ2aWNlX2ZpbGVuYW1lIGFyb19tb25pdG9yX3NlcnZpY2VfZmlsZSB0cnVlCn0KCiMgY29uZmlndXJlX3NlcnZpY2VfYXJvX3BvcnRhbApjb25maWd1cmVfc2VydmljZV9hcm9fcG9ydGFsKCkgewogICAgbG9nICJzdGFydGluZyIKCiAgICBsb2NhbCAtciBhcm9fcG9ydGFsX3NlcnZpY2VfY29uZl9maWxlbmFtZT0nL2V0Yy9zeXNjb25maWcvYXJvLXBvcnRhbCcKICAgIGxvY2FsIC1yIGFyb19wb3J0YWxfc2VydmljZV9jb25mX2ZpbGU9IkFaVVJFX1BPUlRBTF9BQ0NFU1NfR1JPVVBfSURTPSckUE9SVEFMQUNDRVNTR1JPVVBJRFMnCkFaVVJFX1BPUlRBTF9DTElFTlRfSUQ9JyRQT1JUQUxDTElFTlRJRCcKQVpVUkVfUE9SVEFMX0VMRVZBVEVEX0dST1VQX0lEUz0nJFBPUlRBTEVMRVZBVEVER1JPVVBJRFMnCkRBVEFCQVNFX0FDQ09VTlRfTkFNRT0nJERBVEFCQVNFQUNDT1VOVE5BTUUnCktFWVZBVUxUX1BSRUZJWD0nJEtFWVZBVUxUUFJFRklYJwpNRE1fQUNDT1VOVD0nJFJQTURNQUNDT1VOVCcKTURNX05BTUVTUEFDRT1Qb3J0YWwKUE9SVEFMX0hPU1ROQU1FPSckTE9DQVRJT04uYWRtaW4uJFJQUEFSRU5URE9NQUlOTkFNRScKUlBJTUFHRT0nJFJQSU1BR0UnIgoKICAgIHdyaXRlX2ZpbGUgYXJvX3BvcnRhbF9zZXJ2aWNlX2NvbmZfZmlsZW5hbWUgYXJvX3BvcnRhbF9zZXJ2aWNlX2NvbmZfZmlsZSB0cnVlCgogICAgbG9jYWwgLXIgYXJvX3BvcnRhbF9zZXJ2aWNlX2ZpbGVuYW1lPScvZXRjL3N5c3RlbWQvc3lzdGVtL2Fyby1wb3J0YWwuc2VydmljZScKICAgIGxvY2FsIC1yIGFyb19wb3J0YWxfc2VydmljZV9maWxlPSJbVW5pdF0KQWZ0ZXI9bmV0d29yay1vbmxpbmUudGFyZ2V0CldhbnRzPW5ldHdvcmstb25saW5lLnRhcmdldApTdGFydExpbWl0SW50ZXJ2YWw9MAoKW1NlcnZpY2VdCkVudmlyb25tZW50RmlsZT0vZXRjL3N5c2NvbmZpZy9hcm8tcG9ydGFsCkV4ZWNTdGFydFByZT0tL3Vzci9iaW4vZG9ja2VyIHJtIC1mICVOCkV4ZWNTdGFydD0vdXNyL2Jpbi9kb2NrZXIgcnVuIFwKICAtLWhvc3RuYW1lICVIIFwKICAtLW5hbWUgJU4gXAogIC0tcm0gXAogIC0tY2FwLWRyb3AgbmV0X3JhdyBcCiAgLWUgQVpVUkVfUE9SVEFMX0FDQ0VTU19HUk9VUF9JRFMgXAogIC1lIEFaVVJFX1BPUlRBTF9DTElFTlRfSUQgXAogIC1lIEFaVVJFX1BPUlRBTF9FTEVWQVRFRF9HUk9VUF9JRFMgXAogIC1lIERBVEFCQVNFX0FDQ09VTlRfTkFNRSBcCiAgLWUgS0VZVkFVTFRfUFJFRklYIFwKICAtZSBNRE1fQUNDT1VOVCBcCiAgLWUgTURNX05BTUVTUEFDRSBcCiAgLWUgUE9SVEFMX0hPU1ROQU1FIFwKICAtbSAyZyBcCiAgLXAgNDQ0Ojg0NDQgXAogIC1wIDIyMjI6MjIyMiBcCiAgLXYgL3J1bi9zeXN0ZW1kL2pvdXJuYWw6L3J1bi9zeXN0ZW1kL2pvdXJuYWwgXAogIC12IC92YXIvZXR3Oi92YXIvZXR3OnogXAogICRSUElNQUdFIFwKICBwb3J0YWwKUmVzdGFydD1hbHdheXMKUmVzdGFydFNlYz0xCgpbSW5zdGFsbF0KV2FudGVkQnk9bXVsdGktdXNlci50YXJnZXQiCgogICAgd3JpdGVfZmlsZSBhcm9fcG9ydGFsX3NlcnZpY2VfY29uZl9maWxlbmFtZSBhcm9fcG9ydGFsX3NlcnZpY2VfY29uZl9maWxlIHRydWUKfQoKIyBjb25maWd1cmVfc2VydmljZV9tZHNkCmNvbmZpZ3VyZV9zZXJ2aWNlX21kc2QoKSB7CiAgICBsb2cgInN0YXJ0aW5nIgoKICAgIGxvY2FsIC1yIG1kc2Rfc2VydmljZV9kaXI9Ii9ldGMvc3lzdGVtZC9zeXN0ZW0vbWRzZC5zZXJ2aWNlLmQiCiAgICBta2RpciAiJG1kc2Rfc2VydmljZV9kaXIiCgogICAgbG9jYWwgLXIgbWRzZF9vdmVycmlkZV9jb25mX2ZpbGVuYW1lPSIkbWRzZF9zZXJ2aWNlX2Rpci9vdmVycmlkZS5jb25mIgogICAgbG9jYWwgLXIgbWRzZF9vdmVycmlkZV9jb25mX2ZpbGU9IltVbml0XQpBZnRlcj1uZXR3b3JrLW9ubGluZS50YXJnZXQiCgogICAgd3JpdGVfZmlsZSBtZHNkX292ZXJyaWRlX2NvbmZfZmlsZW5hbWUgbWRzZF9vdmVycmlkZV9jb25mX2ZpbGUgdHJ1ZQoKICAgIGxvY2FsIC1yIGRlZmF1bHRfbWRzZF9maWxlbmFtZT0iL2V0Yy9kZWZhdWx0L21kc2QiCiAgICBsb2NhbCAtciBkZWZhdWx0X21kc2RfZmlsZT0iTURTRF9ST0xFX1BSRUZJWD0vdmFyL3J1bi9tZHNkL2RlZmF1bHQKTURTRF9PUFRJT05TPVwiLUEgLWQgLXIgXCRNRFNEX1JPTEVfUFJFRklYXCIKCmV4cG9ydCBNT05JVE9SSU5HX0dDU19FTlZJUk9OTUVOVD0nJE1EU0RFTlZJUk9OTUVOVCcKZXhwb3J0IE1PTklUT1JJTkdfR0NTX0FDQ09VTlQ9JyRSUE1EU0RBQ0NPVU5UJwpleHBvcnQgTU9OSVRPUklOR19HQ1NfUkVHSU9OPSckTE9DQVRJT04nCmV4cG9ydCBNT05JVE9SSU5HX0dDU19BVVRIX0lEX1RZUEU9QXV0aEtleVZhdWx0CmV4cG9ydCBNT05JVE9SSU5HX0dDU19BVVRIX0lEPSckTURTRENFUlRJRklDQVRFU0FOJwpleHBvcnQgTU9OSVRPUklOR19HQ1NfTkFNRVNQQUNFPSckUlBNRFNETkFNRVNQQUNFJwpleHBvcnQgTU9OSVRPUklOR19DT05GSUdfVkVSU0lPTj0nJFJQTURTRENPTkZJR1ZFUlNJT04nCmV4cG9ydCBNT05JVE9SSU5HX1VTRV9HRU5FVkFfQ09ORklHX1NFUlZJQ0U9dHJ1ZQoKZXhwb3J0IE1PTklUT1JJTkdfVEVOQU5UPSckTE9DQVRJT04nCmV4cG9ydCBNT05JVE9SSU5HX1JPTEU9cnAKZXhwb3J0IE1PTklUT1JJTkdfUk9MRV9JTlNUQU5DRT1cIiQoaG9zdG5hbWUpXCIKCmV4cG9ydCBNRFNEX01TR1BBQ0tfU09SVF9DT0xVTU5TPTFcIiIKCiAgICB3cml0ZV9maWxlIGRlZmF1bHRfbWRzZF9maWxlbmFtZSBkZWZhdWx0X21kc2RfZmlsZSB0cnVlCgp9CgojIHJ1bl9henNlY2RfY29uZmlnX3NjYW4KcnVuX2F6c2VjZF9jb25maWdfc2NhbigpIHsKICAgIGxvZyAic3RhcnRpbmciCgogICAgbG9jYWwgLWFyIGNvbmZpZ3M9KAogICAgICAgICJiYXNlbGluZSIKICAgICAgICAiY2xhbWF2IgogICAgICAgICJzb2Z0d2FyZSIKICAgICkKCiAgICBsb2cgIlNjYW5uaW5nIGNvbmZpZ3VyYXRpb24gZmlsZXMgJHtjb25maWdzWypdfSIKICAgICMgc2hlbGxjaGVjayBkaXNhYmxlPVNDMjA2OAogICAgZm9yIHNjYW4gaW4gJHtjb25maWdzW0BdfTsgZG8KICAgICAgICBsb2cgIlNjYW5uaW5nIGNvbmZpZyBmaWxlICRzY2FuIG5vdyIKICAgICAgICAvdXNyL2xvY2FsL2Jpbi9henNlY2QgY29uZmlnIC1zICIkc2NhbiIgLWQgUDFECiAgICBkb25lCn0KCiMgd3JpdGVfZmlsZQojIEFyZ3MKIyAxKSBmaWxlbmFtZSAtIHN0cmluZwojIDIpIGZpbGVfY29udGVudHMgLSBzdHJpbmcKIyAzKSBjbG9iYmVyIC0gYm9vbGVhbjsgb3B0aW9uYWwgLSBkZWZhdWx0cyB0byBmYWxzZQp3cml0ZV9maWxlKCkgewogICAgbG9jYWwgLW4gZmlsZW5hbWU9IiQxIgogICAgbG9jYWwgLW4gZmlsZV9jb250ZW50cz0iJDIiCiAgICBsb2NhbCAtciBjbG9iYmVyPSIkezM6LWZhbHNlfSIKCiAgICBpZiAkY2xvYmJlcjsgdGhlbgogICAgICAgIGxvZyAiT3ZlcndyaXRpbmcgZmlsZSAkZmlsZW5hbWUiCiAgICAgICAgZWNobyAiJGZpbGVfY29udGVudHMiID4gIiRmaWxlbmFtZSIKICAgIGVsc2UKICAgICAgICBsb2cgIkFwcGVuZGluZyB0byAkZmlsZW5hbWUiCiAgICAgICAgZWNobyAiJGZpbGVfY29udGVudHMiID4+ICIkZmlsZW5hbWUiCiAgICBmaQp9CgojIHJlYm9vdF92bSByZXN0b3JlcyBhbGwgc2VsaW51eCBmaWxlIGNvbnRleHRzLCB3YWl0cyAzMCBzZWNvbmRzIHRoZW4gcmVib290cwpyZWJvb3Rfdm0oKSB7CiAgICBsb2cgInN0YXJ0aW5nIgoKICAgIGNvbmZpZ3VyZV9zZWxpbnV4ICJ0cnVlIgogICAgKHNsZWVwIDMwICYmIGxvZyAicmVib290aW5nIHZtIG5vdyI7IHJlYm9vdCkgJgp9CgojIGxvZyBpcyBhIHdyYXBwZXIgZm9yIGVjaG8gdGhhdCBpbmNsdWRlcyB0aGUgZnVuY3Rpb24gbmFtZQpsb2coKSB7CiAgICBsb2NhbCAtciBtc2c9IiR7MTotImxvZyBtZXNzYWdlIGlzIGVtcHR5In0iCiAgICBsb2NhbCAtciBzdGFja19sZXZlbD0iJHsyOi0xfSIKICAgIGVjaG8gIiR7RlVOQ05BTUVbJHtzdGFja19sZXZlbH1dfTogJHttc2d9Igp9CgojIGFib3J0IGlzIGEgd3JhcHBlciBmb3IgbG9nIHRoYXQgZXhpdHMgd2l0aCBhbiBlcnJvciBjb2RlCmFib3J0KCkgewogICAgbG9jYWwgLXJpIG9yaWdpbl9zdGFja2xldmVsPTIKICAgIGxvZyAiJHsxfSIgIiRvcmlnaW5fc3RhY2tsZXZlbCIKICAgIGxvZyAiRXhpdGluZyIKICAgIGV4aXQgMQp9CgpleHBvcnQgQVpVUkVfQ0xPVURfTkFNRT0iJHtBWlVSRUNMT1VETkFNRTo/IkZhaWxlZCB0byBjYXJyeSBvdmVyIHZhcmlhYmxlcyJ9IgoKbWFpbiAiJEAiCg==')))]" } } } diff --git a/pkg/deploy/generator/scripts/devProxyVMSS.sh b/pkg/deploy/generator/scripts/devProxyVMSS.sh index bdbb8fe35b3..2b405881bce 100644 --- a/pkg/deploy/generator/scripts/devProxyVMSS.sh +++ b/pkg/deploy/generator/scripts/devProxyVMSS.sh @@ -1,53 +1,331 @@ -#Adding retry logic to yum commands in order to avoid stalling out on resource locks -echo "running RHUI fix" -for attempt in {1..5}; do - yum update -y --disablerepo='*' --enablerepo='rhui-microsoft-azure*' && break - if [[ ${attempt} -lt 5 ]]; then sleep 10; else exit 1; fi -done - -echo "running yum update" -for attempt in {1..5}; do - yum -y -x WALinuxAgent -x WALinuxAgent-udev update --allowerasing && break - if [[ ${attempt} -lt 5 ]]; then sleep 10; else exit 1; fi -done - -echo "installing podman-docker" -for attempt in {1..5}; do - yum -y install podman-docker && break - if [[ ${attempt} -lt 5 ]]; then sleep 10; else exit 1; fi -done - -firewall-cmd --add-port=443/tcp --permanent - -mkdir /root/.docker -cat >/root/.docker/config.json </etc/proxy/proxy.crt -base64 -d <<<"$PROXYKEY" >/etc/proxy/proxy.key -base64 -d <<<"$PROXYCLIENTCERT" >/etc/proxy/proxy-client.crt -chown -R 1000:1000 /etc/proxy -chmod 0600 /etc/proxy/proxy.key + local -ra aro_services=( + proxy + ) + log "enabling aro services ${aro_services[*]}" + # shellcheck disable=SC2068 + for service in ${aro_services[@]}; do + log "Enabling $service now" + systemctl enable "$service.service" + done +} -cat >/etc/sysconfig/proxy </etc/systemd/system/proxy.service <<'EOF' -[Unit] + base64 -d <<<"$PROXYCERT" >/etc/proxy/proxy.crt + base64 -d <<<"$PROXYKEY" >/etc/proxy/proxy.key + base64 -d <<<"$PROXYCLIENTCERT" >/etc/proxy/proxy-client.crt + chown -R 1000:1000 /etc/proxy + chmod 0600 /etc/proxy/proxy.key +} + +configure_service_proxy() { + local -r sysconfig_proxy_filename='/etc/sysconfig/proxy' + local -r sysconfig_proxy_file="PROXY_IMAGE='$PROXYIMAGE'" + + write_file sysconfig_proxy_filename sysconfig_proxy_file true + + local -r proxy_service_filename='/etc/systemd/system/proxy.service' + local -r proxy_service_file="[Unit] After=network-online.target Wants=network-online.target @@ -61,34 +339,66 @@ RestartSec=1 StartLimitInterval=0 [Install] -WantedBy=multi-user.target -EOF +WantedBy=multi-user.target" -systemctl enable proxy.service + local -r cron_weekly_pull_image_filename='/etc/cron.weekly/pull-image' + local -r cron_weekly_pull_image_file="#!/bin/bash +docker pull $PROXYIMAGE +systemctl restart proxy.service" + + write_file cron_weekly_pull_image_filename cron_weekly_pull_image_file true + chmod +x "$cron_weekly_pull_image_filename" -cat >/etc/cron.weekly/pull-image <<'EOF' -#!/bin/bash + local -r cron_daily_restart_proxy_filename='/etc/cron.daily/restart-proxy' + local -r cron_daily_restart_proxy_file="#!/bin/bash +systemctl restart proxy.service" + + write_file cron_daily_restart_proxy_filename cron_daily_restart_proxy_file + chmod +x "$cron_daily_restart_proxy_filename" +} -docker pull $PROXYIMAGE -systemctl restart proxy.service -EOF -chmod +x /etc/cron.weekly/pull-image +# write_file +# Args +# 1) filename - string +# 2) file_contents - string +# 3) clobber - boolean; optional - defaults to false +write_file() { + local -n filename="$1" + local -n file_contents="$2" + local -r clobber="${3:-false}" -cat >/etc/cron.weekly/yumupdate <<'EOF' -#!/bin/bash + if $clobber; then + log "Overwriting file $filename" + echo "$file_contents" > "$filename" + else + log "Appending to $filename" + echo "$file_contents" >> "$filename" + fi +} -yum update -y -EOF -chmod +x /etc/cron.weekly/yumupdate +# reboot_vm restores all selinux file contexts, waits 30 seconds then reboots +reboot_vm() { + log "starting" -cat >/etc/cron.daily/restart-proxy <<'EOF' -#!/bin/bash + configure_selinux "true" + (sleep 30 && log "rebooting vm now"; reboot) & +} + +# log is a wrapper for echo that includes the function name +log() { + local -r msg="${1:-"log message is empty"}" + local -r stack_level="${2:-1}" + echo "${FUNCNAME[${stack_level}]}: ${msg}" +} + +# abort is a wrapper for log that exits with an error code +abort() { + local -ri origin_stacklevel=2 + log "${1}" "$origin_stacklevel" + log "Exiting" + exit 1 +} -systemctl restart proxy.service -EOF -chmod +x /etc/cron.daily/restart-proxy +export AZURE_CLOUD_NAME="${AZURECLOUDNAME:?"Failed to carry over variables"}" -( - sleep 30 - reboot -) & +main "$@" From ff7c3721e2ce402cbc70b03eb839f3c0156213b9 Mon Sep 17 00:00:00 2001 From: Steven Fairchild Date: Wed, 17 Apr 2024 15:19:10 -0400 Subject: [PATCH 16/38] WIP start moving common functions into common.sh for reuse --- pkg/deploy/generator/scripts/common.sh | 116 ++++++++++++ pkg/deploy/generator/scripts/rpVMSS.sh | 234 +++++++------------------ 2 files changed, 184 insertions(+), 166 deletions(-) create mode 100644 pkg/deploy/generator/scripts/common.sh diff --git a/pkg/deploy/generator/scripts/common.sh b/pkg/deploy/generator/scripts/common.sh new file mode 100644 index 00000000000..9064da4782a --- /dev/null +++ b/pkg/deploy/generator/scripts/common.sh @@ -0,0 +1,116 @@ +#!/bin/bash +# This file is intended to be sourced by bootstrapping scripts for commonly used functions + +# retry Adding retry logic to yum commands in order to avoid stalling out on resource locks +retry() { + local -n cmd_retry="$1" + local -n wait_time="$2" + + for attempt in {1..5}; do + log "attempt #${attempt} - ${FUNCNAME[2]}" + ${cmd_retry[@]} & + + wait $! && break + if [[ ${attempt} -lt 5 ]]; then + sleep "$wait_time" + else + abort "attempt #${attempt} - Failed to update packages" + fi + done +} + + +# We need to configure PasswordAuthentication to yes in order for the VMSS Access JIT to work +configure_sshd() { + log "starting" + local sshd_config="/etc/ssh/sshd_config" + + log "Editing $sshd_config to allow password authentication" + sed -i 's/PasswordAuthentication no/PasswordAuthentication yes/g' "$sshd_config" + + systemctl reload sshd.service || abort "sshd failed to reload" +} + +# dnf_update_pkgs +dnf_update_pkgs() { + local -n excludes="$1" + log "starting" + + local -ra cmd=( + dnf + -y + ${excludes[@]} + update + --allowerasing + ) + + log "Updating all packages excluding ${excludes[*]}" + retry cmd "$2" +} + +# rpm_import_keys +rpm_import_keys() { + local -n keys="$1" + log "starting" + + + # shellcheck disable=SC2068 + for key in ${keys[@]}; do + if [ ${#keys[@]} -eq 0 ]; then + break + fi + local -a cmd=( + rpm + --import + -v + "$key" + ) + + log "attempt #$attempt - importing rpm repository key $key" + retry cmd "$2" && unset key + done +} + +# configure_selinux +configure_selinux() { + log "starting" + + local -r relabel="${1:-false}" + + already_defined_ignore_error="File context for /var/log/journal(/.*)? already defined" + semanage fcontext -a -t var_log_t "/var/log/journal(/.*)?" || log "$already_defined_ignore_error" + chcon -R system_u:object_r:var_log_t:s0 /var/opt/microsoft/linuxmonagent + + if "$relabel"; then + restorecon -RF /var/log/* || log "$already_defined_ignore_error" + fi +} + +# configure_firewalld_rules +configure_firewalld_rules() { + local -n ports="$1" + log "starting" + + # https://access.redhat.com/security/cve/cve-2020-13401 + local -r prefix="/etc/sysctl.d" + local -r disable_accept_ra_conf_filename="$prefix/02-disable-accept-ra.conf" + local -r disable_accept_ra_conf_file="net.ipv6.conf.all.accept_ra=0" + + write_file disable_accept_ra_conf_filename disable_accept_ra_conf_file true + + local -r disable_core_filename="$prefix/01-disable-core.conf" + local -r disable_core_file="kernel.core_pattern = |/bin/true + " + write_file disable_core_filename disable_core_file true + + sysctl --system + + log "Enabling ports ${enable_ports[*]} on default firewalld zone" + # shellcheck disable=SC2068 + for port in ${ports[@]}; do + log "Enabling port $port now" + firewall-cmd "--add-port=$port" + done + + firewall-cmd --runtime-to-permanent +} \ No newline at end of file diff --git a/pkg/deploy/generator/scripts/rpVMSS.sh b/pkg/deploy/generator/scripts/rpVMSS.sh index 3c00da1185c..26c0055b35c 100644 --- a/pkg/deploy/generator/scripts/rpVMSS.sh +++ b/pkg/deploy/generator/scripts/rpVMSS.sh @@ -8,11 +8,53 @@ if [ "${DEBUG:-false}" == true ]; then fi main() { + # transaction attempt retry time in seconds + local -ri retry_wait_time=60 + + # shellcheck source=common.sh + source common.sh + parse_run_options "$@" configure_sshd - configure_and_install_dnf_pkgs_repos + configure_rpm_repos retry_wait_time + + local -ar exclude_pkgs=( + "-x WALinuxAgent" + "-x WALinuxAgent-udev" + ) + + dnf_update_pkgs exclude_pkgs retry_wait_time + + local -ra rpm_keys=( + https://dl.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-8 + https://packages.microsoft.com/keys/microsoft.asc + ) + + rpm_import_keys rpm_keys retry_wait_time + + local -ra repo_rpm_pkgs=( + https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm + ) + + local -ra install_pkgs=( + clamav + azsec-clamav + azsec-monitor + azure-cli + azure-mdsd + azure-security + podman + podman-docker + openssl-perl + # hack - we are installing python3 on hosts due to an issue with Azure Linux Extensions https://github.com/Azure/azure-linux-extensions/pull/1505 + python3 + ) + + dnf_install_pkgs repo_rpm_pkgs retry_wait_time + dnf_install_pkgs install_pkgs retry_wait_time + configure_disk_partitions configure_logrotate configure_selinux @@ -20,8 +62,22 @@ main() { mkdir -p /var/log/journal mkdir -p /var/lib/waagent/Microsoft.Azure.KeyVault.Store - configure_firewalld_rules - pull_container_images + local -ra enable_ports=( + "443/tcp" + "444/tcp" + "445/tcp" + "2222/tcp" + ) + configure_firewalld_rules enable_ports + + MDMIMAGE="${RPIMAGE%%/*}/${MDMIMAGE##*/}" + local -ra images=( + "$MDMIMAGE" + "$RPIMAGE" + "$FLUENTBITIMAGE" + ) + + pull_container_images images configure_system_services reboot_vm } @@ -100,59 +156,11 @@ parse_run_options() { exit 0 } -# We need to configure PasswordAuthentication to yes in order for the VMSS Access JIT to work -configure_sshd() { +configure_rpm_repos() { log "starting" - log "setting ssh password authentication" - sed -i 's/PasswordAuthentication no/PasswordAuthentication yes/g' /etc/ssh/sshd_config - systemctl reload sshd.service - systemctl is-active --quiet sshd || abort "sshd failed to reload" -} - -# configure_and_install_dnf_pkgs_repos -configure_and_install_dnf_pkgs_repos() { - log "starting" - - # transaction attempt retry time in seconds - local -ri retry_wait_time=60 - configure_rhui_repo retry_wait_time - create_azure_rpm_repos retry_wait_time - - local -ar exclude_pkgs=( - "-x WALinuxAgent" - "-x WALinuxAgent-udev" - ) - - dnf_update_pkgs exclude_pkgs retry_wait_time - - local -ra rpm_keys=( - https://dl.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-8 - https://packages.microsoft.com/keys/microsoft.asc - ) - - rpm_import_keys rpm_keys retry_wait_time - - local -ra repo_rpm_pkgs=( - https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm - ) - - local -ra install_pkgs=( - clamav - azsec-clamav - azsec-monitor - azure-cli - azure-mdsd - azure-security - podman - podman-docker - openssl-perl - # hack - we are installing python3 on hosts due to an issue with Azure Linux Extensions https://github.com/Azure/azure-linux-extensions/pull/1505 - python3 - ) - - dnf_install_pkgs repo_rpm_pkgs retry_wait_time - dnf_install_pkgs install_pkgs retry_wait_time + configure_rhui_repo "$1" + create_azure_rpm_repos "$1" } # configure_rhui_repo @@ -171,41 +179,6 @@ configure_rhui_repo() { retry cmd "$1" } -# retry Adding retry logic to yum commands in order to avoid stalling out on resource locks -retry() { - local -n cmd_retry="$1" - local -n wait_time="$2" - - for attempt in {1..5}; do - log "attempt #${attempt} - ${FUNCNAME[2]}" - ${cmd_retry[@]} & - - wait $! && break - if [[ ${attempt} -lt 5 ]]; then - sleep "$wait_time" - else - abort "attempt #${attempt} - Failed to update packages" - fi - done -} - -# dnf_update_pkgs -dnf_update_pkgs() { - local -n excludes="$1" - log "starting" - - local -ra cmd=( - dnf - -y - ${excludes[@]} - update - --allowerasing - ) - - log "Updating all packages" - retry cmd "$2" -} - # dnf_install_pkgs dnf_install_pkgs() { local -n pkgs="$1" @@ -222,29 +195,6 @@ dnf_install_pkgs() { retry cmd "$2" } -# rpm_import_keys -rpm_import_keys() { - local -n keys="$1" - log "starting" - - - # shellcheck disable=SC2068 - for key in ${keys[@]}; do - if [ ${#keys[@]} -eq 0 ]; then - break - fi - local -a cmd=( - rpm - --import - -v - "$key" - ) - - log "attempt #$attempt - importing rpm repository key $key" - retry cmd "$2" && unset key - done -} - # configure_disk_partitions configure_disk_partitions() { log "starting" @@ -329,58 +279,9 @@ gpgcheck=no' write_file azure_repo_filename azure_repo_file true } -# configure_selinux -configure_selinux() { - log "starting" - - local -r relabel="${1:-false}" - - already_defined_ignore_error="File context for /var/log/journal(/.*)? already defined" - semanage fcontext -a -t var_log_t "/var/log/journal(/.*)?" || log "$already_defined_ignore_error" - chcon -R system_u:object_r:var_log_t:s0 /var/opt/microsoft/linuxmonagent - - if "$relabel"; then - restorecon -RF /var/log/* || log "$already_defined_ignore_error" - fi -} - -# configure_firewalld_rules -configure_firewalld_rules() { - log "starting" - - # https://access.redhat.com/security/cve/cve-2020-13401 - local -r prefix="/etc/sysctl.d" - local -r disable_accept_ra_conf_filename="$prefix/02-disable-accept-ra.conf" - local -r disable_accept_ra_conf_file="net.ipv6.conf.all.accept_ra=0" - - write_file disable_accept_ra_conf_filename disable_accept_ra_conf_file true - - local -r disable_core_filename="$prefix/01-disable-core.conf" - local -r disable_core_file="kernel.core_pattern = |/bin/true - " - write_file disable_core_filename disable_core_file true - - sysctl --system - - local -ra enable_ports=( - "443/tcp" - "444/tcp" - "445/tcp" - "2222/tcp" - ) - - log "Enabling ports ${enable_ports[*]} on default firewalld zone" - # shellcheck disable=SC2068 - for port in ${enable_ports[@]}; do - log "Enabling port $port now" - firewall-cmd "--add-port=$port" - done - - firewall-cmd --runtime-to-permanent -} - # pull_container_images pull_container_images() { + local -n pull_images="$1" log "starting" # The managed identity that the VM runs as only has a single roleassignment. @@ -402,10 +303,11 @@ pull_container_images() { log "logging into prod acr" az acr login --name "$(sed -e 's|.*/||' <<<"$ACRRESOURCEID")" - MDMIMAGE="${RPIMAGE%%/*}/${MDMIMAGE##*/}" - docker pull "$MDMIMAGE" - docker pull "$RPIMAGE" - docker pull "$FLUENTBITIMAGE" + # shellcheck disable=SC2068 + for i in ${pull_images[@]}; do + log "Pulling image $i now" + podman pull "$i" + done az logout } From 9dd98cb3a1419b7d2855c2a70924aa03392773f7 Mon Sep 17 00:00:00 2001 From: Steven Fairchild Date: Wed, 17 Apr 2024 15:21:41 -0400 Subject: [PATCH 17/38] WIP Move log rotate configuration to common.sh Need to allow addition of drop in files as well for gatewayVMSS.sh --- pkg/deploy/generator/scripts/common.sh | 44 +++++++++++++++++++++++++- pkg/deploy/generator/scripts/rpVMSS.sh | 42 ------------------------ 2 files changed, 43 insertions(+), 43 deletions(-) diff --git a/pkg/deploy/generator/scripts/common.sh b/pkg/deploy/generator/scripts/common.sh index 9064da4782a..25b249fee42 100644 --- a/pkg/deploy/generator/scripts/common.sh +++ b/pkg/deploy/generator/scripts/common.sh @@ -113,4 +113,46 @@ configure_firewalld_rules() { done firewall-cmd --runtime-to-permanent -} \ No newline at end of file +} + +# configure_logrotate clobbers /etc/logrotate.conf +configure_logrotate() { + log "starting" + + local -r logrotate_conf_filename='/etc/logrotate.conf' + local -r logrotate_conf_file='# see "man logrotate" for details +# rotate log files weekly +weekly + +# keep 2 weeks worth of backlogs +rotate 2 + +# create new (empty) log files after rotating old ones +create + +# use date as a suffix of the rotated file +dateext + +# uncomment this if you want your log files compressed +compress + +# RPM packages drop log rotation information into this directory +include /etc/logrotate.d + +# no packages own wtmp and btmp -- we will rotate them here +/var/log/wtmp { + monthly + create 0664 root utmp + minsize 1M + rotate 1 +} + +/var/log/btmp { + missingok + monthly + create 0600 root utmp + rotate 1 +}' + + write_file logrotate_conf_filename logrotate_conf_file true +} diff --git a/pkg/deploy/generator/scripts/rpVMSS.sh b/pkg/deploy/generator/scripts/rpVMSS.sh index 26c0055b35c..e74da4d3fc9 100644 --- a/pkg/deploy/generator/scripts/rpVMSS.sh +++ b/pkg/deploy/generator/scripts/rpVMSS.sh @@ -217,48 +217,6 @@ configure_disk_partitions() { xfs_growfs /var } -# configure_logrotate clobbers /etc/logrotate.conf -configure_logrotate() { - log "starting" - - local -r logrotate_conf_filename='/etc/logrotate.conf' - local -r logrotate_conf_file='# see "man logrotate" for details -# rotate log files weekly -weekly - -# keep 2 weeks worth of backlogs -rotate 2 - -# create new (empty) log files after rotating old ones -create - -# use date as a suffix of the rotated file -dateext - -# uncomment this if you want your log files compressed -compress - -# RPM packages drop log rotation information into this directory -include /etc/logrotate.d - -# no packages own wtmp and btmp -- we will rotate them here -/var/log/wtmp { - monthly - create 0664 root utmp - minsize 1M - rotate 1 -} - -/var/log/btmp { - missingok - monthly - create 0600 root utmp - rotate 1 -}' - - write_file logrotate_conf_filename logrotate_conf_file true -} - # create_azure_rpm_repos creates /etc/yum.repos.d/azure.repo repository file create_azure_rpm_repos() { log "starting" From 2f1d24b5a520a29cf16d193a8707cd92ddc42ac2 Mon Sep 17 00:00:00 2001 From: Steven Fairchild Date: Wed, 17 Apr 2024 15:22:10 -0400 Subject: [PATCH 18/38] WIP Move image pull function to common.sh --- pkg/deploy/generator/scripts/common.sh | 33 ++++++++++++++++++++++++++ pkg/deploy/generator/scripts/rpVMSS.sh | 33 -------------------------- 2 files changed, 33 insertions(+), 33 deletions(-) diff --git a/pkg/deploy/generator/scripts/common.sh b/pkg/deploy/generator/scripts/common.sh index 25b249fee42..f7b95116aa8 100644 --- a/pkg/deploy/generator/scripts/common.sh +++ b/pkg/deploy/generator/scripts/common.sh @@ -156,3 +156,36 @@ include /etc/logrotate.d write_file logrotate_conf_filename logrotate_conf_file true } + +# pull_container_images +pull_container_images() { + local -n pull_images="$1" + log "starting" + + # The managed identity that the VM runs as only has a single roleassignment. + # This role assignment is ACRPull which is not necessarily present in the + # subscription we're deploying into. If the identity does not have any + # role assignments scoped on the subscription we're deploying into, it will + # not show on az login -i, which is why the below line is commented. + # az account set -s "$SUBSCRIPTIONID" + az login -i --allow-no-subscriptions + + # Suppress emulation output for podman instead of docker for az acr compatability + mkdir -p /etc/containers/ + mkdir -p /root/.docker + touch /etc/containers/nodocker + + # This name is used in the case that az acr login searches for this in it's environment + local -r REGISTRY_AUTH_FILE="/root/.docker/config.json" + + log "logging into prod acr" + az acr login --name "$(sed -e 's|.*/||' <<<"$ACRRESOURCEID")" + + # shellcheck disable=SC2068 + for i in ${pull_images[@]}; do + log "Pulling image $i now" + podman pull "$i" + done + + az logout +} diff --git a/pkg/deploy/generator/scripts/rpVMSS.sh b/pkg/deploy/generator/scripts/rpVMSS.sh index e74da4d3fc9..eb45315853c 100644 --- a/pkg/deploy/generator/scripts/rpVMSS.sh +++ b/pkg/deploy/generator/scripts/rpVMSS.sh @@ -237,39 +237,6 @@ gpgcheck=no' write_file azure_repo_filename azure_repo_file true } -# pull_container_images -pull_container_images() { - local -n pull_images="$1" - log "starting" - - # The managed identity that the VM runs as only has a single roleassignment. - # This role assignment is ACRPull which is not necessarily present in the - # subscription we're deploying into. If the identity does not have any - # role assignments scoped on the subscription we're deploying into, it will - # not show on az login -i, which is why the below line is commented. - # az account set -s "$SUBSCRIPTIONID" - az login -i --allow-no-subscriptions - - # Suppress emulation output for podman instead of docker for az acr compatability - mkdir -p /etc/containers/ - mkdir -p /root/.docker - touch /etc/containers/nodocker - - # This name is used in the case that az acr login searches for this in it's environment - local -r REGISTRY_AUTH_FILE="/root/.docker/config.json" - - log "logging into prod acr" - az acr login --name "$(sed -e 's|.*/||' <<<"$ACRRESOURCEID")" - - # shellcheck disable=SC2068 - for i in ${pull_images[@]}; do - log "Pulling image $i now" - podman pull "$i" - done - - az logout -} - # configure_system_services creates, configures, and enables the following systemd services and timers # services # fluentbit From 7aeda490a9ddfbdfd5efee2719c3bcf911b99461 Mon Sep 17 00:00:00 2001 From: Steven Fairchild Date: Wed, 17 Apr 2024 15:27:03 -0400 Subject: [PATCH 19/38] WIP move enable services to common.sh --- pkg/deploy/generator/scripts/common.sh | 13 +++++++ pkg/deploy/generator/scripts/rpVMSS.sh | 48 +++++++++++--------------- 2 files changed, 33 insertions(+), 28 deletions(-) diff --git a/pkg/deploy/generator/scripts/common.sh b/pkg/deploy/generator/scripts/common.sh index f7b95116aa8..e7985a93017 100644 --- a/pkg/deploy/generator/scripts/common.sh +++ b/pkg/deploy/generator/scripts/common.sh @@ -189,3 +189,16 @@ pull_container_images() { az logout } + +# enable_services enables all services required for aro rp +enable_services() { + local -n services="$1" + log "starting" + + log "enabling aro services ${aro_services[*]}" + # shellcheck disable=SC2068 + for service in ${aro_services[@]}; do + log "Enabling $service now" + systemctl enable "$service.service" + done +} diff --git a/pkg/deploy/generator/scripts/rpVMSS.sh b/pkg/deploy/generator/scripts/rpVMSS.sh index eb45315853c..fcdbcafc921 100644 --- a/pkg/deploy/generator/scripts/rpVMSS.sh +++ b/pkg/deploy/generator/scripts/rpVMSS.sh @@ -78,7 +78,24 @@ main() { ) pull_container_images images - configure_system_services + configure_aro_services + + local -ra aro_services=( + "aro-dbtoken" + "aro-monitor" + "aro-portal" + "aro-rp" + "auoms" + "azsecd" + "azsecmond" + "mdsd" + "mdm" + "chronyd" + "fluentbit" + ) + + enable_services aro_services + reboot_vm } @@ -237,7 +254,7 @@ gpgcheck=no' write_file azure_repo_filename azure_repo_file true } -# configure_system_services creates, configures, and enables the following systemd services and timers +# configure_aro_services creates, configures, and enables the following systemd services and timers # services # fluentbit # mdm @@ -246,7 +263,7 @@ gpgcheck=no' # aro-dbtoken # aro-monitor # aro-portal -configure_system_services() { +configure_aro_services() { configure_service_fluentbit configure_service_mdm configure_timers_mdm_mdsd @@ -257,31 +274,6 @@ configure_system_services() { configure_service_mdsd } -# enable_aro_services enables all services required for aro rp -enable_aro_services() { - log "starting" - - local -ra aro_services=( - "aro-dbtoken" - "aro-monitor" - "aro-portal" - "aro-rp" - "auoms" - "azsecd" - "azsecmond" - "mdsd" - "mdm" - "chronyd" - "fluentbit" - ) - log "enabling aro services ${aro_services[*]}" - # shellcheck disable=SC2068 - for service in ${aro_services[@]}; do - log "Enabling $service now" - systemctl enable "$service.service" - done -} - # configure_service_fluentbit configure_service_fluentbit() { log "starting" From 6354b8e30217878834ef601f5c3f950fc35a4829 Mon Sep 17 00:00:00 2001 From: Steven Fairchild Date: Wed, 17 Apr 2024 15:27:50 -0400 Subject: [PATCH 20/38] WIP add write_file, reboot_vm, log, and abort to common.sh --- pkg/deploy/generator/scripts/common.sh | 42 ++++++++++++++++++++++++++ pkg/deploy/generator/scripts/rpVMSS.sh | 42 -------------------------- 2 files changed, 42 insertions(+), 42 deletions(-) diff --git a/pkg/deploy/generator/scripts/common.sh b/pkg/deploy/generator/scripts/common.sh index e7985a93017..69ee2e6de02 100644 --- a/pkg/deploy/generator/scripts/common.sh +++ b/pkg/deploy/generator/scripts/common.sh @@ -202,3 +202,45 @@ enable_services() { systemctl enable "$service.service" done } + +# write_file +# Args +# 1) filename - string +# 2) file_contents - string +# 3) clobber - boolean; optional - defaults to false +write_file() { + local -n filename="$1" + local -n file_contents="$2" + local -r clobber="${3:-false}" + + if $clobber; then + log "Overwriting file $filename" + echo "$file_contents" > "$filename" + else + log "Appending to $filename" + echo "$file_contents" >> "$filename" + fi +} + +# reboot_vm restores all selinux file contexts, waits 30 seconds then reboots +reboot_vm() { + log "starting" + + configure_selinux "true" + (sleep 30 && log "rebooting vm now"; reboot) & +} + +# log is a wrapper for echo that includes the function name +log() { + local -r msg="${1:-"log message is empty"}" + local -r stack_level="${2:-1}" + echo "${FUNCNAME[${stack_level}]}: ${msg}" +} + +# abort is a wrapper for log that exits with an error code +abort() { + local -ri origin_stacklevel=2 + log "${1}" "$origin_stacklevel" + log "Exiting" + exit 1 +} diff --git a/pkg/deploy/generator/scripts/rpVMSS.sh b/pkg/deploy/generator/scripts/rpVMSS.sh index fcdbcafc921..3d14e9173b6 100644 --- a/pkg/deploy/generator/scripts/rpVMSS.sh +++ b/pkg/deploy/generator/scripts/rpVMSS.sh @@ -905,48 +905,6 @@ run_azsecd_config_scan() { done } -# write_file -# Args -# 1) filename - string -# 2) file_contents - string -# 3) clobber - boolean; optional - defaults to false -write_file() { - local -n filename="$1" - local -n file_contents="$2" - local -r clobber="${3:-false}" - - if $clobber; then - log "Overwriting file $filename" - echo "$file_contents" > "$filename" - else - log "Appending to $filename" - echo "$file_contents" >> "$filename" - fi -} - -# reboot_vm restores all selinux file contexts, waits 30 seconds then reboots -reboot_vm() { - log "starting" - - configure_selinux "true" - (sleep 30 && log "rebooting vm now"; reboot) & -} - -# log is a wrapper for echo that includes the function name -log() { - local -r msg="${1:-"log message is empty"}" - local -r stack_level="${2:-1}" - echo "${FUNCNAME[${stack_level}]}: ${msg}" -} - -# abort is a wrapper for log that exits with an error code -abort() { - local -ri origin_stacklevel=2 - log "${1}" "$origin_stacklevel" - log "Exiting" - exit 1 -} - export AZURE_CLOUD_NAME="${AZURECLOUDNAME:?"Failed to carry over variables"}" main "$@" From d55340cca565d06cfe32dd4badbc19ee50692656 Mon Sep 17 00:00:00 2001 From: Steven Fairchild Date: Wed, 17 Apr 2024 15:29:26 -0400 Subject: [PATCH 21/38] WIP move dnf_install_pkgs to common.sh --- pkg/deploy/generator/scripts/common.sh | 15 +++++++++++++++ pkg/deploy/generator/scripts/rpVMSS.sh | 17 +---------------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/pkg/deploy/generator/scripts/common.sh b/pkg/deploy/generator/scripts/common.sh index 69ee2e6de02..4d39f1dd291 100644 --- a/pkg/deploy/generator/scripts/common.sh +++ b/pkg/deploy/generator/scripts/common.sh @@ -19,6 +19,21 @@ retry() { done } +# dnf_install_pkgs +dnf_install_pkgs() { + local -n pkgs="$1" + log "starting" + + local -ra cmd=( + dnf + -y + install + ${pkgs[@]} + ) + + log "Attempting to install packages: ${pkgs[*]}" + retry cmd "$2" +} # We need to configure PasswordAuthentication to yes in order for the VMSS Access JIT to work configure_sshd() { diff --git a/pkg/deploy/generator/scripts/rpVMSS.sh b/pkg/deploy/generator/scripts/rpVMSS.sh index 3d14e9173b6..7696fc41900 100644 --- a/pkg/deploy/generator/scripts/rpVMSS.sh +++ b/pkg/deploy/generator/scripts/rpVMSS.sh @@ -173,6 +173,7 @@ parse_run_options() { exit 0 } +# configure_rpm_repos configure_rpm_repos() { log "starting" @@ -196,22 +197,6 @@ configure_rhui_repo() { retry cmd "$1" } -# dnf_install_pkgs -dnf_install_pkgs() { - local -n pkgs="$1" - log "starting" - - local -ra cmd=( - dnf - -y - install - ${pkgs[@]} - ) - - log "Attempting to install packages: ${pkgs[*]}" - retry cmd "$2" -} - # configure_disk_partitions configure_disk_partitions() { log "starting" From d4eac32c7ed64c0d6ec79959e1fca115c21a67d5 Mon Sep 17 00:00:00 2001 From: Steven Fairchild Date: Wed, 17 Apr 2024 16:39:04 -0400 Subject: [PATCH 22/38] WIP Fix parse_run_options to allow local testing --- pkg/deploy/generator/scripts/rpVMSS.sh | 98 +++++++++++++++++--------- 1 file changed, 63 insertions(+), 35 deletions(-) diff --git a/pkg/deploy/generator/scripts/rpVMSS.sh b/pkg/deploy/generator/scripts/rpVMSS.sh index 7696fc41900..1188757ed88 100644 --- a/pkg/deploy/generator/scripts/rpVMSS.sh +++ b/pkg/deploy/generator/scripts/rpVMSS.sh @@ -14,26 +14,16 @@ main() { # shellcheck source=common.sh source common.sh - parse_run_options "$@" - - - configure_sshd - configure_rpm_repos retry_wait_time - local -ar exclude_pkgs=( "-x WALinuxAgent" "-x WALinuxAgent-udev" ) - dnf_update_pkgs exclude_pkgs retry_wait_time - local -ra rpm_keys=( https://dl.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-8 https://packages.microsoft.com/keys/microsoft.asc ) - rpm_import_keys rpm_keys retry_wait_time - local -ra repo_rpm_pkgs=( https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm ) @@ -52,24 +42,6 @@ main() { python3 ) - dnf_install_pkgs repo_rpm_pkgs retry_wait_time - dnf_install_pkgs install_pkgs retry_wait_time - - configure_disk_partitions - configure_logrotate - configure_selinux - - mkdir -p /var/log/journal - mkdir -p /var/lib/waagent/Microsoft.Azure.KeyVault.Store - - local -ra enable_ports=( - "443/tcp" - "444/tcp" - "445/tcp" - "2222/tcp" - ) - configure_firewalld_rules enable_ports - MDMIMAGE="${RPIMAGE%%/*}/${MDMIMAGE##*/}" local -ra images=( "$MDMIMAGE" @@ -77,8 +49,12 @@ main() { "$FLUENTBITIMAGE" ) - pull_container_images images - configure_aro_services + local -ra enable_ports=( + "443/tcp" + "444/tcp" + "445/tcp" + "2222/tcp" + ) local -ra aro_services=( "aro-dbtoken" @@ -94,6 +70,39 @@ main() { "fluentbit" ) + parse_run_options "$@" \ + retry_wait_time \ + exclude_pkgs \ + rpm_keys \ + repo_rpm_pkgs \ + install_pkgs \ + images \ + enable_ports \ + aro_services + + configure_sshd + configure_rpm_repos retry_wait_time + + dnf_update_pkgs exclude_pkgs retry_wait_time + + rpm_import_keys rpm_keys retry_wait_time + + dnf_install_pkgs repo_rpm_pkgs retry_wait_time + dnf_install_pkgs install_pkgs retry_wait_time + + configure_disk_partitions + configure_logrotate + configure_selinux + + mkdir -p /var/log/journal + mkdir -p /var/lib/waagent/Microsoft.Azure.KeyVault.Store + + configure_firewalld_rules enable_ports + + pull_container_images images + configure_aro_services + enable_services + enable_services aro_services reboot_vm @@ -122,6 +131,15 @@ usage() { parse_run_options() { # shellcheck disable=SC2206 local -a options=(${1:-}) + local -n retry_time="$2" + local -n pkgs_to_exclude="$3" + local -n keys_to_import="$4" + local -n rpm_pkgs="$5" + local -n pkgs_to_install="$6" + local -n images_to_pull="$7" + local -n ports_to_enable="$8" + local -n services_to_enable="$9" + if [ "${#options[@]}" -eq 0 ]; then log "Running all steps" return 0 @@ -136,8 +154,17 @@ parse_run_options() { configure_disk_partitions ;; p) - log "Running step configure_and_install_dnf_pkgs_repos" - configure_and_install_dnf_pkgs_repos + log "Running step configure_rpm_repos" + configure_rpm_repos keys_to_import + + log "Running step dnf_update_pkgs" + dnf_update_pkgs pkgs_to_exclude retry_time + + log "Running step dnf_install_pkgs rpm_pkgs" + dnf_install_pkgs rpm_pkgs retry_time + + log "Running step dnf_install_pkgs pkgs" + dnf_install_pkgs pkgs_to_install retry_time ;; l) log "Running configure_logrotate" @@ -153,15 +180,16 @@ parse_run_options() { ;; f) log "Running configure_firewalld_rules" - configure_firewalld_rules + configure_firewalld_rules ports_to_enable ;; u) log "Running pull_container_images & configure_system_services" - configure_system_services + configure_aro_services + enable_services services_to_enable ;; i) log "Running pull_container_images" - pull_container_images + pull_container_images images_to_pull ;; *) usage allowed_options From c8639d31be7ded54af5c202ab395b5d2ae92940d Mon Sep 17 00:00:00 2001 From: Steven Fairchild Date: Wed, 17 Apr 2024 16:40:52 -0400 Subject: [PATCH 23/38] WIP add -p to mkdir for mdsd.service.d to allow for existing directory --- pkg/deploy/generator/scripts/rpVMSS.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/deploy/generator/scripts/rpVMSS.sh b/pkg/deploy/generator/scripts/rpVMSS.sh index 1188757ed88..5012c8a9652 100644 --- a/pkg/deploy/generator/scripts/rpVMSS.sh +++ b/pkg/deploy/generator/scripts/rpVMSS.sh @@ -869,7 +869,7 @@ configure_service_mdsd() { log "starting" local -r mdsd_service_dir="/etc/systemd/system/mdsd.service.d" - mkdir "$mdsd_service_dir" + mkdir -p "$mdsd_service_dir" local -r mdsd_override_conf_filename="$mdsd_service_dir/override.conf" local -r mdsd_override_conf_file="[Unit] From e91476ad4e60d4a2984ea785838fd7d574be8f91 Mon Sep 17 00:00:00 2001 From: Steven Fairchild Date: Wed, 17 Apr 2024 16:43:54 -0400 Subject: [PATCH 24/38] WIP correct aro-portal.service, aro-rp.service and fluentbit.service file writing The config file was being written twice --- pkg/deploy/generator/scripts/rpVMSS.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pkg/deploy/generator/scripts/rpVMSS.sh b/pkg/deploy/generator/scripts/rpVMSS.sh index 5012c8a9652..e8cedfd1e25 100644 --- a/pkg/deploy/generator/scripts/rpVMSS.sh +++ b/pkg/deploy/generator/scripts/rpVMSS.sh @@ -371,7 +371,7 @@ StartLimitInterval=0 [Install] WantedBy=multi-user.target" - write_file fluentbit_conf_filename fluentbit_conf_file true + write_file fluentbit_service_filename fluentbit_service_file true } # configure_certs @@ -686,7 +686,7 @@ StartLimitInterval=0 [Install] WantedBy=multi-user.target" - write_file aro_rp_service_filename aro_rp_conf_file true + write_file aro_rp_service_filename aro_rp_service_file true } # configure_service_aro_dbtoken @@ -861,7 +861,7 @@ RestartSec=1 [Install] WantedBy=multi-user.target" - write_file aro_portal_service_conf_filename aro_portal_service_conf_file true + write_file aro_portal_service_filename aro_portal_service_file true } # configure_service_mdsd From 84cfcefa6ac3bc196902e50275216b21efffb955 Mon Sep 17 00:00:00 2001 From: Steven Fairchild Date: Wed, 17 Apr 2024 17:30:25 -0400 Subject: [PATCH 25/38] Rewrite devProxyVMSS.sh to reuse functions in common.sh --- pkg/deploy/assets/env-development.json | 2 +- pkg/deploy/assets/rp-production.json | 2 +- pkg/deploy/generator/scripts/common.sh | 38 ++- pkg/deploy/generator/scripts/devProxyVMSS.sh | 330 ++++--------------- pkg/deploy/generator/scripts/rpVMSS.sh | 24 +- 5 files changed, 103 insertions(+), 293 deletions(-) diff --git a/pkg/deploy/assets/env-development.json b/pkg/deploy/assets/env-development.json index 1da1cb9fb5b..af038e859b5 100644 --- a/pkg/deploy/assets/env-development.json +++ b/pkg/deploy/assets/env-development.json @@ -296,7 +296,7 @@ "autoUpgradeMinorVersion": true, "settings": {}, "protectedSettings": { - "script": "[base64(concat(base64ToString('c2V0IC1leAoK'),'PROXYIMAGE=$(base64 -d \u003c\u003c\u003c''',base64(parameters('proxyImage')),''')\n','PROXYIMAGEAUTH=$(base64 -d \u003c\u003c\u003c''',base64(parameters('proxyImageAuth')),''')\n','PROXYCERT=''',parameters('proxyCert'),'''\n','PROXYCLIENTCERT=''',parameters('proxyClientCert'),'''\n','PROXYKEY=''',parameters('proxyKey'),'''\n','\n',base64ToString('IyEvYmluL2Jhc2gKCnNldCAtbyBlcnJleGl0IFwKICAgIC1vIG5vdW5zZXQKCmlmIFsgIiR7REVCVUc6LWZhbHNlfSIgPT0gdHJ1ZSBdOyB0aGVuCiAgICBzZXQgLXgKZmkKCm1haW4oKSB7CiAgICBwYXJzZV9ydW5fb3B0aW9ucyAiJEAiCgogICAgY29uZmlndXJlX2FuZF9pbnN0YWxsX2RuZl9wa2dzX3JlcG9zCgogICAgY29uZmlndXJlX2ZpcmV3YWxsZF9ydWxlcwogICAgcHVsbF9jb250YWluZXJfaW1hZ2VzCiAgICBjb25maWd1cmVfc3lzdGVtX3NlcnZpY2VzCiAgICByZWJvb3Rfdm0KfQoKdXNhZ2UoKSB7CiAgICBsb2NhbCAtbiBvcHRpb25zPSIkMSIKICAgIGxvZyAiJChiYXNlbmFtZSAiJDAiKSBbJG9wdGlvbnNdCiAgICAgICAgLXAgQ29uZmlndXJlIHJwbSByZXBvc2l0b3JpZXMsIGltcG9ydCByZXF1aXJlZCBycG0ga2V5cywgdXBkYXRlICYgaW5zdGFsbCBwYWNrYWdlcyB3aXRoIGRuZgogICAgICAgIC1mIENvbmZpZ3VyZSBmaXJld2FsbGQgZGVmYXVsdCB6b25lIHJ1bGVzCiAgICAgICAgLXUgQ29uZmlndXJlIHN5c3RlbWQgdW5pdCBmaWxlcyBmb3IgQVJPIFJQCiAgICAgICAgLWkgUHVsbCBjb250YWluZXIgaW1hZ2VzCgogICAgICAgIE5vdGU6IHN0ZXBzIHdpbGwgYmUgZXhlY3V0ZWQgaW4gdGhlIG9yZGVyIHRoYXQgZmxhZ3MgYXJlIHByb3ZpZGVkCiAgICAiCn0KCiMgcGFyc2VfcnVuX29wdGlvbnMgdGFrZXMgYWxsIGFyZ3VlbWVudHMgcGFzc2VkIHRvIG1haW4gYW5kIHBhcnNlcyB0aGVtCiMgYWxsb3dpbmcgaW5kaXZpZHVhbCBzdGVwKHMpIHRvIGJlIHJhbiwgcmF0aGVyIHRoYW4gYWxsIHN0ZXBzCiMKIyBUaGlzIGlzIHVzZWZ1bCBmb3IgbG9jYWwgdGVzdGluZywgb3IgcG9zc2libHkgbW9kaWZ5aW5nIHRoZSBib290c3RyYXAgZXhlY3V0aW9uIHZpYSBlbnZpcm9ubWVudCB2YXJpYWJsZXMgaW4gdGhlIGRlcGxveW1lbnQgcGlwZWxpbmUKcGFyc2VfcnVuX29wdGlvbnMoKSB7CiAgICAjIHNoZWxsY2hlY2sgZGlzYWJsZT1TQzIyMDYKICAgIGxvY2FsIC1hIG9wdGlvbnM9KCR7MTotfSkKICAgIGlmIFsgIiR7I29wdGlvbnNbQF19IiAtZXEgMCBdOyB0aGVuCiAgICAgICAgbG9nICJSdW5uaW5nIGFsbCBzdGVwcyIKICAgICAgICByZXR1cm4gMAogICAgZmkKCiAgICBsb2NhbCBPUFRJTkQKCWxvY2FsIC1yIGFsbG93ZWRfb3B0aW9ucz0icGZ1aSIKICAgIHdoaWxlIGdldG9wdHMgJHthbGxvd2VkX29wdGlvbnN9IG9wdGlvbnM7IGRvCiAgICAgICAgY2FzZSAiJHtvcHRpb25zfSIgaW4KICAgICAgICAgICAgcCkKICAgICAgICAgICAgICAgIGxvZyAiUnVubmluZyBzdGVwIGNvbmZpZ3VyZV9hbmRfaW5zdGFsbF9kbmZfcGtnc19yZXBvcyIKICAgICAgICAgICAgICAgIGNvbmZpZ3VyZV9hbmRfaW5zdGFsbF9kbmZfcGtnc19yZXBvcwogICAgICAgICAgICAgICAgOzsKICAgICAgICAgICAgZikKICAgICAgICAgICAgICAgIGxvZyAiUnVubmluZyBjb25maWd1cmVfZmlyZXdhbGxkX3J1bGVzIgogICAgICAgICAgICAgICAgY29uZmlndXJlX2ZpcmV3YWxsZF9ydWxlcwogICAgICAgICAgICAgICAgOzsKICAgICAgICAgICAgdSkKICAgICAgICAgICAgICAgIGxvZyAiUnVubmluZyBwdWxsX2NvbnRhaW5lcl9pbWFnZXMgJiBjb25maWd1cmVfc3lzdGVtX3NlcnZpY2VzIgogICAgICAgICAgICAgICAgY29uZmlndXJlX3N5c3RlbV9zZXJ2aWNlcwogICAgICAgICAgICAgICAgOzsKICAgICAgICAgICAgaSkKICAgICAgICAgICAgICAgIGxvZyAiUnVubmluZyBwdWxsX2NvbnRhaW5lcl9pbWFnZXMiCiAgICAgICAgICAgICAgICBwdWxsX2NvbnRhaW5lcl9pbWFnZXMgCiAgICAgICAgICAgICAgICA7OwogICAgICAgICAgICAqKQogICAgICAgICAgICAgICAgdXNhZ2UgYWxsb3dlZF9vcHRpb25zCiAgICAgICAgICAgICAgICBhYm9ydCAiVW5rb3duIG9wdGlvbiBwcm92aWRlZCIKICAgICAgICAgICAgICAgIDs7CiAgICAgICAgZXNhYwogICAgZG9uZQogICAgCiAgICBleGl0IDAKfQoKIyBjb25maWd1cmVfYW5kX2luc3RhbGxfZG5mX3BrZ3NfcmVwb3MKY29uZmlndXJlX2FuZF9pbnN0YWxsX2RuZl9wa2dzX3JlcG9zKCkgewogICAgbG9nICJzdGFydGluZyIKCiAgICAjIHRyYW5zYWN0aW9uIGF0dGVtcHQgcmV0cnkgdGltZSBpbiBzZWNvbmRzCiAgICBsb2NhbCAtcmkgcmV0cnlfd2FpdF90aW1lPTYwCiAgICBjb25maWd1cmVfcmh1aV9yZXBvIHJldHJ5X3dhaXRfdGltZQoKICAgIGxvY2FsIC1hciBleGNsdWRlX3BrZ3M9KAogICAgICAgICIteCBXQUxpbnV4QWdlbnQiCiAgICAgICAgIi14IFdBTGludXhBZ2VudC11ZGV2IgogICAgKQoKICAgIGRuZl91cGRhdGVfcGtncyBleGNsdWRlX3BrZ3MgcmV0cnlfd2FpdF90aW1lCgogICAgbG9jYWwgLXJhIHJlcG9fcnBtX3BrZ3M9KAogICAgICAgIGh0dHBzOi8vZGwuZmVkb3JhcHJvamVjdC5vcmcvcHViL2VwZWwvZXBlbC1yZWxlYXNlLWxhdGVzdC04Lm5vYXJjaC5ycG0KICAgICkKCiAgICBsb2NhbCAtcmEgaW5zdGFsbF9wa2dzPSgKICAgICAgICBwb2RtYW4KICAgICAgICBwb2RtYW4tZG9ja2VyCiAgICApCgogICAgZG5mX2luc3RhbGxfcGtncyByZXBvX3JwbV9wa2dzIHJldHJ5X3dhaXRfdGltZQogICAgZG5mX2luc3RhbGxfcGtncyBpbnN0YWxsX3BrZ3MgcmV0cnlfd2FpdF90aW1lCgoJbG9jYWwgLXIgY3Jvbl93ZWVrbHlfZG5mX3VwZGF0ZV9maWxlbmFtZT0nL2V0Yy9jcm9uLndlZWtseS9kbmZ1cGRhdGUnCglsb2NhbCAtciBjcm9uX3dlZWtseV9kbmZfdXBkYXRlX2ZpbGU9IiMhL2Jpbi9iYXNoCmRuZiB1cGRhdGUgLXkiCgoJd3JpdGVfZmlsZSBjcm9uX3dlZWtseV9kbmZfdXBkYXRlX2ZpbGVuYW1lIGNyb25fd2Vla2x5X2RuZl91cGRhdGVfZmlsZSB0cnVlCgljaG1vZCAreCAiJGNyb25fd2Vla2x5X2RuZl91cGRhdGVfZmlsZW5hbWUiCn0KCiMgY29uZmlndXJlX3JodWlfcmVwbwpjb25maWd1cmVfcmh1aV9yZXBvKCkgewogICAgbG9nICJzdGFydGluZyIKCiAgICBsb2NhbCAtcmEgY21kPSgKICAgICAgICBkbmYKICAgICAgICB1cGRhdGUKICAgICAgICAteQogICAgICAgIC0tZGlzYWJsZXJlcG89JyonCiAgICAgICAgLS1lbmFibGVyZXBvPSdyaHVpLW1pY3Jvc29mdC1henVyZSonCiAgICApCgogICAgbG9nICJydW5uaW5nIFJIVUkgcGFja2FnZSB1cGRhdGVzIgogICAgcmV0cnkgY21kICIkMSIKfQoKIyByZXRyeSBBZGRpbmcgcmV0cnkgbG9naWMgdG8geXVtIGNvbW1hbmRzIGluIG9yZGVyIHRvIGF2b2lkIHN0YWxsaW5nIG91dCBvbiByZXNvdXJjZSBsb2NrcwpyZXRyeSgpIHsKICAgIGxvY2FsIC1uIGNtZF9yZXRyeT0iJDEiCiAgICBsb2NhbCAtbiB3YWl0X3RpbWU9IiQyIgoKICAgIGZvciBhdHRlbXB0IGluIHsxLi41fTsgZG8KICAgICAgICBsb2cgImF0dGVtcHQgIyR7YXR0ZW1wdH0gLSAke0ZVTkNOQU1FWzJdfSIKICAgICAgICAke2NtZF9yZXRyeVtAXX0gJgoKICAgICAgICB3YWl0ICQhICYmIGJyZWFrCiAgICAgICAgaWYgW1sgJHthdHRlbXB0fSAtbHQgNSBdXTsgdGhlbgogICAgICAgICAgICBzbGVlcCAiJHdhaXRfdGltZSIKICAgICAgICBlbHNlCiAgICAgICAgICAgIGFib3J0ICJhdHRlbXB0ICMke2F0dGVtcHR9IC0gRmFpbGVkIHRvIHVwZGF0ZSBwYWNrYWdlcyIKICAgICAgICBmaQogICAgZG9uZQp9CgojIGRuZl91cGRhdGVfcGtncwpkbmZfdXBkYXRlX3BrZ3MoKSB7CiAgICBsb2NhbCAtbiBleGNsdWRlcz0iJDEiCiAgICBsb2cgInN0YXJ0aW5nIgoKICAgIGxvY2FsIC1yYSBjbWQ9KAogICAgICAgIGRuZgogICAgICAgIC15CiAgICAgICAgJHtleGNsdWRlc1tAXX0KICAgICAgICB1cGRhdGUKICAgICAgICAtLWFsbG93ZXJhc2luZwogICAgKQoKICAgIGxvZyAiVXBkYXRpbmcgYWxsIHBhY2thZ2VzIgogICAgcmV0cnkgY21kICIkMiIKfQoKIyBkbmZfaW5zdGFsbF9wa2dzCmRuZl9pbnN0YWxsX3BrZ3MoKSB7CiAgICBsb2NhbCAtbiBwa2dzPSIkMSIKICAgIGxvZyAic3RhcnRpbmciCgogICAgbG9jYWwgLXJhIGNtZD0oCiAgICAgICAgZG5mCiAgICAgICAgLXkKICAgICAgICBpbnN0YWxsCiAgICAgICAgJHtwa2dzW0BdfQogICAgKQoKICAgIGxvZyAiQXR0ZW1wdGluZyB0byBpbnN0YWxsIHBhY2thZ2VzOiAke3BrZ3NbKl19IgogICAgcmV0cnkgY21kICIkMiIKfQoKIyBjb25maWd1cmVfbG9ncm90YXRlIGNsb2JiZXJzIC9ldGMvbG9ncm90YXRlLmNvbmYKY29uZmlndXJlX2xvZ3JvdGF0ZSgpIHsKICAgIGxvZyAic3RhcnRpbmciCgogICAgbG9jYWwgLXIgbG9ncm90YXRlX2NvbmZfZmlsZW5hbWU9Jy9ldGMvbG9ncm90YXRlLmNvbmYnCiAgICBsb2NhbCAtciBsb2dyb3RhdGVfY29uZl9maWxlPScjIHNlZSAibWFuIGxvZ3JvdGF0ZSIgZm9yIGRldGFpbHMKIyByb3RhdGUgbG9nIGZpbGVzIHdlZWtseQp3ZWVrbHkKCiMga2VlcCAyIHdlZWtzIHdvcnRoIG9mIGJhY2tsb2dzCnJvdGF0ZSAyCgojIGNyZWF0ZSBuZXcgKGVtcHR5KSBsb2cgZmlsZXMgYWZ0ZXIgcm90YXRpbmcgb2xkIG9uZXMKY3JlYXRlCgojIHVzZSBkYXRlIGFzIGEgc3VmZml4IG9mIHRoZSByb3RhdGVkIGZpbGUKZGF0ZWV4dAoKIyB1bmNvbW1lbnQgdGhpcyBpZiB5b3Ugd2FudCB5b3VyIGxvZyBmaWxlcyBjb21wcmVzc2VkCmNvbXByZXNzCgojIFJQTSBwYWNrYWdlcyBkcm9wIGxvZyByb3RhdGlvbiBpbmZvcm1hdGlvbiBpbnRvIHRoaXMgZGlyZWN0b3J5CmluY2x1ZGUgL2V0Yy9sb2dyb3RhdGUuZAoKIyBubyBwYWNrYWdlcyBvd24gd3RtcCBhbmQgYnRtcCAtLSB3ZSB3aWxsIHJvdGF0ZSB0aGVtIGhlcmUKL3Zhci9sb2cvd3RtcCB7CiAgICBtb250aGx5CiAgICBjcmVhdGUgMDY2NCByb290IHV0bXAKICAgICAgICBtaW5zaXplIDFNCiAgICByb3RhdGUgMQp9CgovdmFyL2xvZy9idG1wIHsKICAgIG1pc3NpbmdvawogICAgbW9udGhseQogICAgY3JlYXRlIDA2MDAgcm9vdCB1dG1wCiAgICByb3RhdGUgMQp9JwoKICAgIHdyaXRlX2ZpbGUgbG9ncm90YXRlX2NvbmZfZmlsZW5hbWUgbG9ncm90YXRlX2NvbmZfZmlsZSB0cnVlCn0KCiMgY29uZmlndXJlX2ZpcmV3YWxsZF9ydWxlcwpjb25maWd1cmVfZmlyZXdhbGxkX3J1bGVzKCkgewogICAgbG9nICJzdGFydGluZyIKCiAgICAjIGh0dHBzOi8vYWNjZXNzLnJlZGhhdC5jb20vc2VjdXJpdHkvY3ZlL2N2ZS0yMDIwLTEzNDAxCiAgICBsb2NhbCAtciBwcmVmaXg9Ii9ldGMvc3lzY3RsLmQiCiAgICBsb2NhbCAtciBkaXNhYmxlX2FjY2VwdF9yYV9jb25mX2ZpbGVuYW1lPSIkcHJlZml4LzAyLWRpc2FibGUtYWNjZXB0LXJhLmNvbmYiCiAgICBsb2NhbCAtciBkaXNhYmxlX2FjY2VwdF9yYV9jb25mX2ZpbGU9Im5ldC5pcHY2LmNvbmYuYWxsLmFjY2VwdF9yYT0wIgoKICAgIHdyaXRlX2ZpbGUgZGlzYWJsZV9hY2NlcHRfcmFfY29uZl9maWxlbmFtZSBkaXNhYmxlX2FjY2VwdF9yYV9jb25mX2ZpbGUgdHJ1ZQoKICAgIGxvY2FsIC1yIGRpc2FibGVfY29yZV9maWxlbmFtZT0iJHByZWZpeC8wMS1kaXNhYmxlLWNvcmUuY29uZiIKICAgIGxvY2FsIC1yIGRpc2FibGVfY29yZV9maWxlPSJrZXJuZWwuY29yZV9wYXR0ZXJuID0gfC9iaW4vdHJ1ZQogICAgIgogICAgd3JpdGVfZmlsZSBkaXNhYmxlX2NvcmVfZmlsZW5hbWUgZGlzYWJsZV9jb3JlX2ZpbGUgdHJ1ZQoKICAgIHN5c2N0bCAtLXN5c3RlbQoKICAgIGxvY2FsIC1yYSBlbmFibGVfcG9ydHM9KAogICAgICAgICI0NDMvdGNwIgogICAgKQoKICAgIGxvZyAiRW5hYmxpbmcgcG9ydHMgJHtlbmFibGVfcG9ydHNbKl19IG9uIGRlZmF1bHQgZmlyZXdhbGxkIHpvbmUiCiAgICAjIHNoZWxsY2hlY2sgZGlzYWJsZT1TQzIwNjgKICAgIGZvciBwb3J0IGluICR7ZW5hYmxlX3BvcnRzW0BdfTsgZG8KICAgICAgICBsb2cgIkVuYWJsaW5nIHBvcnQgJHBvcnQgbm93IgogICAgICAgIGZpcmV3YWxsLWNtZCAiLS1hZGQtcG9ydD0kcG9ydCIKICAgIGRvbmUKCiAgICBmaXJld2FsbC1jbWQgLS1ydW50aW1lLXRvLXBlcm1hbmVudAp9CgojIHB1bGxfY29udGFpbmVyX2ltYWdlcwpwdWxsX2NvbnRhaW5lcl9pbWFnZXMoKSB7CiAgICBsb2cgInN0YXJ0aW5nIgoKICAgICMgVGhlIG1hbmFnZWQgaWRlbnRpdHkgdGhhdCB0aGUgVk0gcnVucyBhcyBvbmx5IGhhcyBhIHNpbmdsZSByb2xlYXNzaWdubWVudC4KICAgICMgVGhpcyByb2xlIGFzc2lnbm1lbnQgaXMgQUNSUHVsbCB3aGljaCBpcyBub3QgbmVjZXNzYXJpbHkgcHJlc2VudCBpbiB0aGUKICAgICMgc3Vic2NyaXB0aW9uIHdlJ3JlIGRlcGxveWluZyBpbnRvLiAgSWYgdGhlIGlkZW50aXR5IGRvZXMgbm90IGhhdmUgYW55CiAgICAjIHJvbGUgYXNzaWdubWVudHMgc2NvcGVkIG9uIHRoZSBzdWJzY3JpcHRpb24gd2UncmUgZGVwbG95aW5nIGludG8sIGl0IHdpbGwKICAgICMgbm90IHNob3cgb24gYXogbG9naW4gLWksIHdoaWNoIGlzIHdoeSB0aGUgYmVsb3cgbGluZSBpcyBjb21tZW50ZWQuCiAgICAjIGF6IGFjY291bnQgc2V0IC1zICIkU1VCU0NSSVBUSU9OSUQiCiAgICBheiBsb2dpbiAtaSAtLWFsbG93LW5vLXN1YnNjcmlwdGlvbnMKCiAgICAjIFN1cHByZXNzIGVtdWxhdGlvbiBvdXRwdXQgZm9yIHBvZG1hbiBpbnN0ZWFkIG9mIGRvY2tlciBmb3IgYXogYWNyIGNvbXBhdGFiaWxpdHkKICAgIG1rZGlyIC1wIC9ldGMvY29udGFpbmVycy8KICAgIG1rZGlyIC1wIC9yb290Ly5kb2NrZXIKICAgIHRvdWNoIC9ldGMvY29udGFpbmVycy9ub2RvY2tlcgoKCSMgVGhpcyBuYW1lIGlzIHVzZWQgaW4gdGhlIGNhc2UgdGhhdCBheiBhY3IgbG9naW4gc2VhcmNoZXMgZm9yIHRoaXMgaW4gaXQncyBlbnZpcm9ubWVudAogICAgbG9jYWwgLXIgUkVHSVNUUllfQVVUSF9GSUxFPSIvcm9vdC8uZG9ja2VyL2NvbmZpZy5qc29uIgoJbG9jYWwgLXIgcmVnaXN0cnlfY29uZmlnX2ZpbGU9InsKCSJhdXRocyI6IHsKCQlcIiR7UFJPWFlJTUFHRSUlLyp9XCI6IHsKCQkJXCJhdXRoXCI6IFwiJFBST1hZSU1BR0VBVVRIXCIKCQl9Cgl9IgoKCXdyaXRlX2ZpbGUgUkVHSVNUUllfQVVUSF9GSUxFIHJlZ2lzdHJ5X2NvbmZpZ19maWxlIHRydWUKCiAgICBsb2cgImxvZ2dpbmcgaW50byBwcm9kIGFjciIKCiAgICBheiBhY3IgbG9naW4gLS1uYW1lICIkKHNlZCAtZSAnc3wuKi98fCcgPDw8IiRBQ1JSRVNPVVJDRUlEIikiCgogICAgZG9ja2VyIHB1bGwgIiRQUk9YWUlNQUdFIgoKICAgIGF6IGxvZ291dAp9CgojIGNvbmZpZ3VyZV9zeXN0ZW1fc2VydmljZXMgY3JlYXRlcywgY29uZmlndXJlcywgYW5kIGVuYWJsZXMgdGhlIGZvbGxvd2luZyBzeXN0ZW1kIHNlcnZpY2VzIGFuZCB0aW1lcnMKIyBzZXJ2aWNlcwojCXByb3h5CmNvbmZpZ3VyZV9zeXN0ZW1fc2VydmljZXMoKSB7Cgljb25maWd1cmVfc2VydmljZV9wcm94eQp9CgojIGVuYWJsZV9hcm9fc2VydmljZXMgZW5hYmxlcyBhbGwgc2VydmljZXMgcmVxdWlyZWQgZm9yIGFybyBycAplbmFibGVfYXJvX3NlcnZpY2VzKCkgewogICAgbG9nICJzdGFydGluZyIKCiAgICBsb2NhbCAtcmEgYXJvX3NlcnZpY2VzPSgKCQlwcm94eQogICAgKQogICAgbG9nICJlbmFibGluZyBhcm8gc2VydmljZXMgJHthcm9fc2VydmljZXNbKl19IgogICAgIyBzaGVsbGNoZWNrIGRpc2FibGU9U0MyMDY4CiAgICBmb3Igc2VydmljZSBpbiAke2Fyb19zZXJ2aWNlc1tAXX07IGRvCiAgICAgICAgbG9nICJFbmFibGluZyAkc2VydmljZSBub3ciCiAgICAgICAgc3lzdGVtY3RsIGVuYWJsZSAiJHNlcnZpY2Uuc2VydmljZSIKICAgIGRvbmUKfQoKIyBjb25maWd1cmVfY2VydHMKY29uZmlndXJlX2NlcnRzKCkgewogICAgbG9nICJzdGFydGluZyIKCgliYXNlNjQgLWQgPDw8IiRQUk9YWUNFUlQiID4vZXRjL3Byb3h5L3Byb3h5LmNydAoJYmFzZTY0IC1kIDw8PCIkUFJPWFlLRVkiID4vZXRjL3Byb3h5L3Byb3h5LmtleQoJYmFzZTY0IC1kIDw8PCIkUFJPWFlDTElFTlRDRVJUIiA+L2V0Yy9wcm94eS9wcm94eS1jbGllbnQuY3J0CgljaG93biAtUiAxMDAwOjEwMDAgL2V0Yy9wcm94eQoJY2htb2QgMDYwMCAvZXRjL3Byb3h5L3Byb3h5LmtleQp9Cgpjb25maWd1cmVfc2VydmljZV9wcm94eSgpIHsKCWxvY2FsIC1yIHN5c2NvbmZpZ19wcm94eV9maWxlbmFtZT0nL2V0Yy9zeXNjb25maWcvcHJveHknCglsb2NhbCAtciBzeXNjb25maWdfcHJveHlfZmlsZT0iUFJPWFlfSU1BR0U9JyRQUk9YWUlNQUdFJyIKCgl3cml0ZV9maWxlIHN5c2NvbmZpZ19wcm94eV9maWxlbmFtZSBzeXNjb25maWdfcHJveHlfZmlsZSB0cnVlCgoJbG9jYWwgLXIgcHJveHlfc2VydmljZV9maWxlbmFtZT0nL2V0Yy9zeXN0ZW1kL3N5c3RlbS9wcm94eS5zZXJ2aWNlJwoJbG9jYWwgLXIgcHJveHlfc2VydmljZV9maWxlPSJbVW5pdF0KQWZ0ZXI9bmV0d29yay1vbmxpbmUudGFyZ2V0CldhbnRzPW5ldHdvcmstb25saW5lLnRhcmdldAoKW1NlcnZpY2VdCkVudmlyb25tZW50RmlsZT0vZXRjL3N5c2NvbmZpZy9wcm94eQpFeGVjU3RhcnRQcmU9LS91c3IvYmluL2RvY2tlciBybSAtZiAlbgpFeGVjU3RhcnQ9L3Vzci9iaW4vZG9ja2VyIHJ1biAtLXJtIC0tbmFtZSAlbiAtcCA0NDM6ODQ0MyAtdiAvZXRjL3Byb3h5Oi9zZWNyZXRzICRQUk9YWV9JTUFHRQpFeGVjU3RvcD0vdXNyL2Jpbi9kb2NrZXIgc3RvcCAlbgpSZXN0YXJ0PWFsd2F5cwpSZXN0YXJ0U2VjPTEKU3RhcnRMaW1pdEludGVydmFsPTAKCltJbnN0YWxsXQpXYW50ZWRCeT1tdWx0aS11c2VyLnRhcmdldCIKCglsb2NhbCAtciBjcm9uX3dlZWtseV9wdWxsX2ltYWdlX2ZpbGVuYW1lPScvZXRjL2Nyb24ud2Vla2x5L3B1bGwtaW1hZ2UnCglsb2NhbCAtciBjcm9uX3dlZWtseV9wdWxsX2ltYWdlX2ZpbGU9IiMhL2Jpbi9iYXNoCmRvY2tlciBwdWxsICRQUk9YWUlNQUdFCnN5c3RlbWN0bCByZXN0YXJ0IHByb3h5LnNlcnZpY2UiCgkKCXdyaXRlX2ZpbGUgY3Jvbl93ZWVrbHlfcHVsbF9pbWFnZV9maWxlbmFtZSBjcm9uX3dlZWtseV9wdWxsX2ltYWdlX2ZpbGUgdHJ1ZQoJY2htb2QgK3ggIiRjcm9uX3dlZWtseV9wdWxsX2ltYWdlX2ZpbGVuYW1lIgoKCWxvY2FsIC1yIGNyb25fZGFpbHlfcmVzdGFydF9wcm94eV9maWxlbmFtZT0nL2V0Yy9jcm9uLmRhaWx5L3Jlc3RhcnQtcHJveHknCglsb2NhbCAtciBjcm9uX2RhaWx5X3Jlc3RhcnRfcHJveHlfZmlsZT0iIyEvYmluL2Jhc2gKc3lzdGVtY3RsIHJlc3RhcnQgcHJveHkuc2VydmljZSIKCQoJd3JpdGVfZmlsZSBjcm9uX2RhaWx5X3Jlc3RhcnRfcHJveHlfZmlsZW5hbWUgY3Jvbl9kYWlseV9yZXN0YXJ0X3Byb3h5X2ZpbGUKCWNobW9kICt4ICIkY3Jvbl9kYWlseV9yZXN0YXJ0X3Byb3h5X2ZpbGVuYW1lIgp9CgojIHdyaXRlX2ZpbGUKIyBBcmdzCiMgMSkgZmlsZW5hbWUgLSBzdHJpbmcKIyAyKSBmaWxlX2NvbnRlbnRzIC0gc3RyaW5nCiMgMykgY2xvYmJlciAtIGJvb2xlYW47IG9wdGlvbmFsIC0gZGVmYXVsdHMgdG8gZmFsc2UKd3JpdGVfZmlsZSgpIHsKICAgIGxvY2FsIC1uIGZpbGVuYW1lPSIkMSIKICAgIGxvY2FsIC1uIGZpbGVfY29udGVudHM9IiQyIgogICAgbG9jYWwgLXIgY2xvYmJlcj0iJHszOi1mYWxzZX0iCgogICAgaWYgJGNsb2JiZXI7IHRoZW4KICAgICAgICBsb2cgIk92ZXJ3cml0aW5nIGZpbGUgJGZpbGVuYW1lIgogICAgICAgIGVjaG8gIiRmaWxlX2NvbnRlbnRzIiA+ICIkZmlsZW5hbWUiCiAgICBlbHNlCiAgICAgICAgbG9nICJBcHBlbmRpbmcgdG8gJGZpbGVuYW1lIgogICAgICAgIGVjaG8gIiRmaWxlX2NvbnRlbnRzIiA+PiAiJGZpbGVuYW1lIgogICAgZmkKfQoKIyByZWJvb3Rfdm0gcmVzdG9yZXMgYWxsIHNlbGludXggZmlsZSBjb250ZXh0cywgd2FpdHMgMzAgc2Vjb25kcyB0aGVuIHJlYm9vdHMKcmVib290X3ZtKCkgewogICAgbG9nICJzdGFydGluZyIKCiAgICBjb25maWd1cmVfc2VsaW51eCAidHJ1ZSIKICAgIChzbGVlcCAzMCAmJiBsb2cgInJlYm9vdGluZyB2bSBub3ciOyByZWJvb3QpICYKfQoKIyBsb2cgaXMgYSB3cmFwcGVyIGZvciBlY2hvIHRoYXQgaW5jbHVkZXMgdGhlIGZ1bmN0aW9uIG5hbWUKbG9nKCkgewogICAgbG9jYWwgLXIgbXNnPSIkezE6LSJsb2cgbWVzc2FnZSBpcyBlbXB0eSJ9IgogICAgbG9jYWwgLXIgc3RhY2tfbGV2ZWw9IiR7MjotMX0iCiAgICBlY2hvICIke0ZVTkNOQU1FWyR7c3RhY2tfbGV2ZWx9XX06ICR7bXNnfSIKfQoKIyBhYm9ydCBpcyBhIHdyYXBwZXIgZm9yIGxvZyB0aGF0IGV4aXRzIHdpdGggYW4gZXJyb3IgY29kZQphYm9ydCgpIHsKICAgIGxvY2FsIC1yaSBvcmlnaW5fc3RhY2tsZXZlbD0yCiAgICBsb2cgIiR7MX0iICIkb3JpZ2luX3N0YWNrbGV2ZWwiCiAgICBsb2cgIkV4aXRpbmciCiAgICBleGl0IDEKfQoKZXhwb3J0IEFaVVJFX0NMT1VEX05BTUU9IiR7QVpVUkVDTE9VRE5BTUU6PyJGYWlsZWQgdG8gY2Fycnkgb3ZlciB2YXJpYWJsZXMifSIKCm1haW4gIiRAIgo=')))]" + "script": "[base64(concat(base64ToString('c2V0IC1leAoK'),'PROXYIMAGE=$(base64 -d \u003c\u003c\u003c''',base64(parameters('proxyImage')),''')\n','PROXYIMAGEAUTH=$(base64 -d \u003c\u003c\u003c''',base64(parameters('proxyImageAuth')),''')\n','PROXYCERT=''',parameters('proxyCert'),'''\n','PROXYCLIENTCERT=''',parameters('proxyClientCert'),'''\n','PROXYKEY=''',parameters('proxyKey'),'''\n','\n',base64ToString('IyEvYmluL2Jhc2gKCnNldCAtbyBlcnJleGl0IFwKICAgIC1vIG5vdW5zZXQKCmlmIFsgIiR7REVCVUc6LWZhbHNlfSIgPT0gdHJ1ZSBdOyB0aGVuCiAgICBzZXQgLXgKZmkKCm1haW4oKSB7CiAgICAjIHRyYW5zYWN0aW9uIGF0dGVtcHQgcmV0cnkgdGltZSBpbiBzZWNvbmRzCiAgICBsb2NhbCAtcmkgcmV0cnlfd2FpdF90aW1lPTYwCgogICAgIyBzaGVsbGNoZWNrIHNvdXJjZT1jb21tb24uc2gKICAgIHNvdXJjZSBjb21tb24uc2gKCiAgICBsb2NhbCAtcmEgZW5hYmxlX3BvcnRzPSgKICAgICAgICAiNDQzL3RjcCIKICAgICkKCiAgICBsb2NhbCBwcm94eV9pbWFnZT0iJFBST1hZSU1BR0UiCglsb2NhbCAtciByZWdpc3RyeV9jb25maWdfZmlsZT0iewogICAgXCJhdXRoc1wiOiB7CiAgICAgICAgXCIke1BST1hZSU1BR0UlJS8qfVwiOiB7CiAgICAgICAgICAgIFwiYXV0aFwiOiBcIiRQUk9YWUlNQUdFQVVUSFwiCiAgICAgICAgfQogICAgfSIKCiAgICBsb2NhbCAtYXIgZXhjbHVkZV9wa2dzPSgKICAgICAgICAiLXggV0FMaW51eEFnZW50IgogICAgICAgICIteCBXQUxpbnV4QWdlbnQtdWRldiIKICAgICkKCiAgICBsb2NhbCAtcmEgaW5zdGFsbF9wa2dzPSgKICAgICAgICBwb2RtYW4KICAgICAgICBwb2RtYW4tZG9ja2VyCiAgICApCgogICAgbG9jYWwgLXJhIHByb3h5X3NlcnZpY2VzPSgKCQlwcm94eQogICAgKQoKICAgIHBhcnNlX3J1bl9vcHRpb25zICIkQCIKCiAgICBkbmZfdXBkYXRlX3BrZ3MgcGtnc190b19leGNsdWRlIHJldHJ5X3dhaXRfdGltZQogICAgZG5mX2luc3RhbGxfcGtncyBpbnN0YWxsX3BrZ3MgcmV0cnlfd2FpdF90aW1lCiAgICBjb25maWd1cmVfZG5mX2Nyb25fam9iCgogICAgY29uZmlndXJlX2ZpcmV3YWxsZF9ydWxlcyBlbmFibGVfcG9ydHMKICAgIHB1bGxfY29udGFpbmVyX2ltYWdlcyBwcm94eV9pbWFnZSByZWdpc3RyeV9jb25maWdfZmlsZQogICAgY29uZmlndXJlX2RldnByb3h5X3NlcnZpY2VzCiAgICBlbmFibGVfc2VydmljZXMgcHJveHlfc2VydmljZXMKICAgIHJlYm9vdF92bQp9Cgp1c2FnZSgpIHsKICAgIGxvY2FsIC1uIG9wdGlvbnM9IiQxIgogICAgbG9nICIkKGJhc2VuYW1lICIkMCIpIFskb3B0aW9uc10KICAgICAgICAtcCBDb25maWd1cmUgcnBtIHJlcG9zaXRvcmllcywgaW1wb3J0IHJlcXVpcmVkIHJwbSBrZXlzLCB1cGRhdGUgJiBpbnN0YWxsIHBhY2thZ2VzIHdpdGggZG5mCiAgICAgICAgLWYgQ29uZmlndXJlIGZpcmV3YWxsZCBkZWZhdWx0IHpvbmUgcnVsZXMKICAgICAgICAtdSBDb25maWd1cmUgc3lzdGVtZCB1bml0IGZpbGVzCiAgICAgICAgLWkgUHVsbCBjb250YWluZXIgaW1hZ2VzCgogICAgICAgIE5vdGU6IHN0ZXBzIHdpbGwgYmUgZXhlY3V0ZWQgaW4gdGhlIG9yZGVyIHRoYXQgZmxhZ3MgYXJlIHByb3ZpZGVkCiAgICAiCn0KCiMgcGFyc2VfcnVuX29wdGlvbnMgdGFrZXMgYWxsIGFyZ3VlbWVudHMgcGFzc2VkIHRvIG1haW4gYW5kIHBhcnNlcyB0aGVtCiMgYWxsb3dpbmcgaW5kaXZpZHVhbCBzdGVwKHMpIHRvIGJlIHJhbiwgcmF0aGVyIHRoYW4gYWxsIHN0ZXBzCiMKIyBUaGlzIGlzIHVzZWZ1bCBmb3IgbG9jYWwgdGVzdGluZywgb3IgcG9zc2libHkgbW9kaWZ5aW5nIHRoZSBib290c3RyYXAgZXhlY3V0aW9uIHZpYSBlbnZpcm9ubWVudCB2YXJpYWJsZXMgaW4gdGhlIGRlcGxveW1lbnQgcGlwZWxpbmUKcGFyc2VfcnVuX29wdGlvbnMoKSB7CiAgICAjIHNoZWxsY2hlY2sgZGlzYWJsZT1TQzIyMDYKICAgIGxvY2FsIC1hIG9wdGlvbnM9KCR7MTotfSkKICAgIGxvY2FsIC1uIHBrZ3NfdG9fZXhjbHVkZT0iJDIiCiAgICBsb2NhbCAtbiBwa2dzX3RvX2luc3RhbGw9IiQzIgogICAgbG9jYWwgLW4gcG9ydHNfdG9fZW5hYmxlPSIkNCIKICAgIGxvY2FsIC1uIHNlcnZpY2VzX3RvX2VuYWJsZT0iJDUiCiAgICBsb2NhbCAtbiBpbWFnZXNfdG9fcHVsbD0iJDYiCgogICAgaWYgWyAiJHsjb3B0aW9uc1tAXX0iIC1lcSAwIF07IHRoZW4KICAgICAgICBsb2cgIlJ1bm5pbmcgYWxsIHN0ZXBzIgogICAgICAgIHJldHVybiAwCiAgICBmaQoKICAgIGxvY2FsIE9QVElORAoJbG9jYWwgLXIgYWxsb3dlZF9vcHRpb25zPSJwZnVpIgogICAgd2hpbGUgZ2V0b3B0cyAke2FsbG93ZWRfb3B0aW9uc30gb3B0aW9uczsgZG8KICAgICAgICBjYXNlICIke29wdGlvbnN9IiBpbgogICAgICAgICAgICBwKQogICAgICAgICAgICAgICAgbG9nICJSdW5uaW5nIHN0ZXAgZG5mX3VwZGF0ZV9wa2dzIgogICAgICAgICAgICAgICAgZG5mX3VwZGF0ZV9wa2dzIHBrZ3NfdG9fZXhjbHVkZSByZXRyeV93YWl0X3RpbWUKCiAgICAgICAgICAgICAgICBsb2cgIlJ1bm5pbmcgc3RlcCBkbmZfaW5zdGFsbF9wa2dzIgogICAgICAgICAgICAgICAgZG5mX2luc3RhbGxfcGtncyBwa2dzX3RvX2luc3RhbGwgcmV0cnlfd2FpdF90aW1lCgogICAgICAgICAgICAgICAgbG9nICJSdW5uaW5nIHN0ZXAgY29uZmlndXJlX2RuZl9jcm9uX2pvYiIKICAgICAgICAgICAgICAgIGNvbmZpZ3VyZV9kbmZfY3Jvbl9qb2IKICAgICAgICAgICAgICAgIDs7CiAgICAgICAgICAgIGYpCiAgICAgICAgICAgICAgICBsb2cgIlJ1bm5pbmcgY29uZmlndXJlX2ZpcmV3YWxsZF9ydWxlcyIKICAgICAgICAgICAgICAgIGNvbmZpZ3VyZV9maXJld2FsbGRfcnVsZXMgcG9ydHNfdG9fZW5hYmxlCiAgICAgICAgICAgICAgICA7OwogICAgICAgICAgICB1KQogICAgICAgICAgICAgICAgbG9nICJSdW5uaW5nIHN0ZXAgY29uZmlndXJlX2RldnByb3h5X3NlcnZpY2VzIgogICAgICAgICAgICAgICAgY29uZmlndXJlX2RldnByb3h5X3NlcnZpY2VzCiAgICAgICAgICAgICAgICBlbmFibGVfc2VydmljZXMgc2VydmljZXNfdG9fZW5hYmxlCiAgICAgICAgICAgICAgICA7OwogICAgICAgICAgICBpKQogICAgICAgICAgICAgICAgbG9nICJSdW5uaW5nIHB1bGxfY29udGFpbmVyX2ltYWdlcyIKICAgICAgICAgICAgICAgIHB1bGxfY29udGFpbmVyX2ltYWdlcyBpbWFnZXNfdG9fcHVsbAogICAgICAgICAgICAgICAgOzsKICAgICAgICAgICAgKikKICAgICAgICAgICAgICAgIHVzYWdlIGFsbG93ZWRfb3B0aW9ucwogICAgICAgICAgICAgICAgYWJvcnQgIlVua293biBvcHRpb24gcHJvdmlkZWQiCiAgICAgICAgICAgICAgICA7OwogICAgICAgIGVzYWMKICAgIGRvbmUKICAgIAogICAgZXhpdCAwCn0KCiMgY29uZmlndXJlX3N5c3RlbV9zZXJ2aWNlcyBjcmVhdGVzLCBjb25maWd1cmVzLCBhbmQgZW5hYmxlcyB0aGUgZm9sbG93aW5nIHN5c3RlbWQgc2VydmljZXMgYW5kIHRpbWVycwojIHNlcnZpY2VzCiMJcHJveHkKY29uZmlndXJlX2RldnByb3h5X3NlcnZpY2VzKCkgewoJY29uZmlndXJlX3NlcnZpY2VfcHJveHkKfQoKIyBlbmFibGVfYXJvX3NlcnZpY2VzIGVuYWJsZXMgYWxsIHNlcnZpY2VzIHJlcXVpcmVkIGZvciBhcm8gcnAKZW5hYmxlX2Fyb19zZXJ2aWNlcygpIHsKICAgIGxvZyAic3RhcnRpbmciCgogICAgbG9nICJlbmFibGluZyBhcm8gc2VydmljZXMgJHthcm9fc2VydmljZXNbKl19IgogICAgIyBzaGVsbGNoZWNrIGRpc2FibGU9U0MyMDY4CiAgICBmb3Igc2VydmljZSBpbiAke2Fyb19zZXJ2aWNlc1tAXX07IGRvCiAgICAgICAgbG9nICJFbmFibGluZyAkc2VydmljZSBub3ciCiAgICAgICAgc3lzdGVtY3RsIGVuYWJsZSAiJHNlcnZpY2Uuc2VydmljZSIKICAgIGRvbmUKfQoKIyBjb25maWd1cmVfY2VydHMKY29uZmlndXJlX2NlcnRzKCkgewogICAgbG9nICJzdGFydGluZyIKCgliYXNlNjQgLWQgPDw8IiRQUk9YWUNFUlQiID4vZXRjL3Byb3h5L3Byb3h5LmNydAoJYmFzZTY0IC1kIDw8PCIkUFJPWFlLRVkiID4vZXRjL3Byb3h5L3Byb3h5LmtleQoJYmFzZTY0IC1kIDw8PCIkUFJPWFlDTElFTlRDRVJUIiA+L2V0Yy9wcm94eS9wcm94eS1jbGllbnQuY3J0CgljaG93biAtUiAxMDAwOjEwMDAgL2V0Yy9wcm94eQoJY2htb2QgMDYwMCAvZXRjL3Byb3h5L3Byb3h5LmtleQp9Cgpjb25maWd1cmVfc2VydmljZV9wcm94eSgpIHsKCWxvY2FsIC1yIHN5c2NvbmZpZ19wcm94eV9maWxlbmFtZT0nL2V0Yy9zeXNjb25maWcvcHJveHknCglsb2NhbCAtciBzeXNjb25maWdfcHJveHlfZmlsZT0iUFJPWFlfSU1BR0U9JyRQUk9YWUlNQUdFJyIKCgl3cml0ZV9maWxlIHN5c2NvbmZpZ19wcm94eV9maWxlbmFtZSBzeXNjb25maWdfcHJveHlfZmlsZSB0cnVlCgoJbG9jYWwgLXIgcHJveHlfc2VydmljZV9maWxlbmFtZT0nL2V0Yy9zeXN0ZW1kL3N5c3RlbS9wcm94eS5zZXJ2aWNlJwoJbG9jYWwgLXIgcHJveHlfc2VydmljZV9maWxlPSJbVW5pdF0KQWZ0ZXI9bmV0d29yay1vbmxpbmUudGFyZ2V0CldhbnRzPW5ldHdvcmstb25saW5lLnRhcmdldAoKW1NlcnZpY2VdCkVudmlyb25tZW50RmlsZT0vZXRjL3N5c2NvbmZpZy9wcm94eQpFeGVjU3RhcnRQcmU9LS91c3IvYmluL2RvY2tlciBybSAtZiAlbgpFeGVjU3RhcnQ9L3Vzci9iaW4vZG9ja2VyIHJ1biAtLXJtIC0tbmFtZSAlbiAtcCA0NDM6ODQ0MyAtdiAvZXRjL3Byb3h5Oi9zZWNyZXRzICRQUk9YWV9JTUFHRQpFeGVjU3RvcD0vdXNyL2Jpbi9kb2NrZXIgc3RvcCAlbgpSZXN0YXJ0PWFsd2F5cwpSZXN0YXJ0U2VjPTEKU3RhcnRMaW1pdEludGVydmFsPTAKCltJbnN0YWxsXQpXYW50ZWRCeT1tdWx0aS11c2VyLnRhcmdldCIKCglsb2NhbCAtciBjcm9uX3dlZWtseV9wdWxsX2ltYWdlX2ZpbGVuYW1lPScvZXRjL2Nyb24ud2Vla2x5L3B1bGwtaW1hZ2UnCglsb2NhbCAtciBjcm9uX3dlZWtseV9wdWxsX2ltYWdlX2ZpbGU9IiMhL2Jpbi9iYXNoCmRvY2tlciBwdWxsICRQUk9YWUlNQUdFCnN5c3RlbWN0bCByZXN0YXJ0IHByb3h5LnNlcnZpY2UiCgkKCXdyaXRlX2ZpbGUgY3Jvbl93ZWVrbHlfcHVsbF9pbWFnZV9maWxlbmFtZSBjcm9uX3dlZWtseV9wdWxsX2ltYWdlX2ZpbGUgdHJ1ZQoJY2htb2QgK3ggIiRjcm9uX3dlZWtseV9wdWxsX2ltYWdlX2ZpbGVuYW1lIgoKCWxvY2FsIC1yIGNyb25fZGFpbHlfcmVzdGFydF9wcm94eV9maWxlbmFtZT0nL2V0Yy9jcm9uLmRhaWx5L3Jlc3RhcnQtcHJveHknCglsb2NhbCAtciBjcm9uX2RhaWx5X3Jlc3RhcnRfcHJveHlfZmlsZT0iIyEvYmluL2Jhc2gKc3lzdGVtY3RsIHJlc3RhcnQgcHJveHkuc2VydmljZSIKCQoJd3JpdGVfZmlsZSBjcm9uX2RhaWx5X3Jlc3RhcnRfcHJveHlfZmlsZW5hbWUgY3Jvbl9kYWlseV9yZXN0YXJ0X3Byb3h5X2ZpbGUKCWNobW9kICt4ICIkY3Jvbl9kYWlseV9yZXN0YXJ0X3Byb3h5X2ZpbGVuYW1lIgp9CgpleHBvcnQgQVpVUkVfQ0xPVURfTkFNRT0iJHtBWlVSRUNMT1VETkFNRTo/IkZhaWxlZCB0byBjYXJyeSBvdmVyIHZhcmlhYmxlcyJ9IgoKbWFpbiAiJEAiCg==')))]" }, "provisionAfterExtensions": [ "Microsoft.Azure.Monitor.AzureMonitorLinuxAgent", diff --git a/pkg/deploy/assets/rp-production.json b/pkg/deploy/assets/rp-production.json index 99f72f4d6ff..19c4eed5edc 100644 --- a/pkg/deploy/assets/rp-production.json +++ b/pkg/deploy/assets/rp-production.json @@ -516,7 +516,7 @@ "autoUpgradeMinorVersion": true, "settings": {}, "protectedSettings": { - "script": "[base64(concat(base64ToString('c2V0IC1leAoK'),'ACRRESOURCEID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('acrResourceId')),''')\n','ADMINAPICLIENTCERTCOMMONNAME=$(base64 -d \u003c\u003c\u003c''',base64(parameters('adminApiClientCertCommonName')),''')\n','ARMAPICLIENTCERTCOMMONNAME=$(base64 -d \u003c\u003c\u003c''',base64(parameters('armApiClientCertCommonName')),''')\n','ARMCLIENTID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('armClientId')),''')\n','AZURECLOUDNAME=$(base64 -d \u003c\u003c\u003c''',base64(parameters('azureCloudName')),''')\n','AZURESECPACKQUALYSURL=$(base64 -d \u003c\u003c\u003c''',base64(parameters('azureSecPackQualysUrl')),''')\n','AZURESECPACKVSATENANTID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('azureSecPackVSATenantId')),''')\n','BILLINGE2ESTORAGEACCOUNTID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('billingE2EStorageAccountId')),''')\n','CLUSTERMDMACCOUNT=$(base64 -d \u003c\u003c\u003c''',base64(parameters('clusterMdmAccount')),''')\n','CLUSTERMDSDACCOUNT=$(base64 -d \u003c\u003c\u003c''',base64(parameters('clusterMdsdAccount')),''')\n','CLUSTERMDSDCONFIGVERSION=$(base64 -d \u003c\u003c\u003c''',base64(parameters('clusterMdsdConfigVersion')),''')\n','CLUSTERMDSDNAMESPACE=$(base64 -d \u003c\u003c\u003c''',base64(parameters('clusterMdsdNamespace')),''')\n','CLUSTERPARENTDOMAINNAME=$(base64 -d \u003c\u003c\u003c''',base64(parameters('clusterParentDomainName')),''')\n','DATABASEACCOUNTNAME=$(base64 -d \u003c\u003c\u003c''',base64(parameters('databaseAccountName')),''')\n','DBTOKENCLIENTID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('dbtokenClientId')),''')\n','FLUENTBITIMAGE=$(base64 -d \u003c\u003c\u003c''',base64(parameters('fluentbitImage')),''')\n','FPCLIENTID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('fpClientId')),''')\n','FPSERVICEPRINCIPALID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('fpServicePrincipalId')),''')\n','GATEWAYDOMAINS=$(base64 -d \u003c\u003c\u003c''',base64(parameters('gatewayDomains')),''')\n','GATEWAYRESOURCEGROUPNAME=$(base64 -d \u003c\u003c\u003c''',base64(parameters('gatewayResourceGroupName')),''')\n','GATEWAYSERVICEPRINCIPALID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('gatewayServicePrincipalId')),''')\n','KEYVAULTDNSSUFFIX=$(base64 -d \u003c\u003c\u003c''',base64(parameters('keyvaultDNSSuffix')),''')\n','KEYVAULTPREFIX=$(base64 -d \u003c\u003c\u003c''',base64(parameters('keyvaultPrefix')),''')\n','MDMFRONTENDURL=$(base64 -d \u003c\u003c\u003c''',base64(parameters('mdmFrontendUrl')),''')\n','MDSDENVIRONMENT=$(base64 -d \u003c\u003c\u003c''',base64(parameters('mdsdEnvironment')),''')\n','PORTALACCESSGROUPIDS=$(base64 -d \u003c\u003c\u003c''',base64(parameters('portalAccessGroupIds')),''')\n','PORTALCLIENTID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('portalClientId')),''')\n','PORTALELEVATEDGROUPIDS=$(base64 -d \u003c\u003c\u003c''',base64(parameters('portalElevatedGroupIds')),''')\n','RPFEATURES=$(base64 -d \u003c\u003c\u003c''',base64(parameters('rpFeatures')),''')\n','RPIMAGE=$(base64 -d \u003c\u003c\u003c''',base64(parameters('rpImage')),''')\n','RPMDMACCOUNT=$(base64 -d \u003c\u003c\u003c''',base64(parameters('rpMdmAccount')),''')\n','RPMDSDACCOUNT=$(base64 -d \u003c\u003c\u003c''',base64(parameters('rpMdsdAccount')),''')\n','RPMDSDCONFIGVERSION=$(base64 -d \u003c\u003c\u003c''',base64(parameters('rpMdsdConfigVersion')),''')\n','RPMDSDNAMESPACE=$(base64 -d \u003c\u003c\u003c''',base64(parameters('rpMdsdNamespace')),''')\n','RPPARENTDOMAINNAME=$(base64 -d \u003c\u003c\u003c''',base64(parameters('rpParentDomainName')),''')\n','CLUSTERSINSTALLVIAHIVE=$(base64 -d \u003c\u003c\u003c''',base64(parameters('clustersInstallViaHive')),''')\n','CLUSTERSADOPTBYHIVE=$(base64 -d \u003c\u003c\u003c''',base64(parameters('clustersAdoptByHive')),''')\n','CLUSTERDEFAULTINSTALLERPULLSPEC=$(base64 -d \u003c\u003c\u003c''',base64(parameters('clusterDefaultInstallerPullspec')),''')\n','USECHECKACCESS=$(base64 -d \u003c\u003c\u003c''',base64(parameters('useCheckAccess')),''')\n','ADMINAPICABUNDLE=''',parameters('adminApiCaBundle'),'''\n','ARMAPICABUNDLE=''',parameters('armApiCaBundle'),'''\n','MDMIMAGE=''/genevamdm:2.2024.328.1744-c5fb79-20240328t1935''\n','LOCATION=$(base64 -d \u003c\u003c\u003c''',base64(resourceGroup().location),''')\n','SUBSCRIPTIONID=$(base64 -d \u003c\u003c\u003c''',base64(subscription().subscriptionId),''')\n','RESOURCEGROUPNAME=$(base64 -d \u003c\u003c\u003c''',base64(resourceGroup().name),''')\n','\n',base64ToString('IyEvYmluL2Jhc2gKCnNldCAtbyBlcnJleGl0IFwKICAgIC1vIG5vdW5zZXQKCmlmIFsgIiR7REVCVUc6LWZhbHNlfSIgPT0gdHJ1ZSBdOyB0aGVuCiAgICBzZXQgLXgKZmkKCm1haW4oKSB7CiAgICBwYXJzZV9ydW5fb3B0aW9ucyAiJEAiCgoKICAgIGNvbmZpZ3VyZV9zc2hkCiAgICBjb25maWd1cmVfYW5kX2luc3RhbGxfZG5mX3BrZ3NfcmVwb3MKICAgIGNvbmZpZ3VyZV9kaXNrX3BhcnRpdGlvbnMKICAgIGNvbmZpZ3VyZV9sb2dyb3RhdGUKICAgIGNvbmZpZ3VyZV9zZWxpbnV4CgogICAgbWtkaXIgLXAgL3Zhci9sb2cvam91cm5hbAogICAgbWtkaXIgLXAgL3Zhci9saWIvd2FhZ2VudC9NaWNyb3NvZnQuQXp1cmUuS2V5VmF1bHQuU3RvcmUKCiAgICBjb25maWd1cmVfZmlyZXdhbGxkX3J1bGVzCiAgICBwdWxsX2NvbnRhaW5lcl9pbWFnZXMKICAgIGNvbmZpZ3VyZV9zeXN0ZW1fc2VydmljZXMKICAgIHJlYm9vdF92bQp9Cgp1c2FnZSgpIHsKICAgIGxvY2FsIC1uIG9wdGlvbnM9IiQxIgogICAgbG9nICIkKGJhc2VuYW1lICIkMCIpIFskb3B0aW9uc10KICAgICAgICAtZCBDb25maWd1cmUgRGlzayBQYXJ0aXRpb25zCiAgICAgICAgLXAgQ29uZmlndXJlIHJwbSByZXBvc2l0b3JpZXMsIGltcG9ydCByZXF1aXJlZCBycG0ga2V5cywgdXBkYXRlICYgaW5zdGFsbCBwYWNrYWdlcyB3aXRoIGRuZgogICAgICAgIC1sIENvbmZpZ3VyZSBsb2dyb3RhdGUuY29uZgogICAgICAgIC1zIE1ha2Ugc2VsaW51eCBtb2RpZmljYXRpb25zIHJlcXVpcmVkIGZvciBBUk8gUlAKICAgICAgICAtciBDb25maWd1cmUgc3NoZCAtIEFsbG93IHBhc3N3b3JkIGF1dGhlbnRpY2FpdG9uCiAgICAgICAgLWYgQ29uZmlndXJlIGZpcmV3YWxsZCBkZWZhdWx0IHpvbmUgcnVsZXMKICAgICAgICAtdSBDb25maWd1cmUgc3lzdGVtZCB1bml0IGZpbGVzIGZvciBBUk8gUlAKICAgICAgICAtaSBQdWxsIGNvbnRhaW5lciBpbWFnZXMKCiAgICAgICAgTm90ZTogc3RlcHMgd2lsbCBiZSBleGVjdXRlZCBpbiB0aGUgb3JkZXIgdGhhdCBmbGFncyBhcmUgcHJvdmlkZWQKICAgICIKfQoKIyBwYXJzZV9ydW5fb3B0aW9ucyB0YWtlcyBhbGwgYXJndWVtZW50cyBwYXNzZWQgdG8gbWFpbiBhbmQgcGFyc2VzIHRoZW0KIyBhbGxvd2luZyBpbmRpdmlkdWFsIHN0ZXAocykgdG8gYmUgcmFuLCByYXRoZXIgdGhhbiBhbGwgc3RlcHMKIwojIFRoaXMgaXMgdXNlZnVsIGZvciBsb2NhbCB0ZXN0aW5nLCBvciBwb3NzaWJseSBtb2RpZnlpbmcgdGhlIGJvb3RzdHJhcCBleGVjdXRpb24gdmlhIGVudmlyb25tZW50IHZhcmlhYmxlcyBpbiB0aGUgZGVwbG95bWVudCBwaXBlbGluZQpwYXJzZV9ydW5fb3B0aW9ucygpIHsKICAgICMgc2hlbGxjaGVjayBkaXNhYmxlPVNDMjIwNgogICAgbG9jYWwgLWEgb3B0aW9ucz0oJHsxOi19KQogICAgaWYgWyAiJHsjb3B0aW9uc1tAXX0iIC1lcSAwIF07IHRoZW4KICAgICAgICBsb2cgIlJ1bm5pbmcgYWxsIHN0ZXBzIgogICAgICAgIHJldHVybiAwCiAgICBmaQoKICAgIGxvY2FsIE9QVElORAogICAgbG9jYWwgLXIgYWxsb3dlZF9vcHRpb25zPSJkcGxzcmZ1aSIKICAgIHdoaWxlIGdldG9wdHMgJHthbGxvd2VkX29wdGlvbnN9IG9wdGlvbnM7IGRvCiAgICAgICAgY2FzZSAiJHtvcHRpb25zfSIgaW4KICAgICAgICAgICAgZCkKICAgICAgICAgICAgICAgIGxvZyAiUnVubmluZyBzdGVwIGNvbmZpZ3VyZV9kaXNrX3BhcnRpdGlvbnMiCiAgICAgICAgICAgICAgICBjb25maWd1cmVfZGlza19wYXJ0aXRpb25zCiAgICAgICAgICAgICAgICA7OwogICAgICAgICAgICBwKQogICAgICAgICAgICAgICAgbG9nICJSdW5uaW5nIHN0ZXAgY29uZmlndXJlX2FuZF9pbnN0YWxsX2RuZl9wa2dzX3JlcG9zIgogICAgICAgICAgICAgICAgY29uZmlndXJlX2FuZF9pbnN0YWxsX2RuZl9wa2dzX3JlcG9zCiAgICAgICAgICAgICAgICA7OwogICAgICAgICAgICBsKQogICAgICAgICAgICAgICAgbG9nICJSdW5uaW5nIGNvbmZpZ3VyZV9sb2dyb3RhdGUiCiAgICAgICAgICAgICAgICBjb25maWd1cmVfbG9ncm90YXRlCiAgICAgICAgICAgICAgICA7OwogICAgICAgICAgICBzKQogICAgICAgICAgICAgICAgbG9nICJSdW5uaW5nIGNvbmZpZ3VyZV9zZWxpbnV4IgogICAgICAgICAgICAgICAgY29uZmlndXJlX3NlbGludXgKICAgICAgICAgICAgICAgIDs7CiAgICAgICAgICAgIHIpCiAgICAgICAgICAgICAgICBsb2cgIlJ1bm5pbmcgY29uZmlndXJlX3NzaGQiCiAgICAgICAgICAgICAgICBjb25maWd1cmVfc3NoZAogICAgICAgICAgICAgICAgOzsKICAgICAgICAgICAgZikKICAgICAgICAgICAgICAgIGxvZyAiUnVubmluZyBjb25maWd1cmVfZmlyZXdhbGxkX3J1bGVzIgogICAgICAgICAgICAgICAgY29uZmlndXJlX2ZpcmV3YWxsZF9ydWxlcwogICAgICAgICAgICAgICAgOzsKICAgICAgICAgICAgdSkKICAgICAgICAgICAgICAgIGxvZyAiUnVubmluZyBwdWxsX2NvbnRhaW5lcl9pbWFnZXMgJiBjb25maWd1cmVfc3lzdGVtX3NlcnZpY2VzIgogICAgICAgICAgICAgICAgY29uZmlndXJlX3N5c3RlbV9zZXJ2aWNlcwogICAgICAgICAgICAgICAgOzsKICAgICAgICAgICAgaSkKICAgICAgICAgICAgICAgIGxvZyAiUnVubmluZyBwdWxsX2NvbnRhaW5lcl9pbWFnZXMiCiAgICAgICAgICAgICAgICBwdWxsX2NvbnRhaW5lcl9pbWFnZXMgCiAgICAgICAgICAgICAgICA7OwogICAgICAgICAgICAqKQogICAgICAgICAgICAgICAgdXNhZ2UgYWxsb3dlZF9vcHRpb25zCiAgICAgICAgICAgICAgICBhYm9ydCAiVW5rb3duIG9wdGlvbiBwcm92aWRlZCIKICAgICAgICAgICAgICAgIDs7CiAgICAgICAgZXNhYwogICAgZG9uZQogICAgCiAgICBleGl0IDAKfQoKIyBXZSBuZWVkIHRvIGNvbmZpZ3VyZSBQYXNzd29yZEF1dGhlbnRpY2F0aW9uIHRvIHllcyBpbiBvcmRlciBmb3IgdGhlIFZNU1MgQWNjZXNzIEpJVCB0byB3b3JrCmNvbmZpZ3VyZV9zc2hkKCkgewogICAgbG9nICJzdGFydGluZyIKICAgIGxvZyAic2V0dGluZyBzc2ggcGFzc3dvcmQgYXV0aGVudGljYXRpb24iCiAgICBzZWQgLWkgJ3MvUGFzc3dvcmRBdXRoZW50aWNhdGlvbiBuby9QYXNzd29yZEF1dGhlbnRpY2F0aW9uIHllcy9nJyAvZXRjL3NzaC9zc2hkX2NvbmZpZwoKICAgIHN5c3RlbWN0bCByZWxvYWQgc3NoZC5zZXJ2aWNlCiAgICBzeXN0ZW1jdGwgaXMtYWN0aXZlIC0tcXVpZXQgc3NoZCB8fCBhYm9ydCAic3NoZCBmYWlsZWQgdG8gcmVsb2FkIgp9CgojIGNvbmZpZ3VyZV9hbmRfaW5zdGFsbF9kbmZfcGtnc19yZXBvcwpjb25maWd1cmVfYW5kX2luc3RhbGxfZG5mX3BrZ3NfcmVwb3MoKSB7CiAgICBsb2cgInN0YXJ0aW5nIgoKICAgICMgdHJhbnNhY3Rpb24gYXR0ZW1wdCByZXRyeSB0aW1lIGluIHNlY29uZHMKICAgIGxvY2FsIC1yaSByZXRyeV93YWl0X3RpbWU9NjAKICAgIGNvbmZpZ3VyZV9yaHVpX3JlcG8gcmV0cnlfd2FpdF90aW1lCiAgICBjcmVhdGVfYXp1cmVfcnBtX3JlcG9zIHJldHJ5X3dhaXRfdGltZQoKICAgIGxvY2FsIC1hciBleGNsdWRlX3BrZ3M9KAogICAgICAgICIteCBXQUxpbnV4QWdlbnQiCiAgICAgICAgIi14IFdBTGludXhBZ2VudC11ZGV2IgogICAgKQoKICAgIGRuZl91cGRhdGVfcGtncyBleGNsdWRlX3BrZ3MgcmV0cnlfd2FpdF90aW1lCgogICAgbG9jYWwgLXJhIHJwbV9rZXlzPSgKICAgICAgICBodHRwczovL2RsLmZlZG9yYXByb2plY3Qub3JnL3B1Yi9lcGVsL1JQTS1HUEctS0VZLUVQRUwtOAogICAgICAgIGh0dHBzOi8vcGFja2FnZXMubWljcm9zb2Z0LmNvbS9rZXlzL21pY3Jvc29mdC5hc2MKICAgICkKCiAgICBycG1faW1wb3J0X2tleXMgcnBtX2tleXMgcmV0cnlfd2FpdF90aW1lCgogICAgbG9jYWwgLXJhIHJlcG9fcnBtX3BrZ3M9KAogICAgICAgIGh0dHBzOi8vZGwuZmVkb3JhcHJvamVjdC5vcmcvcHViL2VwZWwvZXBlbC1yZWxlYXNlLWxhdGVzdC04Lm5vYXJjaC5ycG0KICAgICkKCiAgICBsb2NhbCAtcmEgaW5zdGFsbF9wa2dzPSgKICAgICAgICBjbGFtYXYKICAgICAgICBhenNlYy1jbGFtYXYKICAgICAgICBhenNlYy1tb25pdG9yCiAgICAgICAgYXp1cmUtY2xpCiAgICAgICAgYXp1cmUtbWRzZAogICAgICAgIGF6dXJlLXNlY3VyaXR5CiAgICAgICAgcG9kbWFuCiAgICAgICAgcG9kbWFuLWRvY2tlcgogICAgICAgIG9wZW5zc2wtcGVybAogICAgICAgICMgaGFjayAtIHdlIGFyZSBpbnN0YWxsaW5nIHB5dGhvbjMgb24gaG9zdHMgZHVlIHRvIGFuIGlzc3VlIHdpdGggQXp1cmUgTGludXggRXh0ZW5zaW9ucyBodHRwczovL2dpdGh1Yi5jb20vQXp1cmUvYXp1cmUtbGludXgtZXh0ZW5zaW9ucy9wdWxsLzE1MDUKICAgICAgICBweXRob24zCiAgICApCgogICAgZG5mX2luc3RhbGxfcGtncyByZXBvX3JwbV9wa2dzIHJldHJ5X3dhaXRfdGltZQogICAgZG5mX2luc3RhbGxfcGtncyBpbnN0YWxsX3BrZ3MgcmV0cnlfd2FpdF90aW1lCn0KCiMgY29uZmlndXJlX3JodWlfcmVwbwpjb25maWd1cmVfcmh1aV9yZXBvKCkgewogICAgbG9nICJzdGFydGluZyIKCiAgICBsb2NhbCAtcmEgY21kPSgKICAgICAgICBkbmYKICAgICAgICB1cGRhdGUKICAgICAgICAteQogICAgICAgIC0tZGlzYWJsZXJlcG89JyonCiAgICAgICAgLS1lbmFibGVyZXBvPSdyaHVpLW1pY3Jvc29mdC1henVyZSonCiAgICApCgogICAgbG9nICJydW5uaW5nIFJIVUkgcGFja2FnZSB1cGRhdGVzIgogICAgcmV0cnkgY21kICIkMSIKfQoKIyByZXRyeSBBZGRpbmcgcmV0cnkgbG9naWMgdG8geXVtIGNvbW1hbmRzIGluIG9yZGVyIHRvIGF2b2lkIHN0YWxsaW5nIG91dCBvbiByZXNvdXJjZSBsb2NrcwpyZXRyeSgpIHsKICAgIGxvY2FsIC1uIGNtZF9yZXRyeT0iJDEiCiAgICBsb2NhbCAtbiB3YWl0X3RpbWU9IiQyIgoKICAgIGZvciBhdHRlbXB0IGluIHsxLi41fTsgZG8KICAgICAgICBsb2cgImF0dGVtcHQgIyR7YXR0ZW1wdH0gLSAke0ZVTkNOQU1FWzJdfSIKICAgICAgICAke2NtZF9yZXRyeVtAXX0gJgoKICAgICAgICB3YWl0ICQhICYmIGJyZWFrCiAgICAgICAgaWYgW1sgJHthdHRlbXB0fSAtbHQgNSBdXTsgdGhlbgogICAgICAgICAgICBzbGVlcCAiJHdhaXRfdGltZSIKICAgICAgICBlbHNlCiAgICAgICAgICAgIGFib3J0ICJhdHRlbXB0ICMke2F0dGVtcHR9IC0gRmFpbGVkIHRvIHVwZGF0ZSBwYWNrYWdlcyIKICAgICAgICBmaQogICAgZG9uZQp9CgojIGRuZl91cGRhdGVfcGtncwpkbmZfdXBkYXRlX3BrZ3MoKSB7CiAgICBsb2NhbCAtbiBleGNsdWRlcz0iJDEiCiAgICBsb2cgInN0YXJ0aW5nIgoKICAgIGxvY2FsIC1yYSBjbWQ9KAogICAgICAgIGRuZgogICAgICAgIC15CiAgICAgICAgJHtleGNsdWRlc1tAXX0KICAgICAgICB1cGRhdGUKICAgICAgICAtLWFsbG93ZXJhc2luZwogICAgKQoKICAgIGxvZyAiVXBkYXRpbmcgYWxsIHBhY2thZ2VzIgogICAgcmV0cnkgY21kICIkMiIKfQoKIyBkbmZfaW5zdGFsbF9wa2dzCmRuZl9pbnN0YWxsX3BrZ3MoKSB7CiAgICBsb2NhbCAtbiBwa2dzPSIkMSIKICAgIGxvZyAic3RhcnRpbmciCgogICAgbG9jYWwgLXJhIGNtZD0oCiAgICAgICAgZG5mCiAgICAgICAgLXkKICAgICAgICBpbnN0YWxsCiAgICAgICAgJHtwa2dzW0BdfQogICAgKQoKICAgIGxvZyAiQXR0ZW1wdGluZyB0byBpbnN0YWxsIHBhY2thZ2VzOiAke3BrZ3NbKl19IgogICAgcmV0cnkgY21kICIkMiIKfQoKIyBycG1faW1wb3J0X2tleXMKcnBtX2ltcG9ydF9rZXlzKCkgewogICAgbG9jYWwgLW4ga2V5cz0iJDEiCiAgICBsb2cgInN0YXJ0aW5nIgoKCiAgICAjIHNoZWxsY2hlY2sgZGlzYWJsZT1TQzIwNjgKICAgIGZvciBrZXkgaW4gJHtrZXlzW0BdfTsgZG8KICAgICAgICBpZiBbICR7I2tleXNbQF19IC1lcSAwIF07IHRoZW4KICAgICAgICAgICAgYnJlYWsKICAgICAgICBmaQogICAgICAgICAgICBsb2NhbCAtYSBjbWQ9KAogICAgICAgICAgICAgICAgcnBtCiAgICAgICAgICAgICAgICAtLWltcG9ydAogICAgICAgICAgICAgICAgLXYKICAgICAgICAgICAgICAgICIka2V5IgogICAgICAgICAgICApCgogICAgICAgICAgICBsb2cgImF0dGVtcHQgIyRhdHRlbXB0IC0gaW1wb3J0aW5nIHJwbSByZXBvc2l0b3J5IGtleSAka2V5IgogICAgICAgICAgICByZXRyeSBjbWQgIiQyIiAmJiB1bnNldCBrZXkKICAgIGRvbmUKfQoKIyBjb25maWd1cmVfZGlza19wYXJ0aXRpb25zCmNvbmZpZ3VyZV9kaXNrX3BhcnRpdGlvbnMoKSB7CiAgICBsb2cgInN0YXJ0aW5nIgogICAgbG9nICJleHRlbmRpbmcgcGFydGl0aW9uIHRhYmxlIgoKICAgICMgTGludXggYmxvY2sgZGV2aWNlcyBhcmUgaW5jb25zaXN0ZW50bHkgbmFtZWQKICAgICMgaXQncyBkaWZmaWN1bHQgdG8gdGllIHRoZSBsdm0gcHYgdG8gdGhlIHBoeXNpY2FsIGRpc2sgdXNpbmcgL2Rldi9kaXNrIGZpbGVzLCB3aGljaCBpcyB3aHkgbHZzIGlzIHVzZWQgaGVyZQogICAgcGh5c2ljYWxfZGlzaz0iJChsdnMgLW8gZGV2aWNlcyAtYSB8IGhlYWQgLW4yIHwgdGFpbCAtbjEgfCBjdXQgLWQgJyAnIC1mIDMgfCBjdXQgLWQgXCggLWYgMSB8IHRyIC1kICdbOmRpZ2l0Ol0nKSIKICAgIGdyb3dwYXJ0ICIkcGh5c2ljYWxfZGlzayIgMgoKICAgIGxvZyAiZXh0ZW5kaW5nIGZpbGVzeXN0ZW1zIgogICAgbG9nICJleHRlbmRpbmcgcm9vdCBsdm0iCiAgICBsdmV4dGVuZCAtbCArMjAlRlJFRSAvZGV2L3Jvb3R2Zy9yb290bHYKICAgIGxvZyAiZ3Jvd2luZyByb290IGZpbGVzeXN0ZW0iCiAgICB4ZnNfZ3Jvd2ZzIC8KCiAgICBsb2cgImV4dGVuZGluZyB2YXIgbHZtIgogICAgbHZleHRlbmQgLWwgKzEwMCVGUkVFIC9kZXYvcm9vdHZnL3Zhcmx2CiAgICBsb2cgImdyb3dpbmcgdmFyIGZpbGVzeXN0ZW0iCiAgICB4ZnNfZ3Jvd2ZzIC92YXIKfQoKIyBjb25maWd1cmVfbG9ncm90YXRlIGNsb2JiZXJzIC9ldGMvbG9ncm90YXRlLmNvbmYKY29uZmlndXJlX2xvZ3JvdGF0ZSgpIHsKICAgIGxvZyAic3RhcnRpbmciCgogICAgbG9jYWwgLXIgbG9ncm90YXRlX2NvbmZfZmlsZW5hbWU9Jy9ldGMvbG9ncm90YXRlLmNvbmYnCiAgICBsb2NhbCAtciBsb2dyb3RhdGVfY29uZl9maWxlPScjIHNlZSAibWFuIGxvZ3JvdGF0ZSIgZm9yIGRldGFpbHMKIyByb3RhdGUgbG9nIGZpbGVzIHdlZWtseQp3ZWVrbHkKCiMga2VlcCAyIHdlZWtzIHdvcnRoIG9mIGJhY2tsb2dzCnJvdGF0ZSAyCgojIGNyZWF0ZSBuZXcgKGVtcHR5KSBsb2cgZmlsZXMgYWZ0ZXIgcm90YXRpbmcgb2xkIG9uZXMKY3JlYXRlCgojIHVzZSBkYXRlIGFzIGEgc3VmZml4IG9mIHRoZSByb3RhdGVkIGZpbGUKZGF0ZWV4dAoKIyB1bmNvbW1lbnQgdGhpcyBpZiB5b3Ugd2FudCB5b3VyIGxvZyBmaWxlcyBjb21wcmVzc2VkCmNvbXByZXNzCgojIFJQTSBwYWNrYWdlcyBkcm9wIGxvZyByb3RhdGlvbiBpbmZvcm1hdGlvbiBpbnRvIHRoaXMgZGlyZWN0b3J5CmluY2x1ZGUgL2V0Yy9sb2dyb3RhdGUuZAoKIyBubyBwYWNrYWdlcyBvd24gd3RtcCBhbmQgYnRtcCAtLSB3ZSB3aWxsIHJvdGF0ZSB0aGVtIGhlcmUKL3Zhci9sb2cvd3RtcCB7CiAgICBtb250aGx5CiAgICBjcmVhdGUgMDY2NCByb290IHV0bXAKICAgICAgICBtaW5zaXplIDFNCiAgICByb3RhdGUgMQp9CgovdmFyL2xvZy9idG1wIHsKICAgIG1pc3NpbmdvawogICAgbW9udGhseQogICAgY3JlYXRlIDA2MDAgcm9vdCB1dG1wCiAgICByb3RhdGUgMQp9JwoKICAgIHdyaXRlX2ZpbGUgbG9ncm90YXRlX2NvbmZfZmlsZW5hbWUgbG9ncm90YXRlX2NvbmZfZmlsZSB0cnVlCn0KCiMgY3JlYXRlX2F6dXJlX3JwbV9yZXBvcyBjcmVhdGVzIC9ldGMveXVtLnJlcG9zLmQvYXp1cmUucmVwbyByZXBvc2l0b3J5IGZpbGUKY3JlYXRlX2F6dXJlX3JwbV9yZXBvcygpIHsKICAgIGxvZyAic3RhcnRpbmciCgogICAgbG9jYWwgLXIgYXp1cmVfcmVwb19maWxlbmFtZT0nL2V0Yy95dW0ucmVwb3MuZC9henVyZS5yZXBvJwogICAgbG9jYWwgLXIgYXp1cmVfcmVwb19maWxlPSdbYXp1cmUtY2xpXQpuYW1lPWF6dXJlLWNsaQpiYXNldXJsPWh0dHBzOi8vcGFja2FnZXMubWljcm9zb2Z0LmNvbS95dW1yZXBvcy9henVyZS1jbGkKZW5hYmxlZD15ZXMKZ3BnY2hlY2s9eWVzCgpbYXp1cmVjb3JlXQpuYW1lPWF6dXJlY29yZQpiYXNldXJsPWh0dHBzOi8vcGFja2FnZXMubWljcm9zb2Z0LmNvbS95dW1yZXBvcy9henVyZWNvcmUKZW5hYmxlZD15ZXMKZ3BnY2hlY2s9bm8nCgogICAgd3JpdGVfZmlsZSBhenVyZV9yZXBvX2ZpbGVuYW1lIGF6dXJlX3JlcG9fZmlsZSB0cnVlCn0KCiMgY29uZmlndXJlX3NlbGludXgKY29uZmlndXJlX3NlbGludXgoKSB7CiAgICBsb2cgInN0YXJ0aW5nIgoKICAgIGxvY2FsIC1yIHJlbGFiZWw9IiR7MTotZmFsc2V9IgoKICAgIGFscmVhZHlfZGVmaW5lZF9pZ25vcmVfZXJyb3I9IkZpbGUgY29udGV4dCBmb3IgL3Zhci9sb2cvam91cm5hbCgvLiopPyBhbHJlYWR5IGRlZmluZWQiCiAgICBzZW1hbmFnZSBmY29udGV4dCAtYSAtdCB2YXJfbG9nX3QgIi92YXIvbG9nL2pvdXJuYWwoLy4qKT8iIHx8IGxvZyAiJGFscmVhZHlfZGVmaW5lZF9pZ25vcmVfZXJyb3IiCiAgICBjaGNvbiAtUiBzeXN0ZW1fdTpvYmplY3Rfcjp2YXJfbG9nX3Q6czAgL3Zhci9vcHQvbWljcm9zb2Z0L2xpbnV4bW9uYWdlbnQKCiAgICBpZiAiJHJlbGFiZWwiOyB0aGVuCiAgICAgICAgcmVzdG9yZWNvbiAtUkYgL3Zhci9sb2cvKiB8fCBsb2cgIiRhbHJlYWR5X2RlZmluZWRfaWdub3JlX2Vycm9yIgogICAgZmkKfQoKIyBjb25maWd1cmVfZmlyZXdhbGxkX3J1bGVzCmNvbmZpZ3VyZV9maXJld2FsbGRfcnVsZXMoKSB7CiAgICBsb2cgInN0YXJ0aW5nIgoKICAgICMgaHR0cHM6Ly9hY2Nlc3MucmVkaGF0LmNvbS9zZWN1cml0eS9jdmUvY3ZlLTIwMjAtMTM0MDEKICAgIGxvY2FsIC1yIHByZWZpeD0iL2V0Yy9zeXNjdGwuZCIKICAgIGxvY2FsIC1yIGRpc2FibGVfYWNjZXB0X3JhX2NvbmZfZmlsZW5hbWU9IiRwcmVmaXgvMDItZGlzYWJsZS1hY2NlcHQtcmEuY29uZiIKICAgIGxvY2FsIC1yIGRpc2FibGVfYWNjZXB0X3JhX2NvbmZfZmlsZT0ibmV0LmlwdjYuY29uZi5hbGwuYWNjZXB0X3JhPTAiCgogICAgd3JpdGVfZmlsZSBkaXNhYmxlX2FjY2VwdF9yYV9jb25mX2ZpbGVuYW1lIGRpc2FibGVfYWNjZXB0X3JhX2NvbmZfZmlsZSB0cnVlCgogICAgbG9jYWwgLXIgZGlzYWJsZV9jb3JlX2ZpbGVuYW1lPSIkcHJlZml4LzAxLWRpc2FibGUtY29yZS5jb25mIgogICAgbG9jYWwgLXIgZGlzYWJsZV9jb3JlX2ZpbGU9Imtlcm5lbC5jb3JlX3BhdHRlcm4gPSB8L2Jpbi90cnVlCiAgICAiCiAgICB3cml0ZV9maWxlIGRpc2FibGVfY29yZV9maWxlbmFtZSBkaXNhYmxlX2NvcmVfZmlsZSB0cnVlCgogICAgc3lzY3RsIC0tc3lzdGVtCgogICAgbG9jYWwgLXJhIGVuYWJsZV9wb3J0cz0oCiAgICAgICAgIjQ0My90Y3AiCiAgICAgICAgIjQ0NC90Y3AiCiAgICAgICAgIjQ0NS90Y3AiCiAgICAgICAgIjIyMjIvdGNwIgogICAgKQoKICAgIGxvZyAiRW5hYmxpbmcgcG9ydHMgJHtlbmFibGVfcG9ydHNbKl19IG9uIGRlZmF1bHQgZmlyZXdhbGxkIHpvbmUiCiAgICAjIHNoZWxsY2hlY2sgZGlzYWJsZT1TQzIwNjgKICAgIGZvciBwb3J0IGluICR7ZW5hYmxlX3BvcnRzW0BdfTsgZG8KICAgICAgICBsb2cgIkVuYWJsaW5nIHBvcnQgJHBvcnQgbm93IgogICAgICAgIGZpcmV3YWxsLWNtZCAiLS1hZGQtcG9ydD0kcG9ydCIKICAgIGRvbmUKCiAgICBmaXJld2FsbC1jbWQgLS1ydW50aW1lLXRvLXBlcm1hbmVudAp9CgojIHB1bGxfY29udGFpbmVyX2ltYWdlcwpwdWxsX2NvbnRhaW5lcl9pbWFnZXMoKSB7CiAgICBsb2cgInN0YXJ0aW5nIgoKICAgICMgVGhlIG1hbmFnZWQgaWRlbnRpdHkgdGhhdCB0aGUgVk0gcnVucyBhcyBvbmx5IGhhcyBhIHNpbmdsZSByb2xlYXNzaWdubWVudC4KICAgICMgVGhpcyByb2xlIGFzc2lnbm1lbnQgaXMgQUNSUHVsbCB3aGljaCBpcyBub3QgbmVjZXNzYXJpbHkgcHJlc2VudCBpbiB0aGUKICAgICMgc3Vic2NyaXB0aW9uIHdlJ3JlIGRlcGxveWluZyBpbnRvLiAgSWYgdGhlIGlkZW50aXR5IGRvZXMgbm90IGhhdmUgYW55CiAgICAjIHJvbGUgYXNzaWdubWVudHMgc2NvcGVkIG9uIHRoZSBzdWJzY3JpcHRpb24gd2UncmUgZGVwbG95aW5nIGludG8sIGl0IHdpbGwKICAgICMgbm90IHNob3cgb24gYXogbG9naW4gLWksIHdoaWNoIGlzIHdoeSB0aGUgYmVsb3cgbGluZSBpcyBjb21tZW50ZWQuCiAgICAjIGF6IGFjY291bnQgc2V0IC1zICIkU1VCU0NSSVBUSU9OSUQiCiAgICBheiBsb2dpbiAtaSAtLWFsbG93LW5vLXN1YnNjcmlwdGlvbnMKCiAgICAjIFN1cHByZXNzIGVtdWxhdGlvbiBvdXRwdXQgZm9yIHBvZG1hbiBpbnN0ZWFkIG9mIGRvY2tlciBmb3IgYXogYWNyIGNvbXBhdGFiaWxpdHkKICAgIG1rZGlyIC1wIC9ldGMvY29udGFpbmVycy8KICAgIG1rZGlyIC1wIC9yb290Ly5kb2NrZXIKICAgIHRvdWNoIC9ldGMvY29udGFpbmVycy9ub2RvY2tlcgoKCSMgVGhpcyBuYW1lIGlzIHVzZWQgaW4gdGhlIGNhc2UgdGhhdCBheiBhY3IgbG9naW4gc2VhcmNoZXMgZm9yIHRoaXMgaW4gaXQncyBlbnZpcm9ubWVudAogICAgbG9jYWwgLXIgUkVHSVNUUllfQVVUSF9GSUxFPSIvcm9vdC8uZG9ja2VyL2NvbmZpZy5qc29uIgogICAgCiAgICBsb2cgImxvZ2dpbmcgaW50byBwcm9kIGFjciIKICAgIGF6IGFjciBsb2dpbiAtLW5hbWUgIiQoc2VkIC1lICdzfC4qL3x8JyA8PDwiJEFDUlJFU09VUkNFSUQiKSIKCiAgICBNRE1JTUFHRT0iJHtSUElNQUdFJSUvKn0vJHtNRE1JTUFHRSMjKi99IgogICAgZG9ja2VyIHB1bGwgIiRNRE1JTUFHRSIKICAgIGRvY2tlciBwdWxsICIkUlBJTUFHRSIKICAgIGRvY2tlciBwdWxsICIkRkxVRU5UQklUSU1BR0UiCgogICAgYXogbG9nb3V0Cn0KCiMgY29uZmlndXJlX3N5c3RlbV9zZXJ2aWNlcyBjcmVhdGVzLCBjb25maWd1cmVzLCBhbmQgZW5hYmxlcyB0aGUgZm9sbG93aW5nIHN5c3RlbWQgc2VydmljZXMgYW5kIHRpbWVycwojIHNlcnZpY2VzCiMgICBmbHVlbnRiaXQKIyAgIG1kbQojICAgbWRzZAojICAgYXJwLXJwCiMgICBhcm8tZGJ0b2tlbgojICAgYXJvLW1vbml0b3IKIyAgIGFyby1wb3J0YWwKY29uZmlndXJlX3N5c3RlbV9zZXJ2aWNlcygpIHsKICAgIGNvbmZpZ3VyZV9zZXJ2aWNlX2ZsdWVudGJpdAogICAgY29uZmlndXJlX3NlcnZpY2VfbWRtCiAgICBjb25maWd1cmVfdGltZXJzX21kbV9tZHNkCiAgICBjb25maWd1cmVfc2VydmljZV9hcm9fcnAKICAgIGNvbmZpZ3VyZV9zZXJ2aWNlX2Fyb19kYnRva2VuCiAgICBjb25maWd1cmVfc2VydmljZV9hcm9fbW9uaXRvcgogICAgY29uZmlndXJlX3NlcnZpY2VfYXJvX3BvcnRhbAogICAgY29uZmlndXJlX3NlcnZpY2VfbWRzZAp9CgojIGVuYWJsZV9hcm9fc2VydmljZXMgZW5hYmxlcyBhbGwgc2VydmljZXMgcmVxdWlyZWQgZm9yIGFybyBycAplbmFibGVfYXJvX3NlcnZpY2VzKCkgewogICAgbG9nICJzdGFydGluZyIKCiAgICBsb2NhbCAtcmEgYXJvX3NlcnZpY2VzPSgKICAgICAgICAiYXJvLWRidG9rZW4iCiAgICAgICAgImFyby1tb25pdG9yIgogICAgICAgICJhcm8tcG9ydGFsIgogICAgICAgICJhcm8tcnAiCiAgICAgICAgImF1b21zIgogICAgICAgICJhenNlY2QiCiAgICAgICAgImF6c2VjbW9uZCIKICAgICAgICAibWRzZCIKICAgICAgICAibWRtIgogICAgICAgICJjaHJvbnlkIgogICAgICAgICJmbHVlbnRiaXQiCiAgICApCiAgICBsb2cgImVuYWJsaW5nIGFybyBzZXJ2aWNlcyAke2Fyb19zZXJ2aWNlc1sqXX0iCiAgICAjIHNoZWxsY2hlY2sgZGlzYWJsZT1TQzIwNjgKICAgIGZvciBzZXJ2aWNlIGluICR7YXJvX3NlcnZpY2VzW0BdfTsgZG8KICAgICAgICBsb2cgIkVuYWJsaW5nICRzZXJ2aWNlIG5vdyIKICAgICAgICBzeXN0ZW1jdGwgZW5hYmxlICIkc2VydmljZS5zZXJ2aWNlIgogICAgZG9uZQp9CgojIGNvbmZpZ3VyZV9zZXJ2aWNlX2ZsdWVudGJpdApjb25maWd1cmVfc2VydmljZV9mbHVlbnRiaXQoKSB7CiAgICBsb2cgInN0YXJ0aW5nIgogICAgbG9nICJjb25maWd1cmluZyBmbHVlbnRiaXQgc2VydmljZSIKCiAgICBta2RpciAtcCAvZXRjL2ZsdWVudGJpdC8KICAgIG1rZGlyIC1wIC92YXIvbGliL2ZsdWVudAoKICAgIGxvY2FsIC1yIGZsdWVudGJpdF9jb25mX2ZpbGVuYW1lPScvZXRjL2ZsdWVudGJpdC9mbHVlbnRiaXQuY29uZicKICAgIGxvY2FsIC1yIGZsdWVudGJpdF9jb25mX2ZpbGU9IltJTlBVVF0KTmFtZSBzeXN0ZW1kClRhZyBqb3VybmFsZApTeXN0ZW1kX0ZpbHRlciBfQ09NTT1hcm8KREIgL3Zhci9saWIvZmx1ZW50L2pvdXJuYWxkYgoKW0ZJTFRFUl0KCU5hbWUgbW9kaWZ5CglNYXRjaCBqb3VybmFsZAoJUmVtb3ZlX3dpbGRjYXJkIF8KCVJlbW92ZSBUSU1FU1RBTVAKCltGSUxURVJdCglOYW1lIHJld3JpdGVfdGFnCglNYXRjaCBqb3VybmFsZAoJUnVsZSAkTE9HS0lORCBhc3luY3FvcyBhc3luY3FvcyB0cnVlCgpbRklMVEVSXQoJTmFtZSBtb2RpZnkKCU1hdGNoIGFzeW5jcW9zCglSZW1vdmUgQ0xJRU5UX1BSSU5DSVBBTF9OQU1FCglSZW1vdmUgRklMRQoJUmVtb3ZlIENPTVBPTkVOVAoKW0ZJTFRFUl0KCU5hbWUgcmV3cml0ZV90YWcKCU1hdGNoIGpvdXJuYWxkCglSdWxlICRMT0dLSU5EIGlmeGF1ZGl0IGlmeGF1ZGl0IGZhbHNlCgpbT1VUUFVUXQoJTmFtZSBmb3J3YXJkCglNYXRjaCAqCglQb3J0IDI5MjMwIgoKICAgIHdyaXRlX2ZpbGUgZmx1ZW50Yml0X2NvbmZfZmlsZW5hbWUgZmx1ZW50Yml0X2NvbmZfZmlsZSB0cnVlCgogICAgbG9jYWwgLXIgc3lzY29uZmlnX2ZsdWVudGJpdF9maWxlbmFtZT0nL2V0Yy9zeXNjb25maWcvZmx1ZW50Yml0JwogICAgbG9jYWwgLXIgc3lzY29uZmlnX2ZsdWVudGJpdF9maWxlPSJGTFVFTlRCSVRJTUFHRT0kRkxVRU5UQklUSU1BR0UiCgogICAgd3JpdGVfZmlsZSBzeXNjb25maWdfZmx1ZW50Yml0X2ZpbGVuYW1lIHN5c2NvbmZpZ19mbHVlbnRiaXRfZmlsZSB0cnVlCgogICAgbG9jYWwgLXIgZmx1ZW50Yml0X3NlcnZpY2VfZmlsZW5hbWU9Jy9ldGMvc3lzdGVtZC9zeXN0ZW0vZmx1ZW50Yml0LnNlcnZpY2UnCgogICAgbG9jYWwgLXIgZmx1ZW50Yml0X3NlcnZpY2VfZmlsZT0iW1VuaXRdCkFmdGVyPW5ldHdvcmstb25saW5lLnRhcmdldApXYW50cz1uZXR3b3JrLW9ubGluZS50YXJnZXQKU3RhcnRMaW1pdEludGVydmFsU2VjPTAKCltTZXJ2aWNlXQpSZXN0YXJ0U2VjPTFzCkVudmlyb25tZW50RmlsZT0vZXRjL3N5c2NvbmZpZy9mbHVlbnRiaXQKRXhlY1N0YXJ0UHJlPS0vdXNyL2Jpbi9kb2NrZXIgcm0gLWYgJU4KRXhlY1N0YXJ0PS91c3IvYmluL2RvY2tlciBydW4gXAogIC0tc2VjdXJpdHktb3B0IGxhYmVsPWRpc2FibGUgXAogIC0tZW50cnlwb2ludCAvb3B0L3RkLWFnZW50LWJpdC9iaW4vdGQtYWdlbnQtYml0IFwKICAtLW5ldD1ob3N0IFwKICAtLWhvc3RuYW1lICVIIFwKICAtLW5hbWUgJU4gXAogIC0tcm0gXAogIC0tY2FwLWRyb3AgbmV0X3JhdyBcCiAgLXYgL2V0Yy9mbHVlbnRiaXQvZmx1ZW50Yml0LmNvbmY6L2V0Yy9mbHVlbnRiaXQvZmx1ZW50Yml0LmNvbmYgXAogIC12IC92YXIvbGliL2ZsdWVudDovdmFyL2xpYi9mbHVlbnQ6eiBcCiAgLXYgL3Zhci9sb2cvam91cm5hbDovdmFyL2xvZy9qb3VybmFsOnJvIFwKICAtdiAvZXRjL21hY2hpbmUtaWQ6L2V0Yy9tYWNoaW5lLWlkOnJvIFwKICAkRkxVRU5UQklUSU1BR0UgXAogIC1jIC9ldGMvZmx1ZW50Yml0L2ZsdWVudGJpdC5jb25mCgpFeGVjU3RvcD0vdXNyL2Jpbi9kb2NrZXIgc3RvcCAlTgpSZXN0YXJ0PWFsd2F5cwpSZXN0YXJ0U2VjPTUKU3RhcnRMaW1pdEludGVydmFsPTAKCltJbnN0YWxsXQpXYW50ZWRCeT1tdWx0aS11c2VyLnRhcmdldCIKCiAgICB3cml0ZV9maWxlIGZsdWVudGJpdF9jb25mX2ZpbGVuYW1lIGZsdWVudGJpdF9jb25mX2ZpbGUgdHJ1ZQp9CgojIGNvbmZpZ3VyZV9jZXJ0cwpjb25maWd1cmVfY2VydHMoKSB7CiAgICBsb2cgInN0YXJ0aW5nIgoKICAgIG1rZGlyIC9ldGMvYXJvLXJwCiAgICBiYXNlNjQgLWQgPDw8IiRBRE1JTkFQSUNBQlVORExFIiA+L2V0Yy9hcm8tcnAvYWRtaW4tY2EtYnVuZGxlLnBlbQogICAgaWYgW1sgLW4gIiRBUk1BUElDQUJVTkRMRSIgXV07IHRoZW4KICAgIGJhc2U2NCAtZCA8PDwiJEFSTUFQSUNBQlVORExFIiA+L2V0Yy9hcm8tcnAvYXJtLWNhLWJ1bmRsZS5wZW0KICAgIGZpCiAgICBjaG93biAtUiAxMDAwOjEwMDAgL2V0Yy9hcm8tcnAKCiAgICAjIHNldHRpbmcgTU9OSVRPUklOR19HQ1NfQVVUSF9JRF9UWVBFPUF1dGhLZXlWYXVsdCBzZWVtcyB0byBoYXZlIGNhdXNlZCBtZHNkIG5vdAogICAgIyB0byBob25vdXIgU1NMX0NFUlRfRklMRSBhbnkgbW9yZSwgaGVhdmVuIG9ubHkga25vd3Mgd2h5LgogICAgbWtkaXIgLXAgL3Vzci9saWIvc3NsL2NlcnRzCiAgICBjc3BsaXQgLWYgL3Vzci9saWIvc3NsL2NlcnRzL2NlcnQtIC1iICUwM2QucGVtIC9ldGMvcGtpL3Rscy9jZXJ0cy9jYS1idW5kbGUuY3J0IC9eJC8xICJ7Kn0iID4vZGV2L251bGwKICAgIGNfcmVoYXNoIC91c3IvbGliL3NzbC9jZXJ0cwoKIyB3ZSBsZWF2ZSBjbGllbnRJZCBibGFuayBhcyBsb25nIGFzIG9ubHkgMSBtYW5hZ2VkIGlkZW50aXR5IGFzc2lnbmVkIHRvIHZtc3MKIyBpZiB3ZSBoYXZlIG1vcmUgdGhhbiAxLCB3ZSB3aWxsIG5lZWQgdG8gcG9wdWxhdGUgd2l0aCBjbGllbnRJZCB1c2VkIGZvciBvZmYtbm9kZSBzY2FubmluZwogICAgbG9jYWwgLXIgbm9kZXNjYW5fYWdlbnRfZmlsZW5hbWU9Ii9ldGMvZGVmYXVsdC92c2Etbm9kZXNjYW4tYWdlbnQuY29uZmlnIgogICAgbG9jYWwgLXIgbm9kZXNjYW5fYWdlbnRfZmlsZT0iewogICAgXCJOaWNlXCI6IDE5LAogICAgXCJUaW1lb3V0XCI6IDEwODAwLAogICAgXCJDbGllbnRJZFwiOiBcIlwiLAogICAgXCJUZW5hbnRJZFwiOiAkQVpVUkVTRUNQQUNLVlNBVEVOQU5USUQsCiAgICBcIlF1YWx5c1N0b3JlQmFzZVVybFwiOiAkQVpVUkVTRUNQQUNLUVVBTFlTVVJMLAogICAgXCJQcm9jZXNzVGltZW91dFwiOiAzMDAsCiAgICBcIkNvbW1hbmREZWxheVwiOiAwCiAgfSIKCiAgICB3cml0ZV9maWxlIG5vZGVzY2FuX2FnZW50X2ZpbGVuYW1lIG5vZGVzY2FuX2FnZW50X2ZpbGUgdHJ1ZQp9CgojIGNvbmZpZ3VyZV9zZXJ2aWNlX21kbQpjb25maWd1cmVfc2VydmljZV9tZG0oKSB7CiAgICBsb2cgInN0YXJ0aW5nIgogICAgbG9nICJjb25maWd1cmluZyBtZG0gc2VydmljZSIKCiAgICBsb2NhbCAtciBzeXNjb25maWdfbWRtX2ZpbGVuYW1lPSIvZXRjL3N5c2NvbmZpZy9tZG0iCiAgICBsb2NhbCAtciBzeXNjb25maWdfbWRtX2ZpbGU9Ik1ETUZST05URU5EVVJMPSckTURNRlJPTlRFTkRVUkwnCk1ETUlNQUdFPSckTURNSU1BR0UnCk1ETVNPVVJDRUVOVklST05NRU5UPSckTE9DQVRJT04nCk1ETVNPVVJDRVJPTEU9cnAKTURNU09VUkNFUk9MRUlOU1RBTkNFPVwiJChob3N0bmFtZSlcIiIKCiAgICB3cml0ZV9maWxlIHN5c2NvbmZpZ19tZG1fZmlsZW5hbWUgc3lzY29uZmlnX21kbV9maWxlIHRydWUKCiAgICBta2RpciAtcCAvdmFyL2V0dwogICAgbG9jYWwgLXIgbWRtX3NlcnZpY2VfZmlsZW5hbWU9Ii9ldGMvc3lzdGVtZC9zeXN0ZW0vbWRtLnNlcnZpY2UiCiAgICBsb2NhbCAtciBtZG1fc2VydmljZV9maWxlPSJbVW5pdF0KQWZ0ZXI9bmV0d29yay1vbmxpbmUudGFyZ2V0CldhbnRzPW5ldHdvcmstb25saW5lLnRhcmdldAoKW1NlcnZpY2VdCkVudmlyb25tZW50RmlsZT0vZXRjL3N5c2NvbmZpZy9tZG0KRXhlY1N0YXJ0UHJlPS0vdXNyL2Jpbi9kb2NrZXIgcm0gLWYgJU4KRXhlY1N0YXJ0PS91c3IvYmluL2RvY2tlciBydW4gXAogIC0tZW50cnlwb2ludCAvdXNyL3NiaW4vTWV0cmljc0V4dGVuc2lvbiBcCiAgLS1ob3N0bmFtZSAlSCBcCiAgLS1uYW1lICVOIFwKICAtLXJtIFwKICAtLWNhcC1kcm9wIG5ldF9yYXcgXAogIC1tIDJnIFwKICAtdiAvZXRjL21kbS5wZW06L2V0Yy9tZG0ucGVtIFwKICAtdiAvdmFyL2V0dzovdmFyL2V0dzp6IFwKICAkTURNSU1BR0UgXAogIC1DZXJ0RmlsZSAvZXRjL21kbS5wZW0gXAogIC1Gcm9udEVuZFVybCAkTURNRlJPTlRFTkRVUkwgXAogIC1Mb2dnZXIgQ29uc29sZSBcCiAgLUxvZ0xldmVsIFdhcm5pbmcgXAogIC1Qcml2YXRlS2V5RmlsZSAvZXRjL21kbS5wZW0gXAogIC1Tb3VyY2VFbnZpcm9ubWVudCAkTURNU09VUkNFRU5WSVJPTk1FTlQgXAogIC1Tb3VyY2VSb2xlICRNRE1TT1VSQ0VST0xFIFwKICAtU291cmNlUm9sZUluc3RhbmNlICRNRE1TT1VSQ0VST0xFSU5TVEFOQ0UKRXhlY1N0b3A9L3Vzci9iaW4vZG9ja2VyIHN0b3AgJU4KUmVzdGFydD1hbHdheXMKUmVzdGFydFNlYz0xClN0YXJ0TGltaXRJbnRlcnZhbD0wCgpbSW5zdGFsbF0KV2FudGVkQnk9bXVsdGktdXNlci50YXJnZXQiCgogICAgd3JpdGVfZmlsZSBtZG1fc2VydmljZV9maWxlbmFtZSBtZG1fc2VydmljZV9maWxlIHRydWUKfQoKIyBjb25maWd1cmVfdGltZXJzX21kbV9tZHNkCmNvbmZpZ3VyZV90aW1lcnNfbWRtX21kc2QoKSB7CiAgICBsb2cgInN0YXJ0aW5nIgoKICAgIGZvciB2YXIgaW4gIm1kc2QiICJtZG0iOyBkbwogICAgICAgIGxvY2FsIGRvd25sb2FkX2NyZWRzX3NlcnZpY2VfZmlsZW5hbWU9Ii9ldGMvc3lzdGVtZC9zeXN0ZW0vZG93bmxvYWQtJHZhci1jcmVkZW50aWFscy5zZXJ2aWNlIgogICAgICAgIGxvY2FsIGRvd25sb2FkX2NyZWRzX3NlcnZpY2VfZmlsZT0iW1VuaXRdCkRlc2NyaXB0aW9uPVBlcmlvZGljICR2YXIgY3JlZGVudGlhbHMgcmVmcmVzaAoKW1NlcnZpY2VdClR5cGU9b25lc2hvdApFeGVjU3RhcnQ9L3Vzci9sb2NhbC9iaW4vZG93bmxvYWQtY3JlZGVudGlhbHMuc2ggJHZhciIKCiAgICAgICAgd3JpdGVfZmlsZSBkb3dubG9hZF9jcmVkc19zZXJ2aWNlX2ZpbGVuYW1lIGRvd25sb2FkX2NyZWRzX3NlcnZpY2VfZmlsZSB0cnVlCgogICAgICAgIGxvY2FsIGRvd25sb2FkX2NyZWRzX3RpbWVyX2ZpbGVuYW1lPSIvZXRjL3N5c3RlbWQvc3lzdGVtL2Rvd25sb2FkLSR2YXItY3JlZGVudGlhbHMudGltZXIiCiAgICAgICAgbG9jYWwgZG93bmxvYWRfY3JlZHNfdGltZXJfZmlsZT0iW1VuaXRdCkRlc2NyaXB0aW9uPVBlcmlvZGljICR2YXIgY3JlZGVudGlhbHMgcmVmcmVzaApBZnRlcj1uZXR3b3JrLW9ubGluZS50YXJnZXQKV2FudHM9bmV0d29yay1vbmxpbmUudGFyZ2V0CgpbVGltZXJdCk9uQm9vdFNlYz0wbWluCk9uQ2FsZW5kYXI9MC8xMjowMDowMApBY2N1cmFjeVNlYz01cwoKW0luc3RhbGxdCldhbnRlZEJ5PXRpbWVycy50YXJnZXQiCgogICAgICAgIHdyaXRlX2ZpbGUgZG93bmxvYWRfY3JlZHNfdGltZXJfZmlsZW5hbWUgZG93bmxvYWRfY3JlZHNfdGltZXJfZmlsZSB0cnVlCiAgICBkb25lCgogICAgbG9jYWwgLXIgZG93bmxvYWRfY3JlZHNfc2NyaXB0X2ZpbGVuYW1lPSIvdXNyL2xvY2FsL2Jpbi9kb3dubG9hZC1jcmVkZW50aWFscy5zaCIKICAgIGxvY2FsIC1yIGRvd25sb2FkX2NyZWRzX3NjcmlwdF9maWxlPSIjIS9iaW4vYmFzaApzZXQgLWV1CgpDT01QT05FTlQ9XCQxCmVjaG8gXCJEb3dubG9hZCBcJENPTVBPTkVOVCBjcmVkZW50aWFsc1wiCgpURU1QX0RJUj1cIlwkKG1rdGVtcCAtZClcIgpleHBvcnQgQVpVUkVfQ09ORklHX0RJUj1cIlwkKG1rdGVtcCAtZClcIgoKZWNobyBcIkxvZ2dpbmcgaW50byBBenVyZS4uLlwiClJFVFJJRVM9Mwp3aGlsZSBbWyBcJFJFVFJJRVMgLWd0IDAgXV07IGRvCiAgICBpZiBheiBsb2dpbiAtaSAtLWFsbG93LW5vLXN1YnNjcmlwdGlvbnMKICAgIHRoZW4KICAgICAgICBlY2hvIFwiYXogbG9naW4gc3VjY2Vzc2Z1bFwiCiAgICAgICAgYnJlYWsKICAgIGVsc2UKICAgICAgICBlY2hvIFwiYXogbG9naW4gZmFpbGVkLiBSZXRyeWluZy4uLlwiCiAgICAgICAgbGV0IFJFVFJJRVMtPTEKICAgICAgICBzbGVlcCA1CiAgICBmaQpkb25lCgp0cmFwIFwiY2xlYW51cFwiIEVYSVQKCmNsZWFudXAoKSB7CiAgYXogbG9nb3V0CiAgW1sgXCRURU1QX0RJUiA9fiAvdG1wLy4rIF1dICYmIHJtIC1yZiBcJFRFTVBfRElSCiAgW1sgXCRBWlVSRV9DT05GSUdfRElSID1+IC90bXAvLisgXV0gJiYgcm0gLXJmIFwkQVpVUkVfQ09ORklHX0RJUgp9CgppZiBbWyBcJENPTVBPTkVOVCA9IFwibWRtXCIgXV07IHRoZW4KICBDVVJSRU5UX0NFUlRfRklMRT1cIi9ldGMvbWRtLnBlbVwiCmVsaWYgW1sgXCRDT01QT05FTlRcID0gXCJtZHNkXCIgXV07IHRoZW4KICBDVVJSRU5UX0NFUlRfRklMRT1cIi92YXIvbGliL3dhYWdlbnQvTWljcm9zb2Z0LkF6dXJlLktleVZhdWx0LlN0b3JlL21kc2QucGVtXCIKZWxzZQogIGVjaG8gSW52YWxpZCB1c2FnZSAmJiBleGl0IDEKZmkKClNFQ1JFVF9OQU1FPVwicnAtXCR7Q09NUE9ORU5UfVwiCk5FV19DRVJUX0ZJTEU9XCJcJFRFTVBfRElSL1wkQ09NUE9ORU5ULnBlbVwiCmZvciBhdHRlbXB0IGluIHsxLi41fTsgZG8KICBheiBrZXl2YXVsdCBcCiAgICBzZWNyZXQgXAogICAgZG93bmxvYWQgXAogICAgLS1maWxlIFwiXCRORVdfQ0VSVF9GSUxFXCIgXAogICAgLS1pZCBcImh0dHBzOi8vJEtFWVZBVUxUUFJFRklYLXN2Yy4kS0VZVkFVTFRETlNTVUZGSVgvc2VjcmV0cy9cJFNFQ1JFVF9OQU1FXCIgXAogICAgJiYgYnJlYWsKICBpZiBbWyBcJGF0dGVtcHQgLWx0IDUgXV07IHRoZW4gc2xlZXAgMTA7IGVsc2UgZXhpdCAxOyBmaQpkb25lCgppZiBbIC1mIFwkTkVXX0NFUlRfRklMRSBdOyB0aGVuCiAgaWYgW1sgXCRDT01QT05FTlQgPSBcIm1kc2RcIiBdXTsgdGhlbgogICAgY2hvd24gc3lzbG9nOnN5c2xvZyBcJE5FV19DRVJUX0ZJTEUKICBlbHNlCiAgICBzZWQgLWkgLW5lICcxLC9FTkQgQ0VSVElGSUNBVEUvIHAnIFwkTkVXX0NFUlRfRklMRQogIGZpCgogIG5ld19jZXJ0X3NuPVwiXCQob3BlbnNzbCB4NTA5IC1pbiBcIlwkTkVXX0NFUlRfRklMRVwiIC1ub291dCAtc2VyaWFsIHwgYXdrIC1GPSAne3ByaW50IFwkMn0nKVwiCiAgY3VycmVudF9jZXJ0X3NuPVwiXCQob3BlbnNzbCB4NTA5IC1pbiBcIlwkQ1VSUkVOVF9DRVJUX0ZJTEVcIiAtbm9vdXQgLXNlcmlhbCB8IGF3ayAtRj0gJ3twcmludCBcJDJ9JylcIgogIGlmIFtbICEgLXogXCRuZXdfY2VydF9zbiBdXSAmJiBbWyBcJG5ld19jZXJ0X3NuICE9IFwiXCRjdXJyZW50X2NlcnRfc25cIiBdXTsgdGhlbgogICAgZWNobyB1cGRhdGluZyBjZXJ0aWZpY2F0ZSBmb3IgXCRDT01QT05FTlQKICAgIGNobW9kIDA2MDAgXCRORVdfQ0VSVF9GSUxFCiAgICBtdiBcJE5FV19DRVJUX0ZJTEUgXCRDVVJSRU5UX0NFUlRfRklMRQogIGZpCmVsc2UKICBlY2hvIEZhaWxlZCB0byByZWZyZXNoIGNlcnRpZmljYXRlIGZvciBcJENPTVBPTkVOVCAmJiBleGl0IDEKZmkiCgogICAgd3JpdGVfZmlsZSBkb3dubG9hZF9jcmVkc19zY3JpcHRfZmlsZW5hbWUgZG93bmxvYWRfY3JlZHNfc2NyaXB0X2ZpbGUgdHJ1ZQoKICAgIGNobW9kIHUreCAvdXNyL2xvY2FsL2Jpbi9kb3dubG9hZC1jcmVkZW50aWFscy5zaAoKICAgIHN5c3RlbWN0bCBlbmFibGUgZG93bmxvYWQtbWRzZC1jcmVkZW50aWFscy50aW1lcgogICAgc3lzdGVtY3RsIGVuYWJsZSBkb3dubG9hZC1tZG0tY3JlZGVudGlhbHMudGltZXIKCiAgICAvdXNyL2xvY2FsL2Jpbi9kb3dubG9hZC1jcmVkZW50aWFscy5zaCBtZHNkCiAgICAvdXNyL2xvY2FsL2Jpbi9kb3dubG9hZC1jcmVkZW50aWFscy5zaCBtZG0KCiAgICBsb2NhbCAtciBNRFNEQ0VSVElGSUNBVEVTQU49IiQob3BlbnNzbCB4NTA5IC1pbiAvdmFyL2xpYi93YWFnZW50L01pY3Jvc29mdC5BenVyZS5LZXlWYXVsdC5TdG9yZS9tZHNkLnBlbSAtbm9vdXQgLXN1YmplY3QgfCBzZWQgLWUgJ3MvLipDTiA9IC8vJykiCiAgICBsb2NhbCAtciB3YXRjaF9tZG1fY3JlZHNfc2VydmljZV9maWxlbmFtZT0iL2V0Yy9zeXN0ZW1kL3N5c3RlbS93YXRjaC1tZG0tY3JlZGVudGlhbHMuc2VydmljZSIKICAgIGxvY2FsIC1yIHdhdGNoX21kbV9jcmVkc19zZXJ2aWNlX2ZpbGU9IltVbml0XQpEZXNjcmlwdGlvbj1XYXRjaCBmb3IgY2hhbmdlcyBpbiBtZG0ucGVtIGFuZCByZXN0YXJ0cyB0aGUgbWRtIHNlcnZpY2UKCltTZXJ2aWNlXQpUeXBlPW9uZXNob3QKRXhlY1N0YXJ0PS91c3IvYmluL3N5c3RlbWN0bCByZXN0YXJ0IG1kbS5zZXJ2aWNlCgpbSW5zdGFsbF0KV2FudGVkQnk9bXVsdGktdXNlci50YXJnZXQiCgogICAgd3JpdGVfZmlsZSB3YXRjaF9tZG1fY3JlZHNfc2VydmljZV9maWxlbmFtZSB3YXRjaF9tZG1fY3JlZHNfc2VydmljZV9maWxlIHRydWUKCiAgICBsb2NhbCAtciB3YXRjaF9tZG1fY3JlZHNfcGF0aF9maWxlbmFtZT0nL2V0Yy9zeXN0ZW1kL3N5c3RlbS93YXRjaC1tZG0tY3JlZGVudGlhbHMucGF0aCcKICAgIGxvY2FsIC1yIHdhdGNoX21kbV9jcmVkc19wYXRoX2ZpbGU9J1tQYXRoXQpQYXRoTW9kaWZpZWQ9L2V0Yy9tZG0ucGVtCgpbSW5zdGFsbF0KV2FudGVkQnk9bXVsdGktdXNlci50YXJnZXQnCgogICAgd3JpdGVfZmlsZSB3YXRjaF9tZG1fY3JlZHNfcGF0aF9maWxlbmFtZSB3YXRjaF9tZG1fY3JlZHNfcGF0aF9maWxlIHRydWUKCiAgICBsb2NhbCAtciB3YXRjaF9tZG1fY3JlZHM9J3dhdGNoLW1kbS1jcmVkZW50aWFscy5wYXRoJwogICAgc3lzdGVtY3RsIGVuYWJsZSAiJHdhdGNoX21kbV9jcmVkcyIgfHwgYWJvcnQgImZhaWxlZCB0byBlbmFibGUgJHdhdGNoX21kbV9jcmVkcyIKICAgIHN5c3RlbWN0bCBzdGFydCAiJHdhdGNoX21kbV9jcmVkcyIgfHwgYWJvcnQgImZhaWxlZCB0byBzdGFydCAkd2F0Y2hfbWRtX2NyZWRzIgp9CgojIGNvbmZpZ3VyZV9zZXJ2aWNlX2Fyb19ycApjb25maWd1cmVfc2VydmljZV9hcm9fcnAoKSB7CiAgICBsb2cgInN0YXJ0aW5nIgoKICAgIGxvY2FsIC1yIGFyb19ycF9jb25mX2ZpbGVuYW1lPScvZXRjL3N5c2NvbmZpZy9hcm8tcnAnCiAgICBsb2NhbCAtciBhcm9fcnBfY29uZl9maWxlPSJBQ1JfUkVTT1VSQ0VfSUQ9JyRBQ1JSRVNPVVJDRUlEJwpBRE1JTl9BUElfQ0xJRU5UX0NFUlRfQ09NTU9OX05BTUU9JyRBRE1JTkFQSUNMSUVOVENFUlRDT01NT05OQU1FJwpBUk1fQVBJX0NMSUVOVF9DRVJUX0NPTU1PTl9OQU1FPSckQVJNQVBJQ0xJRU5UQ0VSVENPTU1PTk5BTUUnCkFaVVJFX0FSTV9DTElFTlRfSUQ9JyRBUk1DTElFTlRJRCcKQVpVUkVfRlBfQ0xJRU5UX0lEPSckRlBDTElFTlRJRCcKQVpVUkVfRlBfU0VSVklDRV9QUklOQ0lQQUxfSUQ9JyRGUFNFUlZJQ0VQUklOQ0lQQUxJRCcKQklMTElOR19FMkVfU1RPUkFHRV9BQ0NPVU5UX0lEPSckQklMTElOR0UyRVNUT1JBR0VBQ0NPVU5USUQnCkNMVVNURVJfTURNX0FDQ09VTlQ9JyRDTFVTVEVSTURNQUNDT1VOVCcKQ0xVU1RFUl9NRE1fTkFNRVNQQUNFPVJQCkNMVVNURVJfTURTRF9BQ0NPVU5UPSckQ0xVU1RFUk1EU0RBQ0NPVU5UJwpDTFVTVEVSX01EU0RfQ09ORklHX1ZFUlNJT049JyRDTFVTVEVSTURTRENPTkZJR1ZFUlNJT04nCkNMVVNURVJfTURTRF9OQU1FU1BBQ0U9JyRDTFVTVEVSTURTRE5BTUVTUEFDRScKREFUQUJBU0VfQUNDT1VOVF9OQU1FPSckREFUQUJBU0VBQ0NPVU5UTkFNRScKRE9NQUlOX05BTUU9JyRMT0NBVElPTi4kQ0xVU1RFUlBBUkVOVERPTUFJTk5BTUUnCkdBVEVXQVlfRE9NQUlOUz0nJEdBVEVXQVlET01BSU5TJwpHQVRFV0FZX1JFU09VUkNFR1JPVVA9JyRHQVRFV0FZUkVTT1VSQ0VHUk9VUE5BTUUnCktFWVZBVUxUX1BSRUZJWD0nJEtFWVZBVUxUUFJFRklYJwpNRE1fQUNDT1VOVD0nJFJQTURNQUNDT1VOVCcKTURNX05BTUVTUEFDRT1SUApNRFNEX0VOVklST05NRU5UPSckTURTREVOVklST05NRU5UJwpSUF9GRUFUVVJFUz0nJFJQRkVBVFVSRVMnClJQSU1BR0U9JyRSUElNQUdFJwpBUk9fSU5TVEFMTF9WSUFfSElWRT0nJENMVVNURVJTSU5TVEFMTFZJQUhJVkUnCkFST19ISVZFX0RFRkFVTFRfSU5TVEFMTEVSX1BVTExTUEVDPSckQ0xVU1RFUkRFRkFVTFRJTlNUQUxMRVJQVUxMU1BFQycKQVJPX0FET1BUX0JZX0hJVkU9JyRDTFVTVEVSU0FET1BUQllISVZFJwpVU0VfQ0hFQ0tBQ0NFU1M9JyRVU0VDSEVDS0FDQ0VTUyciCgogICAgd3JpdGVfZmlsZSBhcm9fcnBfY29uZl9maWxlbmFtZSBhcm9fcnBfY29uZl9maWxlIHRydWUKCiAgICBsb2NhbCAtciBhcm9fcnBfc2VydmljZV9maWxlbmFtZT0nL2V0Yy9zeXN0ZW1kL3N5c3RlbS9hcm8tcnAuc2VydmljZScKICAgIGxvY2FsIC1yIGFyb19ycF9zZXJ2aWNlX2ZpbGU9IltVbml0XQpBZnRlcj1uZXR3b3JrLW9ubGluZS50YXJnZXQKV2FudHM9bmV0d29yay1vbmxpbmUudGFyZ2V0CgpbU2VydmljZV0KRW52aXJvbm1lbnRGaWxlPS9ldGMvc3lzY29uZmlnL2Fyby1ycApFeGVjU3RhcnRQcmU9LS91c3IvYmluL2RvY2tlciBybSAtZiAlTgpFeGVjU3RhcnQ9L3Vzci9iaW4vZG9ja2VyIHJ1biBcCiAgLS1ob3N0bmFtZSAlSCBcCiAgLS1uYW1lICVOIFwKICAtLXJtIFwKICAtLWNhcC1kcm9wIG5ldF9yYXcgXAogIC1lIEFDUl9SRVNPVVJDRV9JRCBcCiAgLWUgQURNSU5fQVBJX0NMSUVOVF9DRVJUX0NPTU1PTl9OQU1FIFwKICAtZSBBUk1fQVBJX0NMSUVOVF9DRVJUX0NPTU1PTl9OQU1FIFwKICAtZSBBWlVSRV9BUk1fQ0xJRU5UX0lEIFwKICAtZSBBWlVSRV9GUF9DTElFTlRfSUQgXAogIC1lIEJJTExJTkdfRTJFX1NUT1JBR0VfQUNDT1VOVF9JRCBcCiAgLWUgQ0xVU1RFUl9NRE1fQUNDT1VOVCBcCiAgLWUgQ0xVU1RFUl9NRE1fTkFNRVNQQUNFIFwKICAtZSBDTFVTVEVSX01EU0RfQUNDT1VOVCBcCiAgLWUgQ0xVU1RFUl9NRFNEX0NPTkZJR19WRVJTSU9OIFwKICAtZSBDTFVTVEVSX01EU0RfTkFNRVNQQUNFIFwKICAtZSBEQVRBQkFTRV9BQ0NPVU5UX05BTUUgXAogIC1lIERPTUFJTl9OQU1FIFwKICAtZSBHQVRFV0FZX0RPTUFJTlMgXAogIC1lIEdBVEVXQVlfUkVTT1VSQ0VHUk9VUCBcCiAgLWUgS0VZVkFVTFRfUFJFRklYIFwKICAtZSBNRE1fQUNDT1VOVCBcCiAgLWUgTURNX05BTUVTUEFDRSBcCiAgLWUgTURTRF9FTlZJUk9OTUVOVCBcCiAgLWUgUlBfRkVBVFVSRVMgXAogIC1lIEFST19JTlNUQUxMX1ZJQV9ISVZFIFwKICAtZSBBUk9fSElWRV9ERUZBVUxUX0lOU1RBTExFUl9QVUxMU1BFQyBcCiAgLWUgQVJPX0FET1BUX0JZX0hJVkUgXAogIC1lIFVTRV9DSEVDS0FDQ0VTUyBcCiAgLW0gMmcgXAogIC1wIDQ0Mzo4NDQzIFwKICAtdiAvZXRjL2Fyby1ycDovZXRjL2Fyby1ycCBcCiAgLXYgL3J1bi9zeXN0ZW1kL2pvdXJuYWw6L3J1bi9zeXN0ZW1kL2pvdXJuYWwgXAogIC12IC92YXIvZXR3Oi92YXIvZXR3OnogXAogICRSUElNQUdFIFwKICBycApFeGVjU3RvcD0vdXNyL2Jpbi9kb2NrZXIgc3RvcCAtdCAzNjAwICVOClRpbWVvdXRTdG9wU2VjPTM2MDAKUmVzdGFydD1hbHdheXMKUmVzdGFydFNlYz0xClN0YXJ0TGltaXRJbnRlcnZhbD0wCgpbSW5zdGFsbF0KV2FudGVkQnk9bXVsdGktdXNlci50YXJnZXQiCgogICAgd3JpdGVfZmlsZSBhcm9fcnBfc2VydmljZV9maWxlbmFtZSBhcm9fcnBfY29uZl9maWxlIHRydWUKfQoKIyBjb25maWd1cmVfc2VydmljZV9hcm9fZGJ0b2tlbgpjb25maWd1cmVfc2VydmljZV9hcm9fZGJ0b2tlbigpIHsKICAgIGxvZyAic3RhcnRpbmciCgogICAgbG9jYWwgLXIgYXJvX2RidG9rZW5fc2VydmljZV9jb25mX2ZpbGVuYW1lPScvZXRjL3N5c2NvbmZpZy9hcm8tZGJ0b2tlbicKICAgIGxvY2FsIC1yIGFyb19kYnRva2VuX3NlcnZpY2VfY29uZl9maWxlPSJEQVRBQkFTRV9BQ0NPVU5UX05BTUU9JyREQVRBQkFTRUFDQ09VTlROQU1FJwpBWlVSRV9EQlRPS0VOX0NMSUVOVF9JRD0nJERCVE9LRU5DTElFTlRJRCcKQVpVUkVfR0FURVdBWV9TRVJWSUNFX1BSSU5DSVBBTF9JRD0nJEdBVEVXQVlTRVJWSUNFUFJJTkNJUEFMSUQnCktFWVZBVUxUX1BSRUZJWD0nJEtFWVZBVUxUUFJFRklYJwpNRE1fQUNDT1VOVD0nJFJQTURNQUNDT1VOVCcKTURNX05BTUVTUEFDRT1EQlRva2VuClJQSU1BR0U9JyRSUElNQUdFJyIKCiAgICB3cml0ZV9maWxlIGFyb19kYnRva2VuX3NlcnZpY2VfY29uZl9maWxlbmFtZSBhcm9fZGJ0b2tlbl9zZXJ2aWNlX2NvbmZfZmlsZSB0cnVlCgogICAgbG9jYWwgLXIgYXJvX2RidG9rZW5fc2VydmljZV9maWxlbmFtZT0nL2V0Yy9zeXN0ZW1kL3N5c3RlbS9hcm8tZGJ0b2tlbi5zZXJ2aWNlJwogICAgbG9jYWwgLXIgYXJvX2RidG9rZW5fc2VydmljZV9maWxlPSJbVW5pdF0KQWZ0ZXI9bmV0d29yay1vbmxpbmUudGFyZ2V0CldhbnRzPW5ldHdvcmstb25saW5lLnRhcmdldAoKW1NlcnZpY2VdCkVudmlyb25tZW50RmlsZT0vZXRjL3N5c2NvbmZpZy9hcm8tZGJ0b2tlbgpFeGVjU3RhcnRQcmU9LS91c3IvYmluL2RvY2tlciBybSAtZiAlTgpFeGVjU3RhcnQ9L3Vzci9iaW4vZG9ja2VyIHJ1biBcCiAgLS1ob3N0bmFtZSAlSCBcCiAgLS1uYW1lICVOIFwKICAtLXJtIFwKICAtLWNhcC1kcm9wIG5ldF9yYXcgXAogIC1lIEFaVVJFX0dBVEVXQVlfU0VSVklDRV9QUklOQ0lQQUxfSUQgXAogIC1lIERBVEFCQVNFX0FDQ09VTlRfTkFNRSBcCiAgLWUgQVpVUkVfREJUT0tFTl9DTElFTlRfSUQgXAogIC1lIEtFWVZBVUxUX1BSRUZJWCBcCiAgLWUgTURNX0FDQ09VTlQgXAogIC1lIE1ETV9OQU1FU1BBQ0UgXAogIC1tIDJnIFwKICAtcCA0NDU6ODQ0NSBcCiAgLXYgL3J1bi9zeXN0ZW1kL2pvdXJuYWw6L3J1bi9zeXN0ZW1kL2pvdXJuYWwgXAogIC12IC92YXIvZXR3Oi92YXIvZXR3OnogXAogICRSUElNQUdFIFwKICBkYnRva2VuCkV4ZWNTdG9wPS91c3IvYmluL2RvY2tlciBzdG9wIC10IDM2MDAgJU4KVGltZW91dFN0b3BTZWM9MzYwMApSZXN0YXJ0PWFsd2F5cwpSZXN0YXJ0U2VjPTEKU3RhcnRMaW1pdEludGVydmFsPTAKCltJbnN0YWxsXQpXYW50ZWRCeT1tdWx0aS11c2VyLnRhcmdldCIKCiAgICB3cml0ZV9maWxlIGFyb19kYnRva2VuX3NlcnZpY2VfZmlsZW5hbWUgYXJvX2RidG9rZW5fc2VydmljZV9maWxlIHRydWUKfQoKIyBjb25maWd1cmVfc2VydmljZV9hcm9fbW9uaXRvcgpjb25maWd1cmVfc2VydmljZV9hcm9fbW9uaXRvcigpIHsKICAgIGxvZyAic3RhcnRpbmciCiAgICBsb2cgImNvbmZpZ3VyaW5nIGFyby1tb25pdG9yIHNlcnZpY2UiCgogICAgIyBET01BSU5fTkFNRSwgQ0xVU1RFUl9NRFNEX0FDQ09VTlQsIENMVVNURVJfTURTRF9DT05GSUdfVkVSU0lPTiwgR0FURVdBWV9ET01BSU5TLCBHQVRFV0FZX1JFU09VUkNFR1JPVVAsIE1EU0RfRU5WSVJPTk1FTlQgQ0xVU1RFUl9NRFNEX05BTUVTUEFDRQogICAgIyBhcmUgbm90IHVzZWQsIGJ1dCBjYW4ndCBlYXNpbHkgYmUgcmVmYWN0b3JlZCBvdXQuIFNob3VsZCBiZSByZXZpc2l0ZWQgaW4gdGhlIGZ1dHVyZS4KICAgIGxvY2FsIC1yIGFyb19tb25pdG9yX3NlcnZpY2VfY29uZl9maWxlbmFtZT0nL2V0Yy9zeXNjb25maWcvYXJvLW1vbml0b3InCiAgICBsb2NhbCAtciBhcm9fbW9uaXRvcl9zZXJ2aWNlX2NvbmZfZmlsZT0iQVpVUkVfRlBfQ0xJRU5UX0lEPSckRlBDTElFTlRJRCcKRE9NQUlOX05BTUU9JyRMT0NBVElPTi4kQ0xVU1RFUlBBUkVOVERPTUFJTk5BTUUnCkNMVVNURVJfTURTRF9BQ0NPVU5UPSckQ0xVU1RFUk1EU0RBQ0NPVU5UJwpDTFVTVEVSX01EU0RfQ09ORklHX1ZFUlNJT049JyRDTFVTVEVSTURTRENPTkZJR1ZFUlNJT04nCkdBVEVXQVlfRE9NQUlOUz0nJEdBVEVXQVlET01BSU5TJwpHQVRFV0FZX1JFU09VUkNFR1JPVVA9JyRHQVRFV0FZUkVTT1VSQ0VHUk9VUE5BTUUnCk1EU0RfRU5WSVJPTk1FTlQ9JyRNRFNERU5WSVJPTk1FTlQnCkNMVVNURVJfTURTRF9OQU1FU1BBQ0U9JyRDTFVTVEVSTURTRE5BTUVTUEFDRScKQ0xVU1RFUl9NRE1fQUNDT1VOVD0nJENMVVNURVJNRE1BQ0NPVU5UJwpDTFVTVEVSX01ETV9OQU1FU1BBQ0U9QkJNCkRBVEFCQVNFX0FDQ09VTlRfTkFNRT0nJERBVEFCQVNFQUNDT1VOVE5BTUUnCktFWVZBVUxUX1BSRUZJWD0nJEtFWVZBVUxUUFJFRklYJwpNRE1fQUNDT1VOVD0nJFJQTURNQUNDT1VOVCcKTURNX05BTUVTUEFDRT1CQk0KUlBJTUFHRT0nJFJQSU1BR0UnIgoKICAgIHdyaXRlX2ZpbGUgYXJvX21vbml0b3Jfc2VydmljZV9jb25mX2ZpbGVuYW1lIGFyb19tb25pdG9yX3NlcnZpY2VfY29uZl9maWxlIHRydWUKCiAgICBsb2NhbCAtciBhcm9fbW9uaXRvcl9zZXJ2aWNlX2ZpbGVuYW1lPScvZXRjL3N5c3RlbWQvc3lzdGVtL2Fyby1tb25pdG9yLnNlcnZpY2UnCiAgICBsb2NhbCAtciBhcm9fbW9uaXRvcl9zZXJ2aWNlX2ZpbGU9IltVbml0XQpBZnRlcj1uZXR3b3JrLW9ubGluZS50YXJnZXQKV2FudHM9bmV0d29yay1vbmxpbmUudGFyZ2V0CgpbU2VydmljZV0KRW52aXJvbm1lbnRGaWxlPS9ldGMvc3lzY29uZmlnL2Fyby1tb25pdG9yCkV4ZWNTdGFydFByZT0tL3Vzci9iaW4vZG9ja2VyIHJtIC1mICVOCkV4ZWNTdGFydD0vdXNyL2Jpbi9kb2NrZXIgcnVuIFwKICAtLWhvc3RuYW1lICVIIFwKICAtLW5hbWUgJU4gXAogIC0tcm0gXAogIC0tY2FwLWRyb3AgbmV0X3JhdyBcCiAgLWUgQVpVUkVfRlBfQ0xJRU5UX0lEIFwKICAtZSBET01BSU5fTkFNRSBcCiAgLWUgQ0xVU1RFUl9NRFNEX0FDQ09VTlQgXAogIC1lIENMVVNURVJfTURTRF9DT05GSUdfVkVSU0lPTiBcCiAgLWUgR0FURVdBWV9ET01BSU5TIFwKICAtZSBHQVRFV0FZX1JFU09VUkNFR1JPVVAgXAogIC1lIE1EU0RfRU5WSVJPTk1FTlQgXAogIC1lIENMVVNURVJfTURTRF9OQU1FU1BBQ0UgXAogIC1lIENMVVNURVJfTURNX0FDQ09VTlQgXAogIC1lIENMVVNURVJfTURNX05BTUVTUEFDRSBcCiAgLWUgREFUQUJBU0VfQUNDT1VOVF9OQU1FIFwKICAtZSBLRVlWQVVMVF9QUkVGSVggXAogIC1lIE1ETV9BQ0NPVU5UIFwKICAtZSBNRE1fTkFNRVNQQUNFIFwKICAtbSAyLjVnIFwKICAtdiAvcnVuL3N5c3RlbWQvam91cm5hbDovcnVuL3N5c3RlbWQvam91cm5hbCBcCiAgLXYgL3Zhci9ldHc6L3Zhci9ldHc6eiBcCiAgJFJQSU1BR0UgXAogIG1vbml0b3IKUmVzdGFydD1hbHdheXMKUmVzdGFydFNlYz0xClN0YXJ0TGltaXRJbnRlcnZhbD0wCgpbSW5zdGFsbF0KV2FudGVkQnk9bXVsdGktdXNlci50YXJnZXQiCgogICAgd3JpdGVfZmlsZSBhcm9fbW9uaXRvcl9zZXJ2aWNlX2ZpbGVuYW1lIGFyb19tb25pdG9yX3NlcnZpY2VfZmlsZSB0cnVlCn0KCiMgY29uZmlndXJlX3NlcnZpY2VfYXJvX3BvcnRhbApjb25maWd1cmVfc2VydmljZV9hcm9fcG9ydGFsKCkgewogICAgbG9nICJzdGFydGluZyIKCiAgICBsb2NhbCAtciBhcm9fcG9ydGFsX3NlcnZpY2VfY29uZl9maWxlbmFtZT0nL2V0Yy9zeXNjb25maWcvYXJvLXBvcnRhbCcKICAgIGxvY2FsIC1yIGFyb19wb3J0YWxfc2VydmljZV9jb25mX2ZpbGU9IkFaVVJFX1BPUlRBTF9BQ0NFU1NfR1JPVVBfSURTPSckUE9SVEFMQUNDRVNTR1JPVVBJRFMnCkFaVVJFX1BPUlRBTF9DTElFTlRfSUQ9JyRQT1JUQUxDTElFTlRJRCcKQVpVUkVfUE9SVEFMX0VMRVZBVEVEX0dST1VQX0lEUz0nJFBPUlRBTEVMRVZBVEVER1JPVVBJRFMnCkRBVEFCQVNFX0FDQ09VTlRfTkFNRT0nJERBVEFCQVNFQUNDT1VOVE5BTUUnCktFWVZBVUxUX1BSRUZJWD0nJEtFWVZBVUxUUFJFRklYJwpNRE1fQUNDT1VOVD0nJFJQTURNQUNDT1VOVCcKTURNX05BTUVTUEFDRT1Qb3J0YWwKUE9SVEFMX0hPU1ROQU1FPSckTE9DQVRJT04uYWRtaW4uJFJQUEFSRU5URE9NQUlOTkFNRScKUlBJTUFHRT0nJFJQSU1BR0UnIgoKICAgIHdyaXRlX2ZpbGUgYXJvX3BvcnRhbF9zZXJ2aWNlX2NvbmZfZmlsZW5hbWUgYXJvX3BvcnRhbF9zZXJ2aWNlX2NvbmZfZmlsZSB0cnVlCgogICAgbG9jYWwgLXIgYXJvX3BvcnRhbF9zZXJ2aWNlX2ZpbGVuYW1lPScvZXRjL3N5c3RlbWQvc3lzdGVtL2Fyby1wb3J0YWwuc2VydmljZScKICAgIGxvY2FsIC1yIGFyb19wb3J0YWxfc2VydmljZV9maWxlPSJbVW5pdF0KQWZ0ZXI9bmV0d29yay1vbmxpbmUudGFyZ2V0CldhbnRzPW5ldHdvcmstb25saW5lLnRhcmdldApTdGFydExpbWl0SW50ZXJ2YWw9MAoKW1NlcnZpY2VdCkVudmlyb25tZW50RmlsZT0vZXRjL3N5c2NvbmZpZy9hcm8tcG9ydGFsCkV4ZWNTdGFydFByZT0tL3Vzci9iaW4vZG9ja2VyIHJtIC1mICVOCkV4ZWNTdGFydD0vdXNyL2Jpbi9kb2NrZXIgcnVuIFwKICAtLWhvc3RuYW1lICVIIFwKICAtLW5hbWUgJU4gXAogIC0tcm0gXAogIC0tY2FwLWRyb3AgbmV0X3JhdyBcCiAgLWUgQVpVUkVfUE9SVEFMX0FDQ0VTU19HUk9VUF9JRFMgXAogIC1lIEFaVVJFX1BPUlRBTF9DTElFTlRfSUQgXAogIC1lIEFaVVJFX1BPUlRBTF9FTEVWQVRFRF9HUk9VUF9JRFMgXAogIC1lIERBVEFCQVNFX0FDQ09VTlRfTkFNRSBcCiAgLWUgS0VZVkFVTFRfUFJFRklYIFwKICAtZSBNRE1fQUNDT1VOVCBcCiAgLWUgTURNX05BTUVTUEFDRSBcCiAgLWUgUE9SVEFMX0hPU1ROQU1FIFwKICAtbSAyZyBcCiAgLXAgNDQ0Ojg0NDQgXAogIC1wIDIyMjI6MjIyMiBcCiAgLXYgL3J1bi9zeXN0ZW1kL2pvdXJuYWw6L3J1bi9zeXN0ZW1kL2pvdXJuYWwgXAogIC12IC92YXIvZXR3Oi92YXIvZXR3OnogXAogICRSUElNQUdFIFwKICBwb3J0YWwKUmVzdGFydD1hbHdheXMKUmVzdGFydFNlYz0xCgpbSW5zdGFsbF0KV2FudGVkQnk9bXVsdGktdXNlci50YXJnZXQiCgogICAgd3JpdGVfZmlsZSBhcm9fcG9ydGFsX3NlcnZpY2VfY29uZl9maWxlbmFtZSBhcm9fcG9ydGFsX3NlcnZpY2VfY29uZl9maWxlIHRydWUKfQoKIyBjb25maWd1cmVfc2VydmljZV9tZHNkCmNvbmZpZ3VyZV9zZXJ2aWNlX21kc2QoKSB7CiAgICBsb2cgInN0YXJ0aW5nIgoKICAgIGxvY2FsIC1yIG1kc2Rfc2VydmljZV9kaXI9Ii9ldGMvc3lzdGVtZC9zeXN0ZW0vbWRzZC5zZXJ2aWNlLmQiCiAgICBta2RpciAiJG1kc2Rfc2VydmljZV9kaXIiCgogICAgbG9jYWwgLXIgbWRzZF9vdmVycmlkZV9jb25mX2ZpbGVuYW1lPSIkbWRzZF9zZXJ2aWNlX2Rpci9vdmVycmlkZS5jb25mIgogICAgbG9jYWwgLXIgbWRzZF9vdmVycmlkZV9jb25mX2ZpbGU9IltVbml0XQpBZnRlcj1uZXR3b3JrLW9ubGluZS50YXJnZXQiCgogICAgd3JpdGVfZmlsZSBtZHNkX292ZXJyaWRlX2NvbmZfZmlsZW5hbWUgbWRzZF9vdmVycmlkZV9jb25mX2ZpbGUgdHJ1ZQoKICAgIGxvY2FsIC1yIGRlZmF1bHRfbWRzZF9maWxlbmFtZT0iL2V0Yy9kZWZhdWx0L21kc2QiCiAgICBsb2NhbCAtciBkZWZhdWx0X21kc2RfZmlsZT0iTURTRF9ST0xFX1BSRUZJWD0vdmFyL3J1bi9tZHNkL2RlZmF1bHQKTURTRF9PUFRJT05TPVwiLUEgLWQgLXIgXCRNRFNEX1JPTEVfUFJFRklYXCIKCmV4cG9ydCBNT05JVE9SSU5HX0dDU19FTlZJUk9OTUVOVD0nJE1EU0RFTlZJUk9OTUVOVCcKZXhwb3J0IE1PTklUT1JJTkdfR0NTX0FDQ09VTlQ9JyRSUE1EU0RBQ0NPVU5UJwpleHBvcnQgTU9OSVRPUklOR19HQ1NfUkVHSU9OPSckTE9DQVRJT04nCmV4cG9ydCBNT05JVE9SSU5HX0dDU19BVVRIX0lEX1RZUEU9QXV0aEtleVZhdWx0CmV4cG9ydCBNT05JVE9SSU5HX0dDU19BVVRIX0lEPSckTURTRENFUlRJRklDQVRFU0FOJwpleHBvcnQgTU9OSVRPUklOR19HQ1NfTkFNRVNQQUNFPSckUlBNRFNETkFNRVNQQUNFJwpleHBvcnQgTU9OSVRPUklOR19DT05GSUdfVkVSU0lPTj0nJFJQTURTRENPTkZJR1ZFUlNJT04nCmV4cG9ydCBNT05JVE9SSU5HX1VTRV9HRU5FVkFfQ09ORklHX1NFUlZJQ0U9dHJ1ZQoKZXhwb3J0IE1PTklUT1JJTkdfVEVOQU5UPSckTE9DQVRJT04nCmV4cG9ydCBNT05JVE9SSU5HX1JPTEU9cnAKZXhwb3J0IE1PTklUT1JJTkdfUk9MRV9JTlNUQU5DRT1cIiQoaG9zdG5hbWUpXCIKCmV4cG9ydCBNRFNEX01TR1BBQ0tfU09SVF9DT0xVTU5TPTFcIiIKCiAgICB3cml0ZV9maWxlIGRlZmF1bHRfbWRzZF9maWxlbmFtZSBkZWZhdWx0X21kc2RfZmlsZSB0cnVlCgp9CgojIHJ1bl9henNlY2RfY29uZmlnX3NjYW4KcnVuX2F6c2VjZF9jb25maWdfc2NhbigpIHsKICAgIGxvZyAic3RhcnRpbmciCgogICAgbG9jYWwgLWFyIGNvbmZpZ3M9KAogICAgICAgICJiYXNlbGluZSIKICAgICAgICAiY2xhbWF2IgogICAgICAgICJzb2Z0d2FyZSIKICAgICkKCiAgICBsb2cgIlNjYW5uaW5nIGNvbmZpZ3VyYXRpb24gZmlsZXMgJHtjb25maWdzWypdfSIKICAgICMgc2hlbGxjaGVjayBkaXNhYmxlPVNDMjA2OAogICAgZm9yIHNjYW4gaW4gJHtjb25maWdzW0BdfTsgZG8KICAgICAgICBsb2cgIlNjYW5uaW5nIGNvbmZpZyBmaWxlICRzY2FuIG5vdyIKICAgICAgICAvdXNyL2xvY2FsL2Jpbi9henNlY2QgY29uZmlnIC1zICIkc2NhbiIgLWQgUDFECiAgICBkb25lCn0KCiMgd3JpdGVfZmlsZQojIEFyZ3MKIyAxKSBmaWxlbmFtZSAtIHN0cmluZwojIDIpIGZpbGVfY29udGVudHMgLSBzdHJpbmcKIyAzKSBjbG9iYmVyIC0gYm9vbGVhbjsgb3B0aW9uYWwgLSBkZWZhdWx0cyB0byBmYWxzZQp3cml0ZV9maWxlKCkgewogICAgbG9jYWwgLW4gZmlsZW5hbWU9IiQxIgogICAgbG9jYWwgLW4gZmlsZV9jb250ZW50cz0iJDIiCiAgICBsb2NhbCAtciBjbG9iYmVyPSIkezM6LWZhbHNlfSIKCiAgICBpZiAkY2xvYmJlcjsgdGhlbgogICAgICAgIGxvZyAiT3ZlcndyaXRpbmcgZmlsZSAkZmlsZW5hbWUiCiAgICAgICAgZWNobyAiJGZpbGVfY29udGVudHMiID4gIiRmaWxlbmFtZSIKICAgIGVsc2UKICAgICAgICBsb2cgIkFwcGVuZGluZyB0byAkZmlsZW5hbWUiCiAgICAgICAgZWNobyAiJGZpbGVfY29udGVudHMiID4+ICIkZmlsZW5hbWUiCiAgICBmaQp9CgojIHJlYm9vdF92bSByZXN0b3JlcyBhbGwgc2VsaW51eCBmaWxlIGNvbnRleHRzLCB3YWl0cyAzMCBzZWNvbmRzIHRoZW4gcmVib290cwpyZWJvb3Rfdm0oKSB7CiAgICBsb2cgInN0YXJ0aW5nIgoKICAgIGNvbmZpZ3VyZV9zZWxpbnV4ICJ0cnVlIgogICAgKHNsZWVwIDMwICYmIGxvZyAicmVib290aW5nIHZtIG5vdyI7IHJlYm9vdCkgJgp9CgojIGxvZyBpcyBhIHdyYXBwZXIgZm9yIGVjaG8gdGhhdCBpbmNsdWRlcyB0aGUgZnVuY3Rpb24gbmFtZQpsb2coKSB7CiAgICBsb2NhbCAtciBtc2c9IiR7MTotImxvZyBtZXNzYWdlIGlzIGVtcHR5In0iCiAgICBsb2NhbCAtciBzdGFja19sZXZlbD0iJHsyOi0xfSIKICAgIGVjaG8gIiR7RlVOQ05BTUVbJHtzdGFja19sZXZlbH1dfTogJHttc2d9Igp9CgojIGFib3J0IGlzIGEgd3JhcHBlciBmb3IgbG9nIHRoYXQgZXhpdHMgd2l0aCBhbiBlcnJvciBjb2RlCmFib3J0KCkgewogICAgbG9jYWwgLXJpIG9yaWdpbl9zdGFja2xldmVsPTIKICAgIGxvZyAiJHsxfSIgIiRvcmlnaW5fc3RhY2tsZXZlbCIKICAgIGxvZyAiRXhpdGluZyIKICAgIGV4aXQgMQp9CgpleHBvcnQgQVpVUkVfQ0xPVURfTkFNRT0iJHtBWlVSRUNMT1VETkFNRTo/IkZhaWxlZCB0byBjYXJyeSBvdmVyIHZhcmlhYmxlcyJ9IgoKbWFpbiAiJEAiCg==')))]" + "script": "[base64(concat(base64ToString('c2V0IC1leAoK'),'ACRRESOURCEID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('acrResourceId')),''')\n','ADMINAPICLIENTCERTCOMMONNAME=$(base64 -d \u003c\u003c\u003c''',base64(parameters('adminApiClientCertCommonName')),''')\n','ARMAPICLIENTCERTCOMMONNAME=$(base64 -d \u003c\u003c\u003c''',base64(parameters('armApiClientCertCommonName')),''')\n','ARMCLIENTID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('armClientId')),''')\n','AZURECLOUDNAME=$(base64 -d \u003c\u003c\u003c''',base64(parameters('azureCloudName')),''')\n','AZURESECPACKQUALYSURL=$(base64 -d \u003c\u003c\u003c''',base64(parameters('azureSecPackQualysUrl')),''')\n','AZURESECPACKVSATENANTID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('azureSecPackVSATenantId')),''')\n','BILLINGE2ESTORAGEACCOUNTID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('billingE2EStorageAccountId')),''')\n','CLUSTERMDMACCOUNT=$(base64 -d \u003c\u003c\u003c''',base64(parameters('clusterMdmAccount')),''')\n','CLUSTERMDSDACCOUNT=$(base64 -d \u003c\u003c\u003c''',base64(parameters('clusterMdsdAccount')),''')\n','CLUSTERMDSDCONFIGVERSION=$(base64 -d \u003c\u003c\u003c''',base64(parameters('clusterMdsdConfigVersion')),''')\n','CLUSTERMDSDNAMESPACE=$(base64 -d \u003c\u003c\u003c''',base64(parameters('clusterMdsdNamespace')),''')\n','CLUSTERPARENTDOMAINNAME=$(base64 -d \u003c\u003c\u003c''',base64(parameters('clusterParentDomainName')),''')\n','DATABASEACCOUNTNAME=$(base64 -d \u003c\u003c\u003c''',base64(parameters('databaseAccountName')),''')\n','DBTOKENCLIENTID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('dbtokenClientId')),''')\n','FLUENTBITIMAGE=$(base64 -d \u003c\u003c\u003c''',base64(parameters('fluentbitImage')),''')\n','FPCLIENTID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('fpClientId')),''')\n','FPSERVICEPRINCIPALID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('fpServicePrincipalId')),''')\n','GATEWAYDOMAINS=$(base64 -d \u003c\u003c\u003c''',base64(parameters('gatewayDomains')),''')\n','GATEWAYRESOURCEGROUPNAME=$(base64 -d \u003c\u003c\u003c''',base64(parameters('gatewayResourceGroupName')),''')\n','GATEWAYSERVICEPRINCIPALID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('gatewayServicePrincipalId')),''')\n','KEYVAULTDNSSUFFIX=$(base64 -d \u003c\u003c\u003c''',base64(parameters('keyvaultDNSSuffix')),''')\n','KEYVAULTPREFIX=$(base64 -d \u003c\u003c\u003c''',base64(parameters('keyvaultPrefix')),''')\n','MDMFRONTENDURL=$(base64 -d \u003c\u003c\u003c''',base64(parameters('mdmFrontendUrl')),''')\n','MDSDENVIRONMENT=$(base64 -d \u003c\u003c\u003c''',base64(parameters('mdsdEnvironment')),''')\n','PORTALACCESSGROUPIDS=$(base64 -d \u003c\u003c\u003c''',base64(parameters('portalAccessGroupIds')),''')\n','PORTALCLIENTID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('portalClientId')),''')\n','PORTALELEVATEDGROUPIDS=$(base64 -d \u003c\u003c\u003c''',base64(parameters('portalElevatedGroupIds')),''')\n','RPFEATURES=$(base64 -d \u003c\u003c\u003c''',base64(parameters('rpFeatures')),''')\n','RPIMAGE=$(base64 -d \u003c\u003c\u003c''',base64(parameters('rpImage')),''')\n','RPMDMACCOUNT=$(base64 -d \u003c\u003c\u003c''',base64(parameters('rpMdmAccount')),''')\n','RPMDSDACCOUNT=$(base64 -d \u003c\u003c\u003c''',base64(parameters('rpMdsdAccount')),''')\n','RPMDSDCONFIGVERSION=$(base64 -d \u003c\u003c\u003c''',base64(parameters('rpMdsdConfigVersion')),''')\n','RPMDSDNAMESPACE=$(base64 -d \u003c\u003c\u003c''',base64(parameters('rpMdsdNamespace')),''')\n','RPPARENTDOMAINNAME=$(base64 -d \u003c\u003c\u003c''',base64(parameters('rpParentDomainName')),''')\n','CLUSTERSINSTALLVIAHIVE=$(base64 -d \u003c\u003c\u003c''',base64(parameters('clustersInstallViaHive')),''')\n','CLUSTERSADOPTBYHIVE=$(base64 -d \u003c\u003c\u003c''',base64(parameters('clustersAdoptByHive')),''')\n','CLUSTERDEFAULTINSTALLERPULLSPEC=$(base64 -d \u003c\u003c\u003c''',base64(parameters('clusterDefaultInstallerPullspec')),''')\n','USECHECKACCESS=$(base64 -d \u003c\u003c\u003c''',base64(parameters('useCheckAccess')),''')\n','ADMINAPICABUNDLE=''',parameters('adminApiCaBundle'),'''\n','ARMAPICABUNDLE=''',parameters('armApiCaBundle'),'''\n','MDMIMAGE=''/genevamdm:2.2024.328.1744-c5fb79-20240328t1935''\n','LOCATION=$(base64 -d \u003c\u003c\u003c''',base64(resourceGroup().location),''')\n','SUBSCRIPTIONID=$(base64 -d \u003c\u003c\u003c''',base64(subscription().subscriptionId),''')\n','RESOURCEGROUPNAME=$(base64 -d \u003c\u003c\u003c''',base64(resourceGroup().name),''')\n','\n',base64ToString('IyEvYmluL2Jhc2gKCnNldCAtbyBlcnJleGl0IFwKICAgIC1vIG5vdW5zZXQKCmlmIFsgIiR7REVCVUc6LWZhbHNlfSIgPT0gdHJ1ZSBdOyB0aGVuCiAgICBzZXQgLXgKZmkKCm1haW4oKSB7CiAgICAjIHRyYW5zYWN0aW9uIGF0dGVtcHQgcmV0cnkgdGltZSBpbiBzZWNvbmRzCiAgICBsb2NhbCAtcmkgcmV0cnlfd2FpdF90aW1lPTYwCgogICAgIyBzaGVsbGNoZWNrIHNvdXJjZT1jb21tb24uc2gKICAgIHNvdXJjZSBjb21tb24uc2gKCiAgICBsb2NhbCAtYXIgZXhjbHVkZV9wa2dzPSgKICAgICAgICAiLXggV0FMaW51eEFnZW50IgogICAgICAgICIteCBXQUxpbnV4QWdlbnQtdWRldiIKICAgICkKCiAgICBsb2NhbCAtcmEgcnBtX2tleXM9KAogICAgICAgIGh0dHBzOi8vZGwuZmVkb3JhcHJvamVjdC5vcmcvcHViL2VwZWwvUlBNLUdQRy1LRVktRVBFTC04CiAgICAgICAgaHR0cHM6Ly9wYWNrYWdlcy5taWNyb3NvZnQuY29tL2tleXMvbWljcm9zb2Z0LmFzYwogICAgKQoKICAgIGxvY2FsIC1yYSByZXBvX3JwbV9wa2dzPSgKICAgICAgICBodHRwczovL2RsLmZlZG9yYXByb2plY3Qub3JnL3B1Yi9lcGVsL2VwZWwtcmVsZWFzZS1sYXRlc3QtOC5ub2FyY2gucnBtCiAgICApCgogICAgbG9jYWwgLXJhIGluc3RhbGxfcGtncz0oCiAgICAgICAgY2xhbWF2CiAgICAgICAgYXpzZWMtY2xhbWF2CiAgICAgICAgYXpzZWMtbW9uaXRvcgogICAgICAgIGF6dXJlLWNsaQogICAgICAgIGF6dXJlLW1kc2QKICAgICAgICBhenVyZS1zZWN1cml0eQogICAgICAgIHBvZG1hbgogICAgICAgIHBvZG1hbi1kb2NrZXIKICAgICAgICBvcGVuc3NsLXBlcmwKICAgICAgICAjIGhhY2sgLSB3ZSBhcmUgaW5zdGFsbGluZyBweXRob24zIG9uIGhvc3RzIGR1ZSB0byBhbiBpc3N1ZSB3aXRoIEF6dXJlIExpbnV4IEV4dGVuc2lvbnMgaHR0cHM6Ly9naXRodWIuY29tL0F6dXJlL2F6dXJlLWxpbnV4LWV4dGVuc2lvbnMvcHVsbC8xNTA1CiAgICAgICAgcHl0aG9uMwogICAgKQoKICAgIE1ETUlNQUdFPSIke1JQSU1BR0UlJS8qfS8ke01ETUlNQUdFIyMqL30iCiAgICBsb2NhbCAtcmEgaW1hZ2VzPSgKICAgICAgICAiJE1ETUlNQUdFIgogICAgICAgICIkUlBJTUFHRSIKICAgICAgICAiJEZMVUVOVEJJVElNQUdFIgogICAgKQoKICAgIGxvY2FsIC1yYSBlbmFibGVfcG9ydHM9KAogICAgICAgICI0NDMvdGNwIgogICAgICAgICI0NDQvdGNwIgogICAgICAgICI0NDUvdGNwIgogICAgICAgICIyMjIyL3RjcCIKICAgICkKCiAgICBsb2NhbCAtcmEgYXJvX3NlcnZpY2VzPSgKICAgICAgICAiYXJvLWRidG9rZW4iCiAgICAgICAgImFyby1tb25pdG9yIgogICAgICAgICJhcm8tcG9ydGFsIgogICAgICAgICJhcm8tcnAiCiAgICAgICAgImF1b21zIgogICAgICAgICJhenNlY2QiCiAgICAgICAgImF6c2VjbW9uZCIKICAgICAgICAibWRzZCIKICAgICAgICAibWRtIgogICAgICAgICJjaHJvbnlkIgogICAgICAgICJmbHVlbnRiaXQiCiAgICApCgogICAgcGFyc2VfcnVuX29wdGlvbnMgIiRAIiBcCiAgICAgICAgICAgICAgICAgICAgICAgIHJldHJ5X3dhaXRfdGltZSBcCiAgICAgICAgICAgICAgICAgICAgICAgIGV4Y2x1ZGVfcGtncyBcCiAgICAgICAgICAgICAgICAgICAgICAgIHJwbV9rZXlzIFwKICAgICAgICAgICAgICAgICAgICAgICAgcmVwb19ycG1fcGtncyBcCiAgICAgICAgICAgICAgICAgICAgICAgIGluc3RhbGxfcGtncyBcCiAgICAgICAgICAgICAgICAgICAgICAgIGltYWdlcyBcCiAgICAgICAgICAgICAgICAgICAgICAgIGVuYWJsZV9wb3J0cyBcCiAgICAgICAgICAgICAgICAgICAgICAgIGFyb19zZXJ2aWNlcwoKICAgIGNvbmZpZ3VyZV9zc2hkCiAgICBjb25maWd1cmVfcnBtX3JlcG9zIHJldHJ5X3dhaXRfdGltZQoKICAgIGRuZl91cGRhdGVfcGtncyBleGNsdWRlX3BrZ3MgcmV0cnlfd2FpdF90aW1lCgogICAgcnBtX2ltcG9ydF9rZXlzIHJwbV9rZXlzIHJldHJ5X3dhaXRfdGltZQoKICAgIGRuZl9pbnN0YWxsX3BrZ3MgcmVwb19ycG1fcGtncyByZXRyeV93YWl0X3RpbWUKICAgIGRuZl9pbnN0YWxsX3BrZ3MgaW5zdGFsbF9wa2dzIHJldHJ5X3dhaXRfdGltZQogICAgY29uZmlndXJlX2RuZl9jcm9uX2pvYgoKICAgIGNvbmZpZ3VyZV9kaXNrX3BhcnRpdGlvbnMKICAgIGNvbmZpZ3VyZV9sb2dyb3RhdGUKICAgIGNvbmZpZ3VyZV9zZWxpbnV4CgogICAgbWtkaXIgLXAgL3Zhci9sb2cvam91cm5hbAogICAgbWtkaXIgLXAgL3Zhci9saWIvd2FhZ2VudC9NaWNyb3NvZnQuQXp1cmUuS2V5VmF1bHQuU3RvcmUKCiAgICBjb25maWd1cmVfZmlyZXdhbGxkX3J1bGVzIGVuYWJsZV9wb3J0cwoKICAgIHB1bGxfY29udGFpbmVyX2ltYWdlcyBpbWFnZXMKICAgIGNvbmZpZ3VyZV9hcm9fc2VydmljZXMKICAgIGVuYWJsZV9zZXJ2aWNlcwoKICAgIGVuYWJsZV9zZXJ2aWNlcyBhcm9fc2VydmljZXMKCiAgICByZWJvb3Rfdm0KfQoKdXNhZ2UoKSB7CiAgICBsb2NhbCAtbiBvcHRpb25zPSIkMSIKICAgIGxvZyAiJChiYXNlbmFtZSAiJDAiKSBbJG9wdGlvbnNdCiAgICAgICAgLWQgQ29uZmlndXJlIERpc2sgUGFydGl0aW9ucwogICAgICAgIC1wIENvbmZpZ3VyZSBycG0gcmVwb3NpdG9yaWVzLCBpbXBvcnQgcmVxdWlyZWQgcnBtIGtleXMsIHVwZGF0ZSAmIGluc3RhbGwgcGFja2FnZXMgd2l0aCBkbmYKICAgICAgICAtbCBDb25maWd1cmUgbG9ncm90YXRlLmNvbmYKICAgICAgICAtcyBDb25maWd1cmUgc2VsaW51eAogICAgICAgIC1yIENvbmZpZ3VyZSBzc2hkIC0gQWxsb3cgcGFzc3dvcmQgYXV0aGVudGljYWl0b24KICAgICAgICAtZiBDb25maWd1cmUgZmlyZXdhbGxkIGRlZmF1bHQgem9uZSBydWxlcwogICAgICAgIC11IENvbmZpZ3VyZSBzeXN0ZW1kIHVuaXQgZmlsZXMKICAgICAgICAtaSBQdWxsIGNvbnRhaW5lciBpbWFnZXMKCiAgICAgICAgTm90ZTogc3RlcHMgd2lsbCBiZSBleGVjdXRlZCBpbiB0aGUgb3JkZXIgdGhhdCBmbGFncyBhcmUgcHJvdmlkZWQKICAgICIKfQoKIyBwYXJzZV9ydW5fb3B0aW9ucyB0YWtlcyBhbGwgYXJndWVtZW50cyBwYXNzZWQgdG8gbWFpbiBhbmQgcGFyc2VzIHRoZW0KIyBhbGxvd2luZyBpbmRpdmlkdWFsIHN0ZXAocykgdG8gYmUgcmFuLCByYXRoZXIgdGhhbiBhbGwgc3RlcHMKIwojIFRoaXMgaXMgdXNlZnVsIGZvciBsb2NhbCB0ZXN0aW5nLCBvciBwb3NzaWJseSBtb2RpZnlpbmcgdGhlIGJvb3RzdHJhcCBleGVjdXRpb24gdmlhIGVudmlyb25tZW50IHZhcmlhYmxlcyBpbiB0aGUgZGVwbG95bWVudCBwaXBlbGluZQpwYXJzZV9ydW5fb3B0aW9ucygpIHsKICAgICMgc2hlbGxjaGVjayBkaXNhYmxlPVNDMjIwNgogICAgbG9jYWwgLWEgb3B0aW9ucz0oJHsxOi19KQogICAgbG9jYWwgLW4gcmV0cnlfdGltZT0iJDIiCiAgICBsb2NhbCAtbiBwa2dzX3RvX2V4Y2x1ZGU9IiQzIgogICAgbG9jYWwgLW4ga2V5c190b19pbXBvcnQ9IiQ0IgogICAgbG9jYWwgLW4gcnBtX3BrZ3M9IiQ1IgogICAgbG9jYWwgLW4gcGtnc190b19pbnN0YWxsPSIkNiIKICAgIGxvY2FsIC1uIGltYWdlc190b19wdWxsPSIkNyIKICAgIGxvY2FsIC1uIHBvcnRzX3RvX2VuYWJsZT0iJDgiCiAgICBsb2NhbCAtbiBzZXJ2aWNlc190b19lbmFibGU9IiQ5IgoKICAgIGlmIFsgIiR7I29wdGlvbnNbQF19IiAtZXEgMCBdOyB0aGVuCiAgICAgICAgbG9nICJSdW5uaW5nIGFsbCBzdGVwcyIKICAgICAgICByZXR1cm4gMAogICAgZmkKCiAgICBsb2NhbCBPUFRJTkQKICAgIGxvY2FsIC1yIGFsbG93ZWRfb3B0aW9ucz0iZHBsc3JmdWkiCiAgICB3aGlsZSBnZXRvcHRzICR7YWxsb3dlZF9vcHRpb25zfSBvcHRpb25zOyBkbwogICAgICAgIGNhc2UgIiR7b3B0aW9uc30iIGluCiAgICAgICAgICAgIGQpCiAgICAgICAgICAgICAgICBsb2cgIlJ1bm5pbmcgc3RlcCBjb25maWd1cmVfZGlza19wYXJ0aXRpb25zIgogICAgICAgICAgICAgICAgY29uZmlndXJlX2Rpc2tfcGFydGl0aW9ucwogICAgICAgICAgICAgICAgOzsKICAgICAgICAgICAgcCkKICAgICAgICAgICAgICAgIGxvZyAiUnVubmluZyBzdGVwIGNvbmZpZ3VyZV9ycG1fcmVwb3MiCiAgICAgICAgICAgICAgICBjb25maWd1cmVfcnBtX3JlcG9zIGtleXNfdG9faW1wb3J0CgogICAgICAgICAgICAgICAgbG9nICJSdW5uaW5nIHN0ZXAgZG5mX3VwZGF0ZV9wa2dzIgogICAgICAgICAgICAgICAgZG5mX3VwZGF0ZV9wa2dzIHBrZ3NfdG9fZXhjbHVkZSByZXRyeV90aW1lCgogICAgICAgICAgICAgICAgbG9nICJSdW5uaW5nIHN0ZXAgZG5mX2luc3RhbGxfcGtncyBycG1fcGtncyIKICAgICAgICAgICAgICAgIGRuZl9pbnN0YWxsX3BrZ3MgcnBtX3BrZ3MgcmV0cnlfdGltZQoKICAgICAgICAgICAgICAgIGxvZyAiUnVubmluZyBzdGVwIGRuZl9pbnN0YWxsX3BrZ3MgcGtncyIKICAgICAgICAgICAgICAgIGRuZl9pbnN0YWxsX3BrZ3MgcGtnc190b19pbnN0YWxsIHJldHJ5X3RpbWUKICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgbG9nICJSdW5uaW5nIHN0ZXAgY29uZmlndXJlX2RuZl9jcm9uZF9qb2IiCiAgICAgICAgICAgICAgICBjb25maWd1cmVfZG5mX2Nyb25fam9iCiAgICAgICAgICAgICAgICA7OwogICAgICAgICAgICBsKQogICAgICAgICAgICAgICAgbG9nICJSdW5uaW5nIGNvbmZpZ3VyZV9sb2dyb3RhdGUiCiAgICAgICAgICAgICAgICBjb25maWd1cmVfbG9ncm90YXRlCiAgICAgICAgICAgICAgICA7OwogICAgICAgICAgICBzKQogICAgICAgICAgICAgICAgbG9nICJSdW5uaW5nIGNvbmZpZ3VyZV9zZWxpbnV4IgogICAgICAgICAgICAgICAgY29uZmlndXJlX3NlbGludXgKICAgICAgICAgICAgICAgIDs7CiAgICAgICAgICAgIHIpCiAgICAgICAgICAgICAgICBsb2cgIlJ1bm5pbmcgY29uZmlndXJlX3NzaGQiCiAgICAgICAgICAgICAgICBjb25maWd1cmVfc3NoZAogICAgICAgICAgICAgICAgOzsKICAgICAgICAgICAgZikKICAgICAgICAgICAgICAgIGxvZyAiUnVubmluZyBjb25maWd1cmVfZmlyZXdhbGxkX3J1bGVzIgogICAgICAgICAgICAgICAgY29uZmlndXJlX2ZpcmV3YWxsZF9ydWxlcyBwb3J0c190b19lbmFibGUKICAgICAgICAgICAgICAgIDs7CiAgICAgICAgICAgIHUpCiAgICAgICAgICAgICAgICBsb2cgIlJ1bm5pbmcgcHVsbF9jb250YWluZXJfaW1hZ2VzICYgY29uZmlndXJlX3N5c3RlbV9zZXJ2aWNlcyIKICAgICAgICAgICAgICAgIGNvbmZpZ3VyZV9hcm9fc2VydmljZXMKICAgICAgICAgICAgICAgIGVuYWJsZV9zZXJ2aWNlcyBzZXJ2aWNlc190b19lbmFibGUKICAgICAgICAgICAgICAgIDs7CiAgICAgICAgICAgIGkpCiAgICAgICAgICAgICAgICBsb2cgIlJ1bm5pbmcgcHVsbF9jb250YWluZXJfaW1hZ2VzIgogICAgICAgICAgICAgICAgcHVsbF9jb250YWluZXJfaW1hZ2VzIGltYWdlc190b19wdWxsCiAgICAgICAgICAgICAgICA7OwogICAgICAgICAgICAqKQogICAgICAgICAgICAgICAgdXNhZ2UgYWxsb3dlZF9vcHRpb25zCiAgICAgICAgICAgICAgICBhYm9ydCAiVW5rb3duIG9wdGlvbiBwcm92aWRlZCIKICAgICAgICAgICAgICAgIDs7CiAgICAgICAgZXNhYwogICAgZG9uZQogICAgCiAgICBleGl0IDAKfQoKIyBjb25maWd1cmVfcnBtX3JlcG9zCmNvbmZpZ3VyZV9ycG1fcmVwb3MoKSB7CiAgICBsb2cgInN0YXJ0aW5nIgoKICAgIGNvbmZpZ3VyZV9yaHVpX3JlcG8gIiQxIgogICAgY3JlYXRlX2F6dXJlX3JwbV9yZXBvcyAiJDEiCn0KCiMgY29uZmlndXJlX2Rpc2tfcGFydGl0aW9ucwpjb25maWd1cmVfZGlza19wYXJ0aXRpb25zKCkgewogICAgbG9nICJzdGFydGluZyIKICAgIGxvZyAiZXh0ZW5kaW5nIHBhcnRpdGlvbiB0YWJsZSIKCiAgICAjIExpbnV4IGJsb2NrIGRldmljZXMgYXJlIGluY29uc2lzdGVudGx5IG5hbWVkCiAgICAjIGl0J3MgZGlmZmljdWx0IHRvIHRpZSB0aGUgbHZtIHB2IHRvIHRoZSBwaHlzaWNhbCBkaXNrIHVzaW5nIC9kZXYvZGlzayBmaWxlcywgd2hpY2ggaXMgd2h5IGx2cyBpcyB1c2VkIGhlcmUKICAgIHBoeXNpY2FsX2Rpc2s9IiQobHZzIC1vIGRldmljZXMgLWEgfCBoZWFkIC1uMiB8IHRhaWwgLW4xIHwgY3V0IC1kICcgJyAtZiAzIHwgY3V0IC1kIFwoIC1mIDEgfCB0ciAtZCAnWzpkaWdpdDpdJykiCiAgICBncm93cGFydCAiJHBoeXNpY2FsX2Rpc2siIDIKCiAgICBsb2cgImV4dGVuZGluZyBmaWxlc3lzdGVtcyIKICAgIGxvZyAiZXh0ZW5kaW5nIHJvb3QgbHZtIgogICAgbHZleHRlbmQgLWwgKzIwJUZSRUUgL2Rldi9yb290dmcvcm9vdGx2CiAgICBsb2cgImdyb3dpbmcgcm9vdCBmaWxlc3lzdGVtIgogICAgeGZzX2dyb3dmcyAvCgogICAgbG9nICJleHRlbmRpbmcgdmFyIGx2bSIKICAgIGx2ZXh0ZW5kIC1sICsxMDAlRlJFRSAvZGV2L3Jvb3R2Zy92YXJsdgogICAgbG9nICJncm93aW5nIHZhciBmaWxlc3lzdGVtIgogICAgeGZzX2dyb3dmcyAvdmFyCn0KCiMgY3JlYXRlX2F6dXJlX3JwbV9yZXBvcyBjcmVhdGVzIC9ldGMveXVtLnJlcG9zLmQvYXp1cmUucmVwbyByZXBvc2l0b3J5IGZpbGUKY3JlYXRlX2F6dXJlX3JwbV9yZXBvcygpIHsKICAgIGxvZyAic3RhcnRpbmciCgogICAgbG9jYWwgLXIgYXp1cmVfcmVwb19maWxlbmFtZT0nL2V0Yy95dW0ucmVwb3MuZC9henVyZS5yZXBvJwogICAgbG9jYWwgLXIgYXp1cmVfcmVwb19maWxlPSdbYXp1cmUtY2xpXQpuYW1lPWF6dXJlLWNsaQpiYXNldXJsPWh0dHBzOi8vcGFja2FnZXMubWljcm9zb2Z0LmNvbS95dW1yZXBvcy9henVyZS1jbGkKZW5hYmxlZD15ZXMKZ3BnY2hlY2s9eWVzCgpbYXp1cmVjb3JlXQpuYW1lPWF6dXJlY29yZQpiYXNldXJsPWh0dHBzOi8vcGFja2FnZXMubWljcm9zb2Z0LmNvbS95dW1yZXBvcy9henVyZWNvcmUKZW5hYmxlZD15ZXMKZ3BnY2hlY2s9bm8nCgogICAgd3JpdGVfZmlsZSBhenVyZV9yZXBvX2ZpbGVuYW1lIGF6dXJlX3JlcG9fZmlsZSB0cnVlCn0KCiMgY29uZmlndXJlX2Fyb19zZXJ2aWNlcyBjcmVhdGVzLCBjb25maWd1cmVzLCBhbmQgZW5hYmxlcyB0aGUgZm9sbG93aW5nIHN5c3RlbWQgc2VydmljZXMgYW5kIHRpbWVycwojIHNlcnZpY2VzCiMgICBmbHVlbnRiaXQKIyAgIG1kbQojICAgbWRzZAojICAgYXJwLXJwCiMgICBhcm8tZGJ0b2tlbgojICAgYXJvLW1vbml0b3IKIyAgIGFyby1wb3J0YWwKY29uZmlndXJlX2Fyb19zZXJ2aWNlcygpIHsKICAgIGNvbmZpZ3VyZV9zZXJ2aWNlX2ZsdWVudGJpdAogICAgY29uZmlndXJlX3NlcnZpY2VfbWRtCiAgICBjb25maWd1cmVfdGltZXJzX21kbV9tZHNkCiAgICBjb25maWd1cmVfc2VydmljZV9hcm9fcnAKICAgIGNvbmZpZ3VyZV9zZXJ2aWNlX2Fyb19kYnRva2VuCiAgICBjb25maWd1cmVfc2VydmljZV9hcm9fbW9uaXRvcgogICAgY29uZmlndXJlX3NlcnZpY2VfYXJvX3BvcnRhbAogICAgY29uZmlndXJlX3NlcnZpY2VfbWRzZAp9CgojIGNvbmZpZ3VyZV9zZXJ2aWNlX2ZsdWVudGJpdApjb25maWd1cmVfc2VydmljZV9mbHVlbnRiaXQoKSB7CiAgICBsb2cgInN0YXJ0aW5nIgogICAgbG9nICJjb25maWd1cmluZyBmbHVlbnRiaXQgc2VydmljZSIKCiAgICBta2RpciAtcCAvZXRjL2ZsdWVudGJpdC8KICAgIG1rZGlyIC1wIC92YXIvbGliL2ZsdWVudAoKICAgIGxvY2FsIC1yIGZsdWVudGJpdF9jb25mX2ZpbGVuYW1lPScvZXRjL2ZsdWVudGJpdC9mbHVlbnRiaXQuY29uZicKICAgIGxvY2FsIC1yIGZsdWVudGJpdF9jb25mX2ZpbGU9IltJTlBVVF0KTmFtZSBzeXN0ZW1kClRhZyBqb3VybmFsZApTeXN0ZW1kX0ZpbHRlciBfQ09NTT1hcm8KREIgL3Zhci9saWIvZmx1ZW50L2pvdXJuYWxkYgoKW0ZJTFRFUl0KCU5hbWUgbW9kaWZ5CglNYXRjaCBqb3VybmFsZAoJUmVtb3ZlX3dpbGRjYXJkIF8KCVJlbW92ZSBUSU1FU1RBTVAKCltGSUxURVJdCglOYW1lIHJld3JpdGVfdGFnCglNYXRjaCBqb3VybmFsZAoJUnVsZSAkTE9HS0lORCBhc3luY3FvcyBhc3luY3FvcyB0cnVlCgpbRklMVEVSXQoJTmFtZSBtb2RpZnkKCU1hdGNoIGFzeW5jcW9zCglSZW1vdmUgQ0xJRU5UX1BSSU5DSVBBTF9OQU1FCglSZW1vdmUgRklMRQoJUmVtb3ZlIENPTVBPTkVOVAoKW0ZJTFRFUl0KCU5hbWUgcmV3cml0ZV90YWcKCU1hdGNoIGpvdXJuYWxkCglSdWxlICRMT0dLSU5EIGlmeGF1ZGl0IGlmeGF1ZGl0IGZhbHNlCgpbT1VUUFVUXQoJTmFtZSBmb3J3YXJkCglNYXRjaCAqCglQb3J0IDI5MjMwIgoKICAgIHdyaXRlX2ZpbGUgZmx1ZW50Yml0X2NvbmZfZmlsZW5hbWUgZmx1ZW50Yml0X2NvbmZfZmlsZSB0cnVlCgogICAgbG9jYWwgLXIgc3lzY29uZmlnX2ZsdWVudGJpdF9maWxlbmFtZT0nL2V0Yy9zeXNjb25maWcvZmx1ZW50Yml0JwogICAgbG9jYWwgLXIgc3lzY29uZmlnX2ZsdWVudGJpdF9maWxlPSJGTFVFTlRCSVRJTUFHRT0kRkxVRU5UQklUSU1BR0UiCgogICAgd3JpdGVfZmlsZSBzeXNjb25maWdfZmx1ZW50Yml0X2ZpbGVuYW1lIHN5c2NvbmZpZ19mbHVlbnRiaXRfZmlsZSB0cnVlCgogICAgbG9jYWwgLXIgZmx1ZW50Yml0X3NlcnZpY2VfZmlsZW5hbWU9Jy9ldGMvc3lzdGVtZC9zeXN0ZW0vZmx1ZW50Yml0LnNlcnZpY2UnCgogICAgbG9jYWwgLXIgZmx1ZW50Yml0X3NlcnZpY2VfZmlsZT0iW1VuaXRdCkFmdGVyPW5ldHdvcmstb25saW5lLnRhcmdldApXYW50cz1uZXR3b3JrLW9ubGluZS50YXJnZXQKU3RhcnRMaW1pdEludGVydmFsU2VjPTAKCltTZXJ2aWNlXQpSZXN0YXJ0U2VjPTFzCkVudmlyb25tZW50RmlsZT0vZXRjL3N5c2NvbmZpZy9mbHVlbnRiaXQKRXhlY1N0YXJ0UHJlPS0vdXNyL2Jpbi9kb2NrZXIgcm0gLWYgJU4KRXhlY1N0YXJ0PS91c3IvYmluL2RvY2tlciBydW4gXAogIC0tc2VjdXJpdHktb3B0IGxhYmVsPWRpc2FibGUgXAogIC0tZW50cnlwb2ludCAvb3B0L3RkLWFnZW50LWJpdC9iaW4vdGQtYWdlbnQtYml0IFwKICAtLW5ldD1ob3N0IFwKICAtLWhvc3RuYW1lICVIIFwKICAtLW5hbWUgJU4gXAogIC0tcm0gXAogIC0tY2FwLWRyb3AgbmV0X3JhdyBcCiAgLXYgL2V0Yy9mbHVlbnRiaXQvZmx1ZW50Yml0LmNvbmY6L2V0Yy9mbHVlbnRiaXQvZmx1ZW50Yml0LmNvbmYgXAogIC12IC92YXIvbGliL2ZsdWVudDovdmFyL2xpYi9mbHVlbnQ6eiBcCiAgLXYgL3Zhci9sb2cvam91cm5hbDovdmFyL2xvZy9qb3VybmFsOnJvIFwKICAtdiAvZXRjL21hY2hpbmUtaWQ6L2V0Yy9tYWNoaW5lLWlkOnJvIFwKICAkRkxVRU5UQklUSU1BR0UgXAogIC1jIC9ldGMvZmx1ZW50Yml0L2ZsdWVudGJpdC5jb25mCgpFeGVjU3RvcD0vdXNyL2Jpbi9kb2NrZXIgc3RvcCAlTgpSZXN0YXJ0PWFsd2F5cwpSZXN0YXJ0U2VjPTUKU3RhcnRMaW1pdEludGVydmFsPTAKCltJbnN0YWxsXQpXYW50ZWRCeT1tdWx0aS11c2VyLnRhcmdldCIKCiAgICB3cml0ZV9maWxlIGZsdWVudGJpdF9zZXJ2aWNlX2ZpbGVuYW1lIGZsdWVudGJpdF9zZXJ2aWNlX2ZpbGUgdHJ1ZQp9CgojIGNvbmZpZ3VyZV9jZXJ0cwpjb25maWd1cmVfY2VydHMoKSB7CiAgICBsb2cgInN0YXJ0aW5nIgoKICAgIG1rZGlyIC9ldGMvYXJvLXJwCiAgICBiYXNlNjQgLWQgPDw8IiRBRE1JTkFQSUNBQlVORExFIiA+L2V0Yy9hcm8tcnAvYWRtaW4tY2EtYnVuZGxlLnBlbQogICAgaWYgW1sgLW4gIiRBUk1BUElDQUJVTkRMRSIgXV07IHRoZW4KICAgIGJhc2U2NCAtZCA8PDwiJEFSTUFQSUNBQlVORExFIiA+L2V0Yy9hcm8tcnAvYXJtLWNhLWJ1bmRsZS5wZW0KICAgIGZpCiAgICBjaG93biAtUiAxMDAwOjEwMDAgL2V0Yy9hcm8tcnAKCiAgICAjIHNldHRpbmcgTU9OSVRPUklOR19HQ1NfQVVUSF9JRF9UWVBFPUF1dGhLZXlWYXVsdCBzZWVtcyB0byBoYXZlIGNhdXNlZCBtZHNkIG5vdAogICAgIyB0byBob25vdXIgU1NMX0NFUlRfRklMRSBhbnkgbW9yZSwgaGVhdmVuIG9ubHkga25vd3Mgd2h5LgogICAgbWtkaXIgLXAgL3Vzci9saWIvc3NsL2NlcnRzCiAgICBjc3BsaXQgLWYgL3Vzci9saWIvc3NsL2NlcnRzL2NlcnQtIC1iICUwM2QucGVtIC9ldGMvcGtpL3Rscy9jZXJ0cy9jYS1idW5kbGUuY3J0IC9eJC8xICJ7Kn0iID4vZGV2L251bGwKICAgIGNfcmVoYXNoIC91c3IvbGliL3NzbC9jZXJ0cwoKIyB3ZSBsZWF2ZSBjbGllbnRJZCBibGFuayBhcyBsb25nIGFzIG9ubHkgMSBtYW5hZ2VkIGlkZW50aXR5IGFzc2lnbmVkIHRvIHZtc3MKIyBpZiB3ZSBoYXZlIG1vcmUgdGhhbiAxLCB3ZSB3aWxsIG5lZWQgdG8gcG9wdWxhdGUgd2l0aCBjbGllbnRJZCB1c2VkIGZvciBvZmYtbm9kZSBzY2FubmluZwogICAgbG9jYWwgLXIgbm9kZXNjYW5fYWdlbnRfZmlsZW5hbWU9Ii9ldGMvZGVmYXVsdC92c2Etbm9kZXNjYW4tYWdlbnQuY29uZmlnIgogICAgbG9jYWwgLXIgbm9kZXNjYW5fYWdlbnRfZmlsZT0iewogICAgXCJOaWNlXCI6IDE5LAogICAgXCJUaW1lb3V0XCI6IDEwODAwLAogICAgXCJDbGllbnRJZFwiOiBcIlwiLAogICAgXCJUZW5hbnRJZFwiOiAkQVpVUkVTRUNQQUNLVlNBVEVOQU5USUQsCiAgICBcIlF1YWx5c1N0b3JlQmFzZVVybFwiOiAkQVpVUkVTRUNQQUNLUVVBTFlTVVJMLAogICAgXCJQcm9jZXNzVGltZW91dFwiOiAzMDAsCiAgICBcIkNvbW1hbmREZWxheVwiOiAwCiAgfSIKCiAgICB3cml0ZV9maWxlIG5vZGVzY2FuX2FnZW50X2ZpbGVuYW1lIG5vZGVzY2FuX2FnZW50X2ZpbGUgdHJ1ZQp9CgojIGNvbmZpZ3VyZV9zZXJ2aWNlX21kbQpjb25maWd1cmVfc2VydmljZV9tZG0oKSB7CiAgICBsb2cgInN0YXJ0aW5nIgogICAgbG9nICJjb25maWd1cmluZyBtZG0gc2VydmljZSIKCiAgICBsb2NhbCAtciBzeXNjb25maWdfbWRtX2ZpbGVuYW1lPSIvZXRjL3N5c2NvbmZpZy9tZG0iCiAgICBsb2NhbCAtciBzeXNjb25maWdfbWRtX2ZpbGU9Ik1ETUZST05URU5EVVJMPSckTURNRlJPTlRFTkRVUkwnCk1ETUlNQUdFPSckTURNSU1BR0UnCk1ETVNPVVJDRUVOVklST05NRU5UPSckTE9DQVRJT04nCk1ETVNPVVJDRVJPTEU9cnAKTURNU09VUkNFUk9MRUlOU1RBTkNFPVwiJChob3N0bmFtZSlcIiIKCiAgICB3cml0ZV9maWxlIHN5c2NvbmZpZ19tZG1fZmlsZW5hbWUgc3lzY29uZmlnX21kbV9maWxlIHRydWUKCiAgICBta2RpciAtcCAvdmFyL2V0dwogICAgbG9jYWwgLXIgbWRtX3NlcnZpY2VfZmlsZW5hbWU9Ii9ldGMvc3lzdGVtZC9zeXN0ZW0vbWRtLnNlcnZpY2UiCiAgICBsb2NhbCAtciBtZG1fc2VydmljZV9maWxlPSJbVW5pdF0KQWZ0ZXI9bmV0d29yay1vbmxpbmUudGFyZ2V0CldhbnRzPW5ldHdvcmstb25saW5lLnRhcmdldAoKW1NlcnZpY2VdCkVudmlyb25tZW50RmlsZT0vZXRjL3N5c2NvbmZpZy9tZG0KRXhlY1N0YXJ0UHJlPS0vdXNyL2Jpbi9kb2NrZXIgcm0gLWYgJU4KRXhlY1N0YXJ0PS91c3IvYmluL2RvY2tlciBydW4gXAogIC0tZW50cnlwb2ludCAvdXNyL3NiaW4vTWV0cmljc0V4dGVuc2lvbiBcCiAgLS1ob3N0bmFtZSAlSCBcCiAgLS1uYW1lICVOIFwKICAtLXJtIFwKICAtLWNhcC1kcm9wIG5ldF9yYXcgXAogIC1tIDJnIFwKICAtdiAvZXRjL21kbS5wZW06L2V0Yy9tZG0ucGVtIFwKICAtdiAvdmFyL2V0dzovdmFyL2V0dzp6IFwKICAkTURNSU1BR0UgXAogIC1DZXJ0RmlsZSAvZXRjL21kbS5wZW0gXAogIC1Gcm9udEVuZFVybCAkTURNRlJPTlRFTkRVUkwgXAogIC1Mb2dnZXIgQ29uc29sZSBcCiAgLUxvZ0xldmVsIFdhcm5pbmcgXAogIC1Qcml2YXRlS2V5RmlsZSAvZXRjL21kbS5wZW0gXAogIC1Tb3VyY2VFbnZpcm9ubWVudCAkTURNU09VUkNFRU5WSVJPTk1FTlQgXAogIC1Tb3VyY2VSb2xlICRNRE1TT1VSQ0VST0xFIFwKICAtU291cmNlUm9sZUluc3RhbmNlICRNRE1TT1VSQ0VST0xFSU5TVEFOQ0UKRXhlY1N0b3A9L3Vzci9iaW4vZG9ja2VyIHN0b3AgJU4KUmVzdGFydD1hbHdheXMKUmVzdGFydFNlYz0xClN0YXJ0TGltaXRJbnRlcnZhbD0wCgpbSW5zdGFsbF0KV2FudGVkQnk9bXVsdGktdXNlci50YXJnZXQiCgogICAgd3JpdGVfZmlsZSBtZG1fc2VydmljZV9maWxlbmFtZSBtZG1fc2VydmljZV9maWxlIHRydWUKfQoKIyBjb25maWd1cmVfdGltZXJzX21kbV9tZHNkCmNvbmZpZ3VyZV90aW1lcnNfbWRtX21kc2QoKSB7CiAgICBsb2cgInN0YXJ0aW5nIgoKICAgIGZvciB2YXIgaW4gIm1kc2QiICJtZG0iOyBkbwogICAgICAgIGxvY2FsIGRvd25sb2FkX2NyZWRzX3NlcnZpY2VfZmlsZW5hbWU9Ii9ldGMvc3lzdGVtZC9zeXN0ZW0vZG93bmxvYWQtJHZhci1jcmVkZW50aWFscy5zZXJ2aWNlIgogICAgICAgIGxvY2FsIGRvd25sb2FkX2NyZWRzX3NlcnZpY2VfZmlsZT0iW1VuaXRdCkRlc2NyaXB0aW9uPVBlcmlvZGljICR2YXIgY3JlZGVudGlhbHMgcmVmcmVzaAoKW1NlcnZpY2VdClR5cGU9b25lc2hvdApFeGVjU3RhcnQ9L3Vzci9sb2NhbC9iaW4vZG93bmxvYWQtY3JlZGVudGlhbHMuc2ggJHZhciIKCiAgICAgICAgd3JpdGVfZmlsZSBkb3dubG9hZF9jcmVkc19zZXJ2aWNlX2ZpbGVuYW1lIGRvd25sb2FkX2NyZWRzX3NlcnZpY2VfZmlsZSB0cnVlCgogICAgICAgIGxvY2FsIGRvd25sb2FkX2NyZWRzX3RpbWVyX2ZpbGVuYW1lPSIvZXRjL3N5c3RlbWQvc3lzdGVtL2Rvd25sb2FkLSR2YXItY3JlZGVudGlhbHMudGltZXIiCiAgICAgICAgbG9jYWwgZG93bmxvYWRfY3JlZHNfdGltZXJfZmlsZT0iW1VuaXRdCkRlc2NyaXB0aW9uPVBlcmlvZGljICR2YXIgY3JlZGVudGlhbHMgcmVmcmVzaApBZnRlcj1uZXR3b3JrLW9ubGluZS50YXJnZXQKV2FudHM9bmV0d29yay1vbmxpbmUudGFyZ2V0CgpbVGltZXJdCk9uQm9vdFNlYz0wbWluCk9uQ2FsZW5kYXI9MC8xMjowMDowMApBY2N1cmFjeVNlYz01cwoKW0luc3RhbGxdCldhbnRlZEJ5PXRpbWVycy50YXJnZXQiCgogICAgICAgIHdyaXRlX2ZpbGUgZG93bmxvYWRfY3JlZHNfdGltZXJfZmlsZW5hbWUgZG93bmxvYWRfY3JlZHNfdGltZXJfZmlsZSB0cnVlCiAgICBkb25lCgogICAgbG9jYWwgLXIgZG93bmxvYWRfY3JlZHNfc2NyaXB0X2ZpbGVuYW1lPSIvdXNyL2xvY2FsL2Jpbi9kb3dubG9hZC1jcmVkZW50aWFscy5zaCIKICAgIGxvY2FsIC1yIGRvd25sb2FkX2NyZWRzX3NjcmlwdF9maWxlPSIjIS9iaW4vYmFzaApzZXQgLWV1CgpDT01QT05FTlQ9XCQxCmVjaG8gXCJEb3dubG9hZCBcJENPTVBPTkVOVCBjcmVkZW50aWFsc1wiCgpURU1QX0RJUj1cIlwkKG1rdGVtcCAtZClcIgpleHBvcnQgQVpVUkVfQ09ORklHX0RJUj1cIlwkKG1rdGVtcCAtZClcIgoKZWNobyBcIkxvZ2dpbmcgaW50byBBenVyZS4uLlwiClJFVFJJRVM9Mwp3aGlsZSBbWyBcJFJFVFJJRVMgLWd0IDAgXV07IGRvCiAgICBpZiBheiBsb2dpbiAtaSAtLWFsbG93LW5vLXN1YnNjcmlwdGlvbnMKICAgIHRoZW4KICAgICAgICBlY2hvIFwiYXogbG9naW4gc3VjY2Vzc2Z1bFwiCiAgICAgICAgYnJlYWsKICAgIGVsc2UKICAgICAgICBlY2hvIFwiYXogbG9naW4gZmFpbGVkLiBSZXRyeWluZy4uLlwiCiAgICAgICAgbGV0IFJFVFJJRVMtPTEKICAgICAgICBzbGVlcCA1CiAgICBmaQpkb25lCgp0cmFwIFwiY2xlYW51cFwiIEVYSVQKCmNsZWFudXAoKSB7CiAgYXogbG9nb3V0CiAgW1sgXCRURU1QX0RJUiA9fiAvdG1wLy4rIF1dICYmIHJtIC1yZiBcJFRFTVBfRElSCiAgW1sgXCRBWlVSRV9DT05GSUdfRElSID1+IC90bXAvLisgXV0gJiYgcm0gLXJmIFwkQVpVUkVfQ09ORklHX0RJUgp9CgppZiBbWyBcJENPTVBPTkVOVCA9IFwibWRtXCIgXV07IHRoZW4KICBDVVJSRU5UX0NFUlRfRklMRT1cIi9ldGMvbWRtLnBlbVwiCmVsaWYgW1sgXCRDT01QT05FTlRcID0gXCJtZHNkXCIgXV07IHRoZW4KICBDVVJSRU5UX0NFUlRfRklMRT1cIi92YXIvbGliL3dhYWdlbnQvTWljcm9zb2Z0LkF6dXJlLktleVZhdWx0LlN0b3JlL21kc2QucGVtXCIKZWxzZQogIGVjaG8gSW52YWxpZCB1c2FnZSAmJiBleGl0IDEKZmkKClNFQ1JFVF9OQU1FPVwicnAtXCR7Q09NUE9ORU5UfVwiCk5FV19DRVJUX0ZJTEU9XCJcJFRFTVBfRElSL1wkQ09NUE9ORU5ULnBlbVwiCmZvciBhdHRlbXB0IGluIHsxLi41fTsgZG8KICBheiBrZXl2YXVsdCBcCiAgICBzZWNyZXQgXAogICAgZG93bmxvYWQgXAogICAgLS1maWxlIFwiXCRORVdfQ0VSVF9GSUxFXCIgXAogICAgLS1pZCBcImh0dHBzOi8vJEtFWVZBVUxUUFJFRklYLXN2Yy4kS0VZVkFVTFRETlNTVUZGSVgvc2VjcmV0cy9cJFNFQ1JFVF9OQU1FXCIgXAogICAgJiYgYnJlYWsKICBpZiBbWyBcJGF0dGVtcHQgLWx0IDUgXV07IHRoZW4gc2xlZXAgMTA7IGVsc2UgZXhpdCAxOyBmaQpkb25lCgppZiBbIC1mIFwkTkVXX0NFUlRfRklMRSBdOyB0aGVuCiAgaWYgW1sgXCRDT01QT05FTlQgPSBcIm1kc2RcIiBdXTsgdGhlbgogICAgY2hvd24gc3lzbG9nOnN5c2xvZyBcJE5FV19DRVJUX0ZJTEUKICBlbHNlCiAgICBzZWQgLWkgLW5lICcxLC9FTkQgQ0VSVElGSUNBVEUvIHAnIFwkTkVXX0NFUlRfRklMRQogIGZpCgogIG5ld19jZXJ0X3NuPVwiXCQob3BlbnNzbCB4NTA5IC1pbiBcIlwkTkVXX0NFUlRfRklMRVwiIC1ub291dCAtc2VyaWFsIHwgYXdrIC1GPSAne3ByaW50IFwkMn0nKVwiCiAgY3VycmVudF9jZXJ0X3NuPVwiXCQob3BlbnNzbCB4NTA5IC1pbiBcIlwkQ1VSUkVOVF9DRVJUX0ZJTEVcIiAtbm9vdXQgLXNlcmlhbCB8IGF3ayAtRj0gJ3twcmludCBcJDJ9JylcIgogIGlmIFtbICEgLXogXCRuZXdfY2VydF9zbiBdXSAmJiBbWyBcJG5ld19jZXJ0X3NuICE9IFwiXCRjdXJyZW50X2NlcnRfc25cIiBdXTsgdGhlbgogICAgZWNobyB1cGRhdGluZyBjZXJ0aWZpY2F0ZSBmb3IgXCRDT01QT05FTlQKICAgIGNobW9kIDA2MDAgXCRORVdfQ0VSVF9GSUxFCiAgICBtdiBcJE5FV19DRVJUX0ZJTEUgXCRDVVJSRU5UX0NFUlRfRklMRQogIGZpCmVsc2UKICBlY2hvIEZhaWxlZCB0byByZWZyZXNoIGNlcnRpZmljYXRlIGZvciBcJENPTVBPTkVOVCAmJiBleGl0IDEKZmkiCgogICAgd3JpdGVfZmlsZSBkb3dubG9hZF9jcmVkc19zY3JpcHRfZmlsZW5hbWUgZG93bmxvYWRfY3JlZHNfc2NyaXB0X2ZpbGUgdHJ1ZQoKICAgIGNobW9kIHUreCAvdXNyL2xvY2FsL2Jpbi9kb3dubG9hZC1jcmVkZW50aWFscy5zaAoKICAgIHN5c3RlbWN0bCBlbmFibGUgZG93bmxvYWQtbWRzZC1jcmVkZW50aWFscy50aW1lcgogICAgc3lzdGVtY3RsIGVuYWJsZSBkb3dubG9hZC1tZG0tY3JlZGVudGlhbHMudGltZXIKCiAgICAvdXNyL2xvY2FsL2Jpbi9kb3dubG9hZC1jcmVkZW50aWFscy5zaCBtZHNkCiAgICAvdXNyL2xvY2FsL2Jpbi9kb3dubG9hZC1jcmVkZW50aWFscy5zaCBtZG0KCiAgICBsb2NhbCAtciBNRFNEQ0VSVElGSUNBVEVTQU49IiQob3BlbnNzbCB4NTA5IC1pbiAvdmFyL2xpYi93YWFnZW50L01pY3Jvc29mdC5BenVyZS5LZXlWYXVsdC5TdG9yZS9tZHNkLnBlbSAtbm9vdXQgLXN1YmplY3QgfCBzZWQgLWUgJ3MvLipDTiA9IC8vJykiCiAgICBsb2NhbCAtciB3YXRjaF9tZG1fY3JlZHNfc2VydmljZV9maWxlbmFtZT0iL2V0Yy9zeXN0ZW1kL3N5c3RlbS93YXRjaC1tZG0tY3JlZGVudGlhbHMuc2VydmljZSIKICAgIGxvY2FsIC1yIHdhdGNoX21kbV9jcmVkc19zZXJ2aWNlX2ZpbGU9IltVbml0XQpEZXNjcmlwdGlvbj1XYXRjaCBmb3IgY2hhbmdlcyBpbiBtZG0ucGVtIGFuZCByZXN0YXJ0cyB0aGUgbWRtIHNlcnZpY2UKCltTZXJ2aWNlXQpUeXBlPW9uZXNob3QKRXhlY1N0YXJ0PS91c3IvYmluL3N5c3RlbWN0bCByZXN0YXJ0IG1kbS5zZXJ2aWNlCgpbSW5zdGFsbF0KV2FudGVkQnk9bXVsdGktdXNlci50YXJnZXQiCgogICAgd3JpdGVfZmlsZSB3YXRjaF9tZG1fY3JlZHNfc2VydmljZV9maWxlbmFtZSB3YXRjaF9tZG1fY3JlZHNfc2VydmljZV9maWxlIHRydWUKCiAgICBsb2NhbCAtciB3YXRjaF9tZG1fY3JlZHNfcGF0aF9maWxlbmFtZT0nL2V0Yy9zeXN0ZW1kL3N5c3RlbS93YXRjaC1tZG0tY3JlZGVudGlhbHMucGF0aCcKICAgIGxvY2FsIC1yIHdhdGNoX21kbV9jcmVkc19wYXRoX2ZpbGU9J1tQYXRoXQpQYXRoTW9kaWZpZWQ9L2V0Yy9tZG0ucGVtCgpbSW5zdGFsbF0KV2FudGVkQnk9bXVsdGktdXNlci50YXJnZXQnCgogICAgd3JpdGVfZmlsZSB3YXRjaF9tZG1fY3JlZHNfcGF0aF9maWxlbmFtZSB3YXRjaF9tZG1fY3JlZHNfcGF0aF9maWxlIHRydWUKCiAgICBsb2NhbCAtciB3YXRjaF9tZG1fY3JlZHM9J3dhdGNoLW1kbS1jcmVkZW50aWFscy5wYXRoJwogICAgc3lzdGVtY3RsIGVuYWJsZSAiJHdhdGNoX21kbV9jcmVkcyIgfHwgYWJvcnQgImZhaWxlZCB0byBlbmFibGUgJHdhdGNoX21kbV9jcmVkcyIKICAgIHN5c3RlbWN0bCBzdGFydCAiJHdhdGNoX21kbV9jcmVkcyIgfHwgYWJvcnQgImZhaWxlZCB0byBzdGFydCAkd2F0Y2hfbWRtX2NyZWRzIgp9CgojIGNvbmZpZ3VyZV9zZXJ2aWNlX2Fyb19ycApjb25maWd1cmVfc2VydmljZV9hcm9fcnAoKSB7CiAgICBsb2cgInN0YXJ0aW5nIgoKICAgIGxvY2FsIC1yIGFyb19ycF9jb25mX2ZpbGVuYW1lPScvZXRjL3N5c2NvbmZpZy9hcm8tcnAnCiAgICBsb2NhbCAtciBhcm9fcnBfY29uZl9maWxlPSJBQ1JfUkVTT1VSQ0VfSUQ9JyRBQ1JSRVNPVVJDRUlEJwpBRE1JTl9BUElfQ0xJRU5UX0NFUlRfQ09NTU9OX05BTUU9JyRBRE1JTkFQSUNMSUVOVENFUlRDT01NT05OQU1FJwpBUk1fQVBJX0NMSUVOVF9DRVJUX0NPTU1PTl9OQU1FPSckQVJNQVBJQ0xJRU5UQ0VSVENPTU1PTk5BTUUnCkFaVVJFX0FSTV9DTElFTlRfSUQ9JyRBUk1DTElFTlRJRCcKQVpVUkVfRlBfQ0xJRU5UX0lEPSckRlBDTElFTlRJRCcKQVpVUkVfRlBfU0VSVklDRV9QUklOQ0lQQUxfSUQ9JyRGUFNFUlZJQ0VQUklOQ0lQQUxJRCcKQklMTElOR19FMkVfU1RPUkFHRV9BQ0NPVU5UX0lEPSckQklMTElOR0UyRVNUT1JBR0VBQ0NPVU5USUQnCkNMVVNURVJfTURNX0FDQ09VTlQ9JyRDTFVTVEVSTURNQUNDT1VOVCcKQ0xVU1RFUl9NRE1fTkFNRVNQQUNFPVJQCkNMVVNURVJfTURTRF9BQ0NPVU5UPSckQ0xVU1RFUk1EU0RBQ0NPVU5UJwpDTFVTVEVSX01EU0RfQ09ORklHX1ZFUlNJT049JyRDTFVTVEVSTURTRENPTkZJR1ZFUlNJT04nCkNMVVNURVJfTURTRF9OQU1FU1BBQ0U9JyRDTFVTVEVSTURTRE5BTUVTUEFDRScKREFUQUJBU0VfQUNDT1VOVF9OQU1FPSckREFUQUJBU0VBQ0NPVU5UTkFNRScKRE9NQUlOX05BTUU9JyRMT0NBVElPTi4kQ0xVU1RFUlBBUkVOVERPTUFJTk5BTUUnCkdBVEVXQVlfRE9NQUlOUz0nJEdBVEVXQVlET01BSU5TJwpHQVRFV0FZX1JFU09VUkNFR1JPVVA9JyRHQVRFV0FZUkVTT1VSQ0VHUk9VUE5BTUUnCktFWVZBVUxUX1BSRUZJWD0nJEtFWVZBVUxUUFJFRklYJwpNRE1fQUNDT1VOVD0nJFJQTURNQUNDT1VOVCcKTURNX05BTUVTUEFDRT1SUApNRFNEX0VOVklST05NRU5UPSckTURTREVOVklST05NRU5UJwpSUF9GRUFUVVJFUz0nJFJQRkVBVFVSRVMnClJQSU1BR0U9JyRSUElNQUdFJwpBUk9fSU5TVEFMTF9WSUFfSElWRT0nJENMVVNURVJTSU5TVEFMTFZJQUhJVkUnCkFST19ISVZFX0RFRkFVTFRfSU5TVEFMTEVSX1BVTExTUEVDPSckQ0xVU1RFUkRFRkFVTFRJTlNUQUxMRVJQVUxMU1BFQycKQVJPX0FET1BUX0JZX0hJVkU9JyRDTFVTVEVSU0FET1BUQllISVZFJwpVU0VfQ0hFQ0tBQ0NFU1M9JyRVU0VDSEVDS0FDQ0VTUyciCgogICAgd3JpdGVfZmlsZSBhcm9fcnBfY29uZl9maWxlbmFtZSBhcm9fcnBfY29uZl9maWxlIHRydWUKCiAgICBsb2NhbCAtciBhcm9fcnBfc2VydmljZV9maWxlbmFtZT0nL2V0Yy9zeXN0ZW1kL3N5c3RlbS9hcm8tcnAuc2VydmljZScKICAgIGxvY2FsIC1yIGFyb19ycF9zZXJ2aWNlX2ZpbGU9IltVbml0XQpBZnRlcj1uZXR3b3JrLW9ubGluZS50YXJnZXQKV2FudHM9bmV0d29yay1vbmxpbmUudGFyZ2V0CgpbU2VydmljZV0KRW52aXJvbm1lbnRGaWxlPS9ldGMvc3lzY29uZmlnL2Fyby1ycApFeGVjU3RhcnRQcmU9LS91c3IvYmluL2RvY2tlciBybSAtZiAlTgpFeGVjU3RhcnQ9L3Vzci9iaW4vZG9ja2VyIHJ1biBcCiAgLS1ob3N0bmFtZSAlSCBcCiAgLS1uYW1lICVOIFwKICAtLXJtIFwKICAtLWNhcC1kcm9wIG5ldF9yYXcgXAogIC1lIEFDUl9SRVNPVVJDRV9JRCBcCiAgLWUgQURNSU5fQVBJX0NMSUVOVF9DRVJUX0NPTU1PTl9OQU1FIFwKICAtZSBBUk1fQVBJX0NMSUVOVF9DRVJUX0NPTU1PTl9OQU1FIFwKICAtZSBBWlVSRV9BUk1fQ0xJRU5UX0lEIFwKICAtZSBBWlVSRV9GUF9DTElFTlRfSUQgXAogIC1lIEJJTExJTkdfRTJFX1NUT1JBR0VfQUNDT1VOVF9JRCBcCiAgLWUgQ0xVU1RFUl9NRE1fQUNDT1VOVCBcCiAgLWUgQ0xVU1RFUl9NRE1fTkFNRVNQQUNFIFwKICAtZSBDTFVTVEVSX01EU0RfQUNDT1VOVCBcCiAgLWUgQ0xVU1RFUl9NRFNEX0NPTkZJR19WRVJTSU9OIFwKICAtZSBDTFVTVEVSX01EU0RfTkFNRVNQQUNFIFwKICAtZSBEQVRBQkFTRV9BQ0NPVU5UX05BTUUgXAogIC1lIERPTUFJTl9OQU1FIFwKICAtZSBHQVRFV0FZX0RPTUFJTlMgXAogIC1lIEdBVEVXQVlfUkVTT1VSQ0VHUk9VUCBcCiAgLWUgS0VZVkFVTFRfUFJFRklYIFwKICAtZSBNRE1fQUNDT1VOVCBcCiAgLWUgTURNX05BTUVTUEFDRSBcCiAgLWUgTURTRF9FTlZJUk9OTUVOVCBcCiAgLWUgUlBfRkVBVFVSRVMgXAogIC1lIEFST19JTlNUQUxMX1ZJQV9ISVZFIFwKICAtZSBBUk9fSElWRV9ERUZBVUxUX0lOU1RBTExFUl9QVUxMU1BFQyBcCiAgLWUgQVJPX0FET1BUX0JZX0hJVkUgXAogIC1lIFVTRV9DSEVDS0FDQ0VTUyBcCiAgLW0gMmcgXAogIC1wIDQ0Mzo4NDQzIFwKICAtdiAvZXRjL2Fyby1ycDovZXRjL2Fyby1ycCBcCiAgLXYgL3J1bi9zeXN0ZW1kL2pvdXJuYWw6L3J1bi9zeXN0ZW1kL2pvdXJuYWwgXAogIC12IC92YXIvZXR3Oi92YXIvZXR3OnogXAogICRSUElNQUdFIFwKICBycApFeGVjU3RvcD0vdXNyL2Jpbi9kb2NrZXIgc3RvcCAtdCAzNjAwICVOClRpbWVvdXRTdG9wU2VjPTM2MDAKUmVzdGFydD1hbHdheXMKUmVzdGFydFNlYz0xClN0YXJ0TGltaXRJbnRlcnZhbD0wCgpbSW5zdGFsbF0KV2FudGVkQnk9bXVsdGktdXNlci50YXJnZXQiCgogICAgd3JpdGVfZmlsZSBhcm9fcnBfc2VydmljZV9maWxlbmFtZSBhcm9fcnBfc2VydmljZV9maWxlIHRydWUKfQoKIyBjb25maWd1cmVfc2VydmljZV9hcm9fZGJ0b2tlbgpjb25maWd1cmVfc2VydmljZV9hcm9fZGJ0b2tlbigpIHsKICAgIGxvZyAic3RhcnRpbmciCgogICAgbG9jYWwgLXIgYXJvX2RidG9rZW5fc2VydmljZV9jb25mX2ZpbGVuYW1lPScvZXRjL3N5c2NvbmZpZy9hcm8tZGJ0b2tlbicKICAgIGxvY2FsIC1yIGFyb19kYnRva2VuX3NlcnZpY2VfY29uZl9maWxlPSJEQVRBQkFTRV9BQ0NPVU5UX05BTUU9JyREQVRBQkFTRUFDQ09VTlROQU1FJwpBWlVSRV9EQlRPS0VOX0NMSUVOVF9JRD0nJERCVE9LRU5DTElFTlRJRCcKQVpVUkVfR0FURVdBWV9TRVJWSUNFX1BSSU5DSVBBTF9JRD0nJEdBVEVXQVlTRVJWSUNFUFJJTkNJUEFMSUQnCktFWVZBVUxUX1BSRUZJWD0nJEtFWVZBVUxUUFJFRklYJwpNRE1fQUNDT1VOVD0nJFJQTURNQUNDT1VOVCcKTURNX05BTUVTUEFDRT1EQlRva2VuClJQSU1BR0U9JyRSUElNQUdFJyIKCiAgICB3cml0ZV9maWxlIGFyb19kYnRva2VuX3NlcnZpY2VfY29uZl9maWxlbmFtZSBhcm9fZGJ0b2tlbl9zZXJ2aWNlX2NvbmZfZmlsZSB0cnVlCgogICAgbG9jYWwgLXIgYXJvX2RidG9rZW5fc2VydmljZV9maWxlbmFtZT0nL2V0Yy9zeXN0ZW1kL3N5c3RlbS9hcm8tZGJ0b2tlbi5zZXJ2aWNlJwogICAgbG9jYWwgLXIgYXJvX2RidG9rZW5fc2VydmljZV9maWxlPSJbVW5pdF0KQWZ0ZXI9bmV0d29yay1vbmxpbmUudGFyZ2V0CldhbnRzPW5ldHdvcmstb25saW5lLnRhcmdldAoKW1NlcnZpY2VdCkVudmlyb25tZW50RmlsZT0vZXRjL3N5c2NvbmZpZy9hcm8tZGJ0b2tlbgpFeGVjU3RhcnRQcmU9LS91c3IvYmluL2RvY2tlciBybSAtZiAlTgpFeGVjU3RhcnQ9L3Vzci9iaW4vZG9ja2VyIHJ1biBcCiAgLS1ob3N0bmFtZSAlSCBcCiAgLS1uYW1lICVOIFwKICAtLXJtIFwKICAtLWNhcC1kcm9wIG5ldF9yYXcgXAogIC1lIEFaVVJFX0dBVEVXQVlfU0VSVklDRV9QUklOQ0lQQUxfSUQgXAogIC1lIERBVEFCQVNFX0FDQ09VTlRfTkFNRSBcCiAgLWUgQVpVUkVfREJUT0tFTl9DTElFTlRfSUQgXAogIC1lIEtFWVZBVUxUX1BSRUZJWCBcCiAgLWUgTURNX0FDQ09VTlQgXAogIC1lIE1ETV9OQU1FU1BBQ0UgXAogIC1tIDJnIFwKICAtcCA0NDU6ODQ0NSBcCiAgLXYgL3J1bi9zeXN0ZW1kL2pvdXJuYWw6L3J1bi9zeXN0ZW1kL2pvdXJuYWwgXAogIC12IC92YXIvZXR3Oi92YXIvZXR3OnogXAogICRSUElNQUdFIFwKICBkYnRva2VuCkV4ZWNTdG9wPS91c3IvYmluL2RvY2tlciBzdG9wIC10IDM2MDAgJU4KVGltZW91dFN0b3BTZWM9MzYwMApSZXN0YXJ0PWFsd2F5cwpSZXN0YXJ0U2VjPTEKU3RhcnRMaW1pdEludGVydmFsPTAKCltJbnN0YWxsXQpXYW50ZWRCeT1tdWx0aS11c2VyLnRhcmdldCIKCiAgICB3cml0ZV9maWxlIGFyb19kYnRva2VuX3NlcnZpY2VfZmlsZW5hbWUgYXJvX2RidG9rZW5fc2VydmljZV9maWxlIHRydWUKfQoKIyBjb25maWd1cmVfc2VydmljZV9hcm9fbW9uaXRvcgpjb25maWd1cmVfc2VydmljZV9hcm9fbW9uaXRvcigpIHsKICAgIGxvZyAic3RhcnRpbmciCiAgICBsb2cgImNvbmZpZ3VyaW5nIGFyby1tb25pdG9yIHNlcnZpY2UiCgogICAgIyBET01BSU5fTkFNRSwgQ0xVU1RFUl9NRFNEX0FDQ09VTlQsIENMVVNURVJfTURTRF9DT05GSUdfVkVSU0lPTiwgR0FURVdBWV9ET01BSU5TLCBHQVRFV0FZX1JFU09VUkNFR1JPVVAsIE1EU0RfRU5WSVJPTk1FTlQgQ0xVU1RFUl9NRFNEX05BTUVTUEFDRQogICAgIyBhcmUgbm90IHVzZWQsIGJ1dCBjYW4ndCBlYXNpbHkgYmUgcmVmYWN0b3JlZCBvdXQuIFNob3VsZCBiZSByZXZpc2l0ZWQgaW4gdGhlIGZ1dHVyZS4KICAgIGxvY2FsIC1yIGFyb19tb25pdG9yX3NlcnZpY2VfY29uZl9maWxlbmFtZT0nL2V0Yy9zeXNjb25maWcvYXJvLW1vbml0b3InCiAgICBsb2NhbCAtciBhcm9fbW9uaXRvcl9zZXJ2aWNlX2NvbmZfZmlsZT0iQVpVUkVfRlBfQ0xJRU5UX0lEPSckRlBDTElFTlRJRCcKRE9NQUlOX05BTUU9JyRMT0NBVElPTi4kQ0xVU1RFUlBBUkVOVERPTUFJTk5BTUUnCkNMVVNURVJfTURTRF9BQ0NPVU5UPSckQ0xVU1RFUk1EU0RBQ0NPVU5UJwpDTFVTVEVSX01EU0RfQ09ORklHX1ZFUlNJT049JyRDTFVTVEVSTURTRENPTkZJR1ZFUlNJT04nCkdBVEVXQVlfRE9NQUlOUz0nJEdBVEVXQVlET01BSU5TJwpHQVRFV0FZX1JFU09VUkNFR1JPVVA9JyRHQVRFV0FZUkVTT1VSQ0VHUk9VUE5BTUUnCk1EU0RfRU5WSVJPTk1FTlQ9JyRNRFNERU5WSVJPTk1FTlQnCkNMVVNURVJfTURTRF9OQU1FU1BBQ0U9JyRDTFVTVEVSTURTRE5BTUVTUEFDRScKQ0xVU1RFUl9NRE1fQUNDT1VOVD0nJENMVVNURVJNRE1BQ0NPVU5UJwpDTFVTVEVSX01ETV9OQU1FU1BBQ0U9QkJNCkRBVEFCQVNFX0FDQ09VTlRfTkFNRT0nJERBVEFCQVNFQUNDT1VOVE5BTUUnCktFWVZBVUxUX1BSRUZJWD0nJEtFWVZBVUxUUFJFRklYJwpNRE1fQUNDT1VOVD0nJFJQTURNQUNDT1VOVCcKTURNX05BTUVTUEFDRT1CQk0KUlBJTUFHRT0nJFJQSU1BR0UnIgoKICAgIHdyaXRlX2ZpbGUgYXJvX21vbml0b3Jfc2VydmljZV9jb25mX2ZpbGVuYW1lIGFyb19tb25pdG9yX3NlcnZpY2VfY29uZl9maWxlIHRydWUKCiAgICBsb2NhbCAtciBhcm9fbW9uaXRvcl9zZXJ2aWNlX2ZpbGVuYW1lPScvZXRjL3N5c3RlbWQvc3lzdGVtL2Fyby1tb25pdG9yLnNlcnZpY2UnCiAgICBsb2NhbCAtciBhcm9fbW9uaXRvcl9zZXJ2aWNlX2ZpbGU9IltVbml0XQpBZnRlcj1uZXR3b3JrLW9ubGluZS50YXJnZXQKV2FudHM9bmV0d29yay1vbmxpbmUudGFyZ2V0CgpbU2VydmljZV0KRW52aXJvbm1lbnRGaWxlPS9ldGMvc3lzY29uZmlnL2Fyby1tb25pdG9yCkV4ZWNTdGFydFByZT0tL3Vzci9iaW4vZG9ja2VyIHJtIC1mICVOCkV4ZWNTdGFydD0vdXNyL2Jpbi9kb2NrZXIgcnVuIFwKICAtLWhvc3RuYW1lICVIIFwKICAtLW5hbWUgJU4gXAogIC0tcm0gXAogIC0tY2FwLWRyb3AgbmV0X3JhdyBcCiAgLWUgQVpVUkVfRlBfQ0xJRU5UX0lEIFwKICAtZSBET01BSU5fTkFNRSBcCiAgLWUgQ0xVU1RFUl9NRFNEX0FDQ09VTlQgXAogIC1lIENMVVNURVJfTURTRF9DT05GSUdfVkVSU0lPTiBcCiAgLWUgR0FURVdBWV9ET01BSU5TIFwKICAtZSBHQVRFV0FZX1JFU09VUkNFR1JPVVAgXAogIC1lIE1EU0RfRU5WSVJPTk1FTlQgXAogIC1lIENMVVNURVJfTURTRF9OQU1FU1BBQ0UgXAogIC1lIENMVVNURVJfTURNX0FDQ09VTlQgXAogIC1lIENMVVNURVJfTURNX05BTUVTUEFDRSBcCiAgLWUgREFUQUJBU0VfQUNDT1VOVF9OQU1FIFwKICAtZSBLRVlWQVVMVF9QUkVGSVggXAogIC1lIE1ETV9BQ0NPVU5UIFwKICAtZSBNRE1fTkFNRVNQQUNFIFwKICAtbSAyLjVnIFwKICAtdiAvcnVuL3N5c3RlbWQvam91cm5hbDovcnVuL3N5c3RlbWQvam91cm5hbCBcCiAgLXYgL3Zhci9ldHc6L3Zhci9ldHc6eiBcCiAgJFJQSU1BR0UgXAogIG1vbml0b3IKUmVzdGFydD1hbHdheXMKUmVzdGFydFNlYz0xClN0YXJ0TGltaXRJbnRlcnZhbD0wCgpbSW5zdGFsbF0KV2FudGVkQnk9bXVsdGktdXNlci50YXJnZXQiCgogICAgd3JpdGVfZmlsZSBhcm9fbW9uaXRvcl9zZXJ2aWNlX2ZpbGVuYW1lIGFyb19tb25pdG9yX3NlcnZpY2VfZmlsZSB0cnVlCn0KCiMgY29uZmlndXJlX3NlcnZpY2VfYXJvX3BvcnRhbApjb25maWd1cmVfc2VydmljZV9hcm9fcG9ydGFsKCkgewogICAgbG9nICJzdGFydGluZyIKCiAgICBsb2NhbCAtciBhcm9fcG9ydGFsX3NlcnZpY2VfY29uZl9maWxlbmFtZT0nL2V0Yy9zeXNjb25maWcvYXJvLXBvcnRhbCcKICAgIGxvY2FsIC1yIGFyb19wb3J0YWxfc2VydmljZV9jb25mX2ZpbGU9IkFaVVJFX1BPUlRBTF9BQ0NFU1NfR1JPVVBfSURTPSckUE9SVEFMQUNDRVNTR1JPVVBJRFMnCkFaVVJFX1BPUlRBTF9DTElFTlRfSUQ9JyRQT1JUQUxDTElFTlRJRCcKQVpVUkVfUE9SVEFMX0VMRVZBVEVEX0dST1VQX0lEUz0nJFBPUlRBTEVMRVZBVEVER1JPVVBJRFMnCkRBVEFCQVNFX0FDQ09VTlRfTkFNRT0nJERBVEFCQVNFQUNDT1VOVE5BTUUnCktFWVZBVUxUX1BSRUZJWD0nJEtFWVZBVUxUUFJFRklYJwpNRE1fQUNDT1VOVD0nJFJQTURNQUNDT1VOVCcKTURNX05BTUVTUEFDRT1Qb3J0YWwKUE9SVEFMX0hPU1ROQU1FPSckTE9DQVRJT04uYWRtaW4uJFJQUEFSRU5URE9NQUlOTkFNRScKUlBJTUFHRT0nJFJQSU1BR0UnIgoKICAgIHdyaXRlX2ZpbGUgYXJvX3BvcnRhbF9zZXJ2aWNlX2NvbmZfZmlsZW5hbWUgYXJvX3BvcnRhbF9zZXJ2aWNlX2NvbmZfZmlsZSB0cnVlCgogICAgbG9jYWwgLXIgYXJvX3BvcnRhbF9zZXJ2aWNlX2ZpbGVuYW1lPScvZXRjL3N5c3RlbWQvc3lzdGVtL2Fyby1wb3J0YWwuc2VydmljZScKICAgIGxvY2FsIC1yIGFyb19wb3J0YWxfc2VydmljZV9maWxlPSJbVW5pdF0KQWZ0ZXI9bmV0d29yay1vbmxpbmUudGFyZ2V0CldhbnRzPW5ldHdvcmstb25saW5lLnRhcmdldApTdGFydExpbWl0SW50ZXJ2YWw9MAoKW1NlcnZpY2VdCkVudmlyb25tZW50RmlsZT0vZXRjL3N5c2NvbmZpZy9hcm8tcG9ydGFsCkV4ZWNTdGFydFByZT0tL3Vzci9iaW4vZG9ja2VyIHJtIC1mICVOCkV4ZWNTdGFydD0vdXNyL2Jpbi9kb2NrZXIgcnVuIFwKICAtLWhvc3RuYW1lICVIIFwKICAtLW5hbWUgJU4gXAogIC0tcm0gXAogIC0tY2FwLWRyb3AgbmV0X3JhdyBcCiAgLWUgQVpVUkVfUE9SVEFMX0FDQ0VTU19HUk9VUF9JRFMgXAogIC1lIEFaVVJFX1BPUlRBTF9DTElFTlRfSUQgXAogIC1lIEFaVVJFX1BPUlRBTF9FTEVWQVRFRF9HUk9VUF9JRFMgXAogIC1lIERBVEFCQVNFX0FDQ09VTlRfTkFNRSBcCiAgLWUgS0VZVkFVTFRfUFJFRklYIFwKICAtZSBNRE1fQUNDT1VOVCBcCiAgLWUgTURNX05BTUVTUEFDRSBcCiAgLWUgUE9SVEFMX0hPU1ROQU1FIFwKICAtbSAyZyBcCiAgLXAgNDQ0Ojg0NDQgXAogIC1wIDIyMjI6MjIyMiBcCiAgLXYgL3J1bi9zeXN0ZW1kL2pvdXJuYWw6L3J1bi9zeXN0ZW1kL2pvdXJuYWwgXAogIC12IC92YXIvZXR3Oi92YXIvZXR3OnogXAogICRSUElNQUdFIFwKICBwb3J0YWwKUmVzdGFydD1hbHdheXMKUmVzdGFydFNlYz0xCgpbSW5zdGFsbF0KV2FudGVkQnk9bXVsdGktdXNlci50YXJnZXQiCgogICAgd3JpdGVfZmlsZSBhcm9fcG9ydGFsX3NlcnZpY2VfZmlsZW5hbWUgYXJvX3BvcnRhbF9zZXJ2aWNlX2ZpbGUgdHJ1ZQp9CgojIGNvbmZpZ3VyZV9zZXJ2aWNlX21kc2QKY29uZmlndXJlX3NlcnZpY2VfbWRzZCgpIHsKICAgIGxvZyAic3RhcnRpbmciCgogICAgbG9jYWwgLXIgbWRzZF9zZXJ2aWNlX2Rpcj0iL2V0Yy9zeXN0ZW1kL3N5c3RlbS9tZHNkLnNlcnZpY2UuZCIKICAgIG1rZGlyIC1wICIkbWRzZF9zZXJ2aWNlX2RpciIKCiAgICBsb2NhbCAtciBtZHNkX292ZXJyaWRlX2NvbmZfZmlsZW5hbWU9IiRtZHNkX3NlcnZpY2VfZGlyL292ZXJyaWRlLmNvbmYiCiAgICBsb2NhbCAtciBtZHNkX292ZXJyaWRlX2NvbmZfZmlsZT0iW1VuaXRdCkFmdGVyPW5ldHdvcmstb25saW5lLnRhcmdldCIKCiAgICB3cml0ZV9maWxlIG1kc2Rfb3ZlcnJpZGVfY29uZl9maWxlbmFtZSBtZHNkX292ZXJyaWRlX2NvbmZfZmlsZSB0cnVlCgogICAgbG9jYWwgLXIgZGVmYXVsdF9tZHNkX2ZpbGVuYW1lPSIvZXRjL2RlZmF1bHQvbWRzZCIKICAgIGxvY2FsIC1yIGRlZmF1bHRfbWRzZF9maWxlPSJNRFNEX1JPTEVfUFJFRklYPS92YXIvcnVuL21kc2QvZGVmYXVsdApNRFNEX09QVElPTlM9XCItQSAtZCAtciBcJE1EU0RfUk9MRV9QUkVGSVhcIgoKZXhwb3J0IE1PTklUT1JJTkdfR0NTX0VOVklST05NRU5UPSckTURTREVOVklST05NRU5UJwpleHBvcnQgTU9OSVRPUklOR19HQ1NfQUNDT1VOVD0nJFJQTURTREFDQ09VTlQnCmV4cG9ydCBNT05JVE9SSU5HX0dDU19SRUdJT049JyRMT0NBVElPTicKZXhwb3J0IE1PTklUT1JJTkdfR0NTX0FVVEhfSURfVFlQRT1BdXRoS2V5VmF1bHQKZXhwb3J0IE1PTklUT1JJTkdfR0NTX0FVVEhfSUQ9JyRNRFNEQ0VSVElGSUNBVEVTQU4nCmV4cG9ydCBNT05JVE9SSU5HX0dDU19OQU1FU1BBQ0U9JyRSUE1EU0ROQU1FU1BBQ0UnCmV4cG9ydCBNT05JVE9SSU5HX0NPTkZJR19WRVJTSU9OPSckUlBNRFNEQ09ORklHVkVSU0lPTicKZXhwb3J0IE1PTklUT1JJTkdfVVNFX0dFTkVWQV9DT05GSUdfU0VSVklDRT10cnVlCgpleHBvcnQgTU9OSVRPUklOR19URU5BTlQ9JyRMT0NBVElPTicKZXhwb3J0IE1PTklUT1JJTkdfUk9MRT1ycApleHBvcnQgTU9OSVRPUklOR19ST0xFX0lOU1RBTkNFPVwiJChob3N0bmFtZSlcIgoKZXhwb3J0IE1EU0RfTVNHUEFDS19TT1JUX0NPTFVNTlM9MVwiIgoKICAgIHdyaXRlX2ZpbGUgZGVmYXVsdF9tZHNkX2ZpbGVuYW1lIGRlZmF1bHRfbWRzZF9maWxlIHRydWUKCn0KCiMgcnVuX2F6c2VjZF9jb25maWdfc2NhbgpydW5fYXpzZWNkX2NvbmZpZ19zY2FuKCkgewogICAgbG9nICJzdGFydGluZyIKCiAgICBsb2NhbCAtYXIgY29uZmlncz0oCiAgICAgICAgImJhc2VsaW5lIgogICAgICAgICJjbGFtYXYiCiAgICAgICAgInNvZnR3YXJlIgogICAgKQoKICAgIGxvZyAiU2Nhbm5pbmcgY29uZmlndXJhdGlvbiBmaWxlcyAke2NvbmZpZ3NbKl19IgogICAgIyBzaGVsbGNoZWNrIGRpc2FibGU9U0MyMDY4CiAgICBmb3Igc2NhbiBpbiAke2NvbmZpZ3NbQF19OyBkbwogICAgICAgIGxvZyAiU2Nhbm5pbmcgY29uZmlnIGZpbGUgJHNjYW4gbm93IgogICAgICAgIC91c3IvbG9jYWwvYmluL2F6c2VjZCBjb25maWcgLXMgIiRzY2FuIiAtZCBQMUQKICAgIGRvbmUKfQoKZXhwb3J0IEFaVVJFX0NMT1VEX05BTUU9IiR7QVpVUkVDTE9VRE5BTUU6PyJGYWlsZWQgdG8gY2Fycnkgb3ZlciB2YXJpYWJsZXMifSIKCm1haW4gIiRAIgo=')))]" } } } diff --git a/pkg/deploy/generator/scripts/common.sh b/pkg/deploy/generator/scripts/common.sh index 4d39f1dd291..436c89366a4 100644 --- a/pkg/deploy/generator/scripts/common.sh +++ b/pkg/deploy/generator/scripts/common.sh @@ -175,6 +175,7 @@ include /etc/logrotate.d # pull_container_images pull_container_images() { local -n pull_images="$1" + local -n registry_conf="${2:-}" log "starting" # The managed identity that the VM runs as only has a single roleassignment. @@ -190,9 +191,13 @@ pull_container_images() { mkdir -p /root/.docker touch /etc/containers/nodocker - # This name is used in the case that az acr login searches for this in it's environment + # This name is used in the case that az acr login searches for this in it's environment local -r REGISTRY_AUTH_FILE="/root/.docker/config.json" + if [[ -n $registry_conf ]]; then + write_file REGISTRY_AUTH_FILE registry_conf true + fi + log "logging into prod acr" az acr login --name "$(sed -e 's|.*/||' <<<"$ACRRESOURCEID")" @@ -210,9 +215,9 @@ enable_services() { local -n services="$1" log "starting" - log "enabling aro services ${aro_services[*]}" + log "enabling services ${services[*]}" # shellcheck disable=SC2068 - for service in ${aro_services[@]}; do + for service in ${services[@]}; do log "Enabling $service now" systemctl enable "$service.service" done @@ -259,3 +264,30 @@ abort() { log "Exiting" exit 1 } + +# configure_rhui_repo +configure_rhui_repo() { + log "starting" + + local -ra cmd=( + dnf + update + -y + --disablerepo='*' + --enablerepo='rhui-microsoft-azure*' + ) + + log "running RHUI package updates" + retry cmd "$1" +} + +configure_dnf_cron_job() { + log "Starting" + local -r cron_weekly_dnf_update_filename='/etc/cron.weekly/dnfupdate' + local -r cron_weekly_dnf_update_file="#!/bin/bash +dnf update -y" + + write_file cron_weekly_dnf_update_filename cron_weekly_dnf_update_file true + chmod +x "$cron_weekly_dnf_update_filename" +} + diff --git a/pkg/deploy/generator/scripts/devProxyVMSS.sh b/pkg/deploy/generator/scripts/devProxyVMSS.sh index 2b405881bce..19289b8ee1a 100644 --- a/pkg/deploy/generator/scripts/devProxyVMSS.sh +++ b/pkg/deploy/generator/scripts/devProxyVMSS.sh @@ -8,13 +8,48 @@ if [ "${DEBUG:-false}" == true ]; then fi main() { + # transaction attempt retry time in seconds + local -ri retry_wait_time=60 + + # shellcheck source=common.sh + source common.sh + + local -ra enable_ports=( + "443/tcp" + ) + + local proxy_image="$PROXYIMAGE" + local -r registry_config_file="{ + \"auths\": { + \"${PROXYIMAGE%%/*}\": { + \"auth\": \"$PROXYIMAGEAUTH\" + } + }" + + local -ar exclude_pkgs=( + "-x WALinuxAgent" + "-x WALinuxAgent-udev" + ) + + local -ra install_pkgs=( + podman + podman-docker + ) + + local -ra proxy_services=( + proxy + ) + parse_run_options "$@" - configure_and_install_dnf_pkgs_repos + dnf_update_pkgs pkgs_to_exclude retry_wait_time + dnf_install_pkgs install_pkgs retry_wait_time + configure_dnf_cron_job - configure_firewalld_rules - pull_container_images - configure_system_services + configure_firewalld_rules enable_ports + pull_container_images proxy_image registry_config_file + configure_devproxy_services + enable_services proxy_services reboot_vm } @@ -23,7 +58,7 @@ usage() { log "$(basename "$0") [$options] -p Configure rpm repositories, import required rpm keys, update & install packages with dnf -f Configure firewalld default zone rules - -u Configure systemd unit files for ARO RP + -u Configure systemd unit files -i Pull container images Note: steps will be executed in the order that flags are provided @@ -37,6 +72,12 @@ usage() { parse_run_options() { # shellcheck disable=SC2206 local -a options=(${1:-}) + local -n pkgs_to_exclude="$2" + local -n pkgs_to_install="$3" + local -n ports_to_enable="$4" + local -n services_to_enable="$5" + local -n images_to_pull="$6" + if [ "${#options[@]}" -eq 0 ]; then log "Running all steps" return 0 @@ -47,20 +88,27 @@ parse_run_options() { while getopts ${allowed_options} options; do case "${options}" in p) - log "Running step configure_and_install_dnf_pkgs_repos" - configure_and_install_dnf_pkgs_repos + log "Running step dnf_update_pkgs" + dnf_update_pkgs pkgs_to_exclude retry_wait_time + + log "Running step dnf_install_pkgs" + dnf_install_pkgs pkgs_to_install retry_wait_time + + log "Running step configure_dnf_cron_job" + configure_dnf_cron_job ;; f) log "Running configure_firewalld_rules" - configure_firewalld_rules + configure_firewalld_rules ports_to_enable ;; u) - log "Running pull_container_images & configure_system_services" - configure_system_services + log "Running step configure_devproxy_services" + configure_devproxy_services + enable_services services_to_enable ;; i) log "Running pull_container_images" - pull_container_images + pull_container_images images_to_pull ;; *) usage allowed_options @@ -72,223 +120,10 @@ parse_run_options() { exit 0 } -# configure_and_install_dnf_pkgs_repos -configure_and_install_dnf_pkgs_repos() { - log "starting" - - # transaction attempt retry time in seconds - local -ri retry_wait_time=60 - configure_rhui_repo retry_wait_time - - local -ar exclude_pkgs=( - "-x WALinuxAgent" - "-x WALinuxAgent-udev" - ) - - dnf_update_pkgs exclude_pkgs retry_wait_time - - local -ra repo_rpm_pkgs=( - https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm - ) - - local -ra install_pkgs=( - podman - podman-docker - ) - - dnf_install_pkgs repo_rpm_pkgs retry_wait_time - dnf_install_pkgs install_pkgs retry_wait_time - - local -r cron_weekly_dnf_update_filename='/etc/cron.weekly/dnfupdate' - local -r cron_weekly_dnf_update_file="#!/bin/bash -dnf update -y" - - write_file cron_weekly_dnf_update_filename cron_weekly_dnf_update_file true - chmod +x "$cron_weekly_dnf_update_filename" -} - -# configure_rhui_repo -configure_rhui_repo() { - log "starting" - - local -ra cmd=( - dnf - update - -y - --disablerepo='*' - --enablerepo='rhui-microsoft-azure*' - ) - - log "running RHUI package updates" - retry cmd "$1" -} - -# retry Adding retry logic to yum commands in order to avoid stalling out on resource locks -retry() { - local -n cmd_retry="$1" - local -n wait_time="$2" - - for attempt in {1..5}; do - log "attempt #${attempt} - ${FUNCNAME[2]}" - ${cmd_retry[@]} & - - wait $! && break - if [[ ${attempt} -lt 5 ]]; then - sleep "$wait_time" - else - abort "attempt #${attempt} - Failed to update packages" - fi - done -} - -# dnf_update_pkgs -dnf_update_pkgs() { - local -n excludes="$1" - log "starting" - - local -ra cmd=( - dnf - -y - ${excludes[@]} - update - --allowerasing - ) - - log "Updating all packages" - retry cmd "$2" -} - -# dnf_install_pkgs -dnf_install_pkgs() { - local -n pkgs="$1" - log "starting" - - local -ra cmd=( - dnf - -y - install - ${pkgs[@]} - ) - - log "Attempting to install packages: ${pkgs[*]}" - retry cmd "$2" -} - -# configure_logrotate clobbers /etc/logrotate.conf -configure_logrotate() { - log "starting" - - local -r logrotate_conf_filename='/etc/logrotate.conf' - local -r logrotate_conf_file='# see "man logrotate" for details -# rotate log files weekly -weekly - -# keep 2 weeks worth of backlogs -rotate 2 - -# create new (empty) log files after rotating old ones -create - -# use date as a suffix of the rotated file -dateext - -# uncomment this if you want your log files compressed -compress - -# RPM packages drop log rotation information into this directory -include /etc/logrotate.d - -# no packages own wtmp and btmp -- we will rotate them here -/var/log/wtmp { - monthly - create 0664 root utmp - minsize 1M - rotate 1 -} - -/var/log/btmp { - missingok - monthly - create 0600 root utmp - rotate 1 -}' - - write_file logrotate_conf_filename logrotate_conf_file true -} - -# configure_firewalld_rules -configure_firewalld_rules() { - log "starting" - - # https://access.redhat.com/security/cve/cve-2020-13401 - local -r prefix="/etc/sysctl.d" - local -r disable_accept_ra_conf_filename="$prefix/02-disable-accept-ra.conf" - local -r disable_accept_ra_conf_file="net.ipv6.conf.all.accept_ra=0" - - write_file disable_accept_ra_conf_filename disable_accept_ra_conf_file true - - local -r disable_core_filename="$prefix/01-disable-core.conf" - local -r disable_core_file="kernel.core_pattern = |/bin/true - " - write_file disable_core_filename disable_core_file true - - sysctl --system - - local -ra enable_ports=( - "443/tcp" - ) - - log "Enabling ports ${enable_ports[*]} on default firewalld zone" - # shellcheck disable=SC2068 - for port in ${enable_ports[@]}; do - log "Enabling port $port now" - firewall-cmd "--add-port=$port" - done - - firewall-cmd --runtime-to-permanent -} - -# pull_container_images -pull_container_images() { - log "starting" - - # The managed identity that the VM runs as only has a single roleassignment. - # This role assignment is ACRPull which is not necessarily present in the - # subscription we're deploying into. If the identity does not have any - # role assignments scoped on the subscription we're deploying into, it will - # not show on az login -i, which is why the below line is commented. - # az account set -s "$SUBSCRIPTIONID" - az login -i --allow-no-subscriptions - - # Suppress emulation output for podman instead of docker for az acr compatability - mkdir -p /etc/containers/ - mkdir -p /root/.docker - touch /etc/containers/nodocker - - # This name is used in the case that az acr login searches for this in it's environment - local -r REGISTRY_AUTH_FILE="/root/.docker/config.json" - local -r registry_config_file="{ - "auths": { - \"${PROXYIMAGE%%/*}\": { - \"auth\": \"$PROXYIMAGEAUTH\" - } - }" - - write_file REGISTRY_AUTH_FILE registry_config_file true - - log "logging into prod acr" - - az acr login --name "$(sed -e 's|.*/||' <<<"$ACRRESOURCEID")" - - docker pull "$PROXYIMAGE" - - az logout -} - # configure_system_services creates, configures, and enables the following systemd services and timers # services # proxy -configure_system_services() { +configure_devproxy_services() { configure_service_proxy } @@ -296,9 +131,6 @@ configure_system_services() { enable_aro_services() { log "starting" - local -ra aro_services=( - proxy - ) log "enabling aro services ${aro_services[*]}" # shellcheck disable=SC2068 for service in ${aro_services[@]}; do @@ -357,48 +189,6 @@ systemctl restart proxy.service" chmod +x "$cron_daily_restart_proxy_filename" } -# write_file -# Args -# 1) filename - string -# 2) file_contents - string -# 3) clobber - boolean; optional - defaults to false -write_file() { - local -n filename="$1" - local -n file_contents="$2" - local -r clobber="${3:-false}" - - if $clobber; then - log "Overwriting file $filename" - echo "$file_contents" > "$filename" - else - log "Appending to $filename" - echo "$file_contents" >> "$filename" - fi -} - -# reboot_vm restores all selinux file contexts, waits 30 seconds then reboots -reboot_vm() { - log "starting" - - configure_selinux "true" - (sleep 30 && log "rebooting vm now"; reboot) & -} - -# log is a wrapper for echo that includes the function name -log() { - local -r msg="${1:-"log message is empty"}" - local -r stack_level="${2:-1}" - echo "${FUNCNAME[${stack_level}]}: ${msg}" -} - -# abort is a wrapper for log that exits with an error code -abort() { - local -ri origin_stacklevel=2 - log "${1}" "$origin_stacklevel" - log "Exiting" - exit 1 -} - export AZURE_CLOUD_NAME="${AZURECLOUDNAME:?"Failed to carry over variables"}" main "$@" diff --git a/pkg/deploy/generator/scripts/rpVMSS.sh b/pkg/deploy/generator/scripts/rpVMSS.sh index e8cedfd1e25..decdfba6986 100644 --- a/pkg/deploy/generator/scripts/rpVMSS.sh +++ b/pkg/deploy/generator/scripts/rpVMSS.sh @@ -89,6 +89,7 @@ main() { dnf_install_pkgs repo_rpm_pkgs retry_wait_time dnf_install_pkgs install_pkgs retry_wait_time + configure_dnf_cron_job configure_disk_partitions configure_logrotate @@ -114,10 +115,10 @@ usage() { -d Configure Disk Partitions -p Configure rpm repositories, import required rpm keys, update & install packages with dnf -l Configure logrotate.conf - -s Make selinux modifications required for ARO RP + -s Configure selinux -r Configure sshd - Allow password authenticaiton -f Configure firewalld default zone rules - -u Configure systemd unit files for ARO RP + -u Configure systemd unit files -i Pull container images Note: steps will be executed in the order that flags are provided @@ -165,6 +166,9 @@ parse_run_options() { log "Running step dnf_install_pkgs pkgs" dnf_install_pkgs pkgs_to_install retry_time + + log "Running step configure_dnf_crond_job" + configure_dnf_cron_job ;; l) log "Running configure_logrotate" @@ -209,22 +213,6 @@ configure_rpm_repos() { create_azure_rpm_repos "$1" } -# configure_rhui_repo -configure_rhui_repo() { - log "starting" - - local -ra cmd=( - dnf - update - -y - --disablerepo='*' - --enablerepo='rhui-microsoft-azure*' - ) - - log "running RHUI package updates" - retry cmd "$1" -} - # configure_disk_partitions configure_disk_partitions() { log "starting" From 28b42a0848679165f547f73afa2bb457ce969192 Mon Sep 17 00:00:00 2001 From: Steven Fairchild Date: Thu, 18 Apr 2024 09:42:54 -0400 Subject: [PATCH 26/38] Correct parse_run_options by passing in user options as a nameref var --- pkg/deploy/generator/scripts/devProxyVMSS.sh | 14 ++++++++++---- pkg/deploy/generator/scripts/rpVMSS.sh | 5 +++-- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/pkg/deploy/generator/scripts/devProxyVMSS.sh b/pkg/deploy/generator/scripts/devProxyVMSS.sh index 19289b8ee1a..2c35fa6ee88 100644 --- a/pkg/deploy/generator/scripts/devProxyVMSS.sh +++ b/pkg/deploy/generator/scripts/devProxyVMSS.sh @@ -18,10 +18,10 @@ main() { "443/tcp" ) - local proxy_image="$PROXYIMAGE" + local -ra proxy_images=("$PROXYIMAGE") local -r registry_config_file="{ \"auths\": { - \"${PROXYIMAGE%%/*}\": { + \"${proxy_images[0]%%/*}\": { \"auth\": \"$PROXYIMAGEAUTH\" } }" @@ -40,7 +40,13 @@ main() { proxy ) - parse_run_options "$@" + local -ra user_options=("$@") + parse_run_options user_options \ + exclude_pkgs \ + install_pkgs \ + enable_ports \ + proxy_services \ + proxy_images dnf_update_pkgs pkgs_to_exclude retry_wait_time dnf_install_pkgs install_pkgs retry_wait_time @@ -71,7 +77,7 @@ usage() { # This is useful for local testing, or possibly modifying the bootstrap execution via environment variables in the deployment pipeline parse_run_options() { # shellcheck disable=SC2206 - local -a options=(${1:-}) + local -n run_options="$1" local -n pkgs_to_exclude="$2" local -n pkgs_to_install="$3" local -n ports_to_enable="$4" diff --git a/pkg/deploy/generator/scripts/rpVMSS.sh b/pkg/deploy/generator/scripts/rpVMSS.sh index decdfba6986..b954a29fd19 100644 --- a/pkg/deploy/generator/scripts/rpVMSS.sh +++ b/pkg/deploy/generator/scripts/rpVMSS.sh @@ -70,7 +70,8 @@ main() { "fluentbit" ) - parse_run_options "$@" \ + local -ra user_options=("$@") + parse_run_options user_options \ retry_wait_time \ exclude_pkgs \ rpm_keys \ @@ -131,7 +132,7 @@ usage() { # This is useful for local testing, or possibly modifying the bootstrap execution via environment variables in the deployment pipeline parse_run_options() { # shellcheck disable=SC2206 - local -a options=(${1:-}) + local -n run_options="$1" local -n retry_time="$2" local -n pkgs_to_exclude="$3" local -n keys_to_import="$4" From 9160d504d8b620f3de54fcbaae41403e088d45b2 Mon Sep 17 00:00:00 2001 From: Steven Fairchild Date: Thu, 18 Apr 2024 09:57:58 -0400 Subject: [PATCH 27/38] Correct options in parse_run_options to avoid curcuilar nameref, pass PROXY_IMAGE to configure_service_proxy function --- pkg/deploy/generator/scripts/devProxyVMSS.sh | 18 ++++++++++-------- pkg/deploy/generator/scripts/rpVMSS.sh | 4 ++-- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/pkg/deploy/generator/scripts/devProxyVMSS.sh b/pkg/deploy/generator/scripts/devProxyVMSS.sh index 2c35fa6ee88..f7816f47294 100644 --- a/pkg/deploy/generator/scripts/devProxyVMSS.sh +++ b/pkg/deploy/generator/scripts/devProxyVMSS.sh @@ -54,7 +54,7 @@ main() { configure_firewalld_rules enable_ports pull_container_images proxy_image registry_config_file - configure_devproxy_services + configure_devproxy_services proxy_images enable_services proxy_services reboot_vm } @@ -84,7 +84,7 @@ parse_run_options() { local -n services_to_enable="$5" local -n images_to_pull="$6" - if [ "${#options[@]}" -eq 0 ]; then + if [ "${#run_options[@]}" -eq 0 ]; then log "Running all steps" return 0 fi @@ -92,7 +92,7 @@ parse_run_options() { local OPTIND local -r allowed_options="pfui" while getopts ${allowed_options} options; do - case "${options}" in + case "${run_options}" in p) log "Running step dnf_update_pkgs" dnf_update_pkgs pkgs_to_exclude retry_wait_time @@ -109,7 +109,7 @@ parse_run_options() { ;; u) log "Running step configure_devproxy_services" - configure_devproxy_services + configure_devproxy_services proxy_images enable_services services_to_enable ;; i) @@ -130,7 +130,7 @@ parse_run_options() { # services # proxy configure_devproxy_services() { - configure_service_proxy + configure_service_proxy "$1" } # enable_aro_services enables all services required for aro rp @@ -158,7 +158,7 @@ configure_certs() { configure_service_proxy() { local -r sysconfig_proxy_filename='/etc/sysconfig/proxy' - local -r sysconfig_proxy_file="PROXY_IMAGE='$PROXYIMAGE'" + local -r sysconfig_proxy_file="PROXY_IMAGE='$1'" write_file sysconfig_proxy_filename sysconfig_proxy_file true @@ -170,7 +170,7 @@ Wants=network-online.target [Service] EnvironmentFile=/etc/sysconfig/proxy ExecStartPre=-/usr/bin/docker rm -f %n -ExecStart=/usr/bin/docker run --rm --name %n -p 443:8443 -v /etc/proxy:/secrets $PROXY_IMAGE +ExecStart=/usr/bin/docker run --rm --name %n -p 443:8443 -v /etc/proxy:/secrets $1 ExecStop=/usr/bin/docker stop %n Restart=always RestartSec=1 @@ -179,9 +179,11 @@ StartLimitInterval=0 [Install] WantedBy=multi-user.target" + write_file proxy_service_filename proxy_service_file true + local -r cron_weekly_pull_image_filename='/etc/cron.weekly/pull-image' local -r cron_weekly_pull_image_file="#!/bin/bash -docker pull $PROXYIMAGE +docker pull $1 systemctl restart proxy.service" write_file cron_weekly_pull_image_filename cron_weekly_pull_image_file true diff --git a/pkg/deploy/generator/scripts/rpVMSS.sh b/pkg/deploy/generator/scripts/rpVMSS.sh index b954a29fd19..906bdfd1cde 100644 --- a/pkg/deploy/generator/scripts/rpVMSS.sh +++ b/pkg/deploy/generator/scripts/rpVMSS.sh @@ -142,7 +142,7 @@ parse_run_options() { local -n ports_to_enable="$8" local -n services_to_enable="$9" - if [ "${#options[@]}" -eq 0 ]; then + if [ "${#run_options[@]}" -eq 0 ]; then log "Running all steps" return 0 fi @@ -150,7 +150,7 @@ parse_run_options() { local OPTIND local -r allowed_options="dplsrfui" while getopts ${allowed_options} options; do - case "${options}" in + case "${run_options}" in d) log "Running step configure_disk_partitions" configure_disk_partitions From 347450e009386ff9a7d00a54b0f6df37b9171e16 Mon Sep 17 00:00:00 2001 From: Steven Fairchild Date: Thu, 18 Apr 2024 11:52:39 -0400 Subject: [PATCH 28/38] Remove unused function, correct nameref usage in configure_service_proxy --- pkg/deploy/assets/env-development.json | 2 +- pkg/deploy/assets/rp-production.json | 2 +- pkg/deploy/generator/scripts/devProxyVMSS.sh | 19 ++++--------------- 3 files changed, 6 insertions(+), 17 deletions(-) diff --git a/pkg/deploy/assets/env-development.json b/pkg/deploy/assets/env-development.json index af038e859b5..dc0106ae8b3 100644 --- a/pkg/deploy/assets/env-development.json +++ b/pkg/deploy/assets/env-development.json @@ -296,7 +296,7 @@ "autoUpgradeMinorVersion": true, "settings": {}, "protectedSettings": { - "script": "[base64(concat(base64ToString('c2V0IC1leAoK'),'PROXYIMAGE=$(base64 -d \u003c\u003c\u003c''',base64(parameters('proxyImage')),''')\n','PROXYIMAGEAUTH=$(base64 -d \u003c\u003c\u003c''',base64(parameters('proxyImageAuth')),''')\n','PROXYCERT=''',parameters('proxyCert'),'''\n','PROXYCLIENTCERT=''',parameters('proxyClientCert'),'''\n','PROXYKEY=''',parameters('proxyKey'),'''\n','\n',base64ToString('IyEvYmluL2Jhc2gKCnNldCAtbyBlcnJleGl0IFwKICAgIC1vIG5vdW5zZXQKCmlmIFsgIiR7REVCVUc6LWZhbHNlfSIgPT0gdHJ1ZSBdOyB0aGVuCiAgICBzZXQgLXgKZmkKCm1haW4oKSB7CiAgICAjIHRyYW5zYWN0aW9uIGF0dGVtcHQgcmV0cnkgdGltZSBpbiBzZWNvbmRzCiAgICBsb2NhbCAtcmkgcmV0cnlfd2FpdF90aW1lPTYwCgogICAgIyBzaGVsbGNoZWNrIHNvdXJjZT1jb21tb24uc2gKICAgIHNvdXJjZSBjb21tb24uc2gKCiAgICBsb2NhbCAtcmEgZW5hYmxlX3BvcnRzPSgKICAgICAgICAiNDQzL3RjcCIKICAgICkKCiAgICBsb2NhbCBwcm94eV9pbWFnZT0iJFBST1hZSU1BR0UiCglsb2NhbCAtciByZWdpc3RyeV9jb25maWdfZmlsZT0iewogICAgXCJhdXRoc1wiOiB7CiAgICAgICAgXCIke1BST1hZSU1BR0UlJS8qfVwiOiB7CiAgICAgICAgICAgIFwiYXV0aFwiOiBcIiRQUk9YWUlNQUdFQVVUSFwiCiAgICAgICAgfQogICAgfSIKCiAgICBsb2NhbCAtYXIgZXhjbHVkZV9wa2dzPSgKICAgICAgICAiLXggV0FMaW51eEFnZW50IgogICAgICAgICIteCBXQUxpbnV4QWdlbnQtdWRldiIKICAgICkKCiAgICBsb2NhbCAtcmEgaW5zdGFsbF9wa2dzPSgKICAgICAgICBwb2RtYW4KICAgICAgICBwb2RtYW4tZG9ja2VyCiAgICApCgogICAgbG9jYWwgLXJhIHByb3h5X3NlcnZpY2VzPSgKCQlwcm94eQogICAgKQoKICAgIHBhcnNlX3J1bl9vcHRpb25zICIkQCIKCiAgICBkbmZfdXBkYXRlX3BrZ3MgcGtnc190b19leGNsdWRlIHJldHJ5X3dhaXRfdGltZQogICAgZG5mX2luc3RhbGxfcGtncyBpbnN0YWxsX3BrZ3MgcmV0cnlfd2FpdF90aW1lCiAgICBjb25maWd1cmVfZG5mX2Nyb25fam9iCgogICAgY29uZmlndXJlX2ZpcmV3YWxsZF9ydWxlcyBlbmFibGVfcG9ydHMKICAgIHB1bGxfY29udGFpbmVyX2ltYWdlcyBwcm94eV9pbWFnZSByZWdpc3RyeV9jb25maWdfZmlsZQogICAgY29uZmlndXJlX2RldnByb3h5X3NlcnZpY2VzCiAgICBlbmFibGVfc2VydmljZXMgcHJveHlfc2VydmljZXMKICAgIHJlYm9vdF92bQp9Cgp1c2FnZSgpIHsKICAgIGxvY2FsIC1uIG9wdGlvbnM9IiQxIgogICAgbG9nICIkKGJhc2VuYW1lICIkMCIpIFskb3B0aW9uc10KICAgICAgICAtcCBDb25maWd1cmUgcnBtIHJlcG9zaXRvcmllcywgaW1wb3J0IHJlcXVpcmVkIHJwbSBrZXlzLCB1cGRhdGUgJiBpbnN0YWxsIHBhY2thZ2VzIHdpdGggZG5mCiAgICAgICAgLWYgQ29uZmlndXJlIGZpcmV3YWxsZCBkZWZhdWx0IHpvbmUgcnVsZXMKICAgICAgICAtdSBDb25maWd1cmUgc3lzdGVtZCB1bml0IGZpbGVzCiAgICAgICAgLWkgUHVsbCBjb250YWluZXIgaW1hZ2VzCgogICAgICAgIE5vdGU6IHN0ZXBzIHdpbGwgYmUgZXhlY3V0ZWQgaW4gdGhlIG9yZGVyIHRoYXQgZmxhZ3MgYXJlIHByb3ZpZGVkCiAgICAiCn0KCiMgcGFyc2VfcnVuX29wdGlvbnMgdGFrZXMgYWxsIGFyZ3VlbWVudHMgcGFzc2VkIHRvIG1haW4gYW5kIHBhcnNlcyB0aGVtCiMgYWxsb3dpbmcgaW5kaXZpZHVhbCBzdGVwKHMpIHRvIGJlIHJhbiwgcmF0aGVyIHRoYW4gYWxsIHN0ZXBzCiMKIyBUaGlzIGlzIHVzZWZ1bCBmb3IgbG9jYWwgdGVzdGluZywgb3IgcG9zc2libHkgbW9kaWZ5aW5nIHRoZSBib290c3RyYXAgZXhlY3V0aW9uIHZpYSBlbnZpcm9ubWVudCB2YXJpYWJsZXMgaW4gdGhlIGRlcGxveW1lbnQgcGlwZWxpbmUKcGFyc2VfcnVuX29wdGlvbnMoKSB7CiAgICAjIHNoZWxsY2hlY2sgZGlzYWJsZT1TQzIyMDYKICAgIGxvY2FsIC1hIG9wdGlvbnM9KCR7MTotfSkKICAgIGxvY2FsIC1uIHBrZ3NfdG9fZXhjbHVkZT0iJDIiCiAgICBsb2NhbCAtbiBwa2dzX3RvX2luc3RhbGw9IiQzIgogICAgbG9jYWwgLW4gcG9ydHNfdG9fZW5hYmxlPSIkNCIKICAgIGxvY2FsIC1uIHNlcnZpY2VzX3RvX2VuYWJsZT0iJDUiCiAgICBsb2NhbCAtbiBpbWFnZXNfdG9fcHVsbD0iJDYiCgogICAgaWYgWyAiJHsjb3B0aW9uc1tAXX0iIC1lcSAwIF07IHRoZW4KICAgICAgICBsb2cgIlJ1bm5pbmcgYWxsIHN0ZXBzIgogICAgICAgIHJldHVybiAwCiAgICBmaQoKICAgIGxvY2FsIE9QVElORAoJbG9jYWwgLXIgYWxsb3dlZF9vcHRpb25zPSJwZnVpIgogICAgd2hpbGUgZ2V0b3B0cyAke2FsbG93ZWRfb3B0aW9uc30gb3B0aW9uczsgZG8KICAgICAgICBjYXNlICIke29wdGlvbnN9IiBpbgogICAgICAgICAgICBwKQogICAgICAgICAgICAgICAgbG9nICJSdW5uaW5nIHN0ZXAgZG5mX3VwZGF0ZV9wa2dzIgogICAgICAgICAgICAgICAgZG5mX3VwZGF0ZV9wa2dzIHBrZ3NfdG9fZXhjbHVkZSByZXRyeV93YWl0X3RpbWUKCiAgICAgICAgICAgICAgICBsb2cgIlJ1bm5pbmcgc3RlcCBkbmZfaW5zdGFsbF9wa2dzIgogICAgICAgICAgICAgICAgZG5mX2luc3RhbGxfcGtncyBwa2dzX3RvX2luc3RhbGwgcmV0cnlfd2FpdF90aW1lCgogICAgICAgICAgICAgICAgbG9nICJSdW5uaW5nIHN0ZXAgY29uZmlndXJlX2RuZl9jcm9uX2pvYiIKICAgICAgICAgICAgICAgIGNvbmZpZ3VyZV9kbmZfY3Jvbl9qb2IKICAgICAgICAgICAgICAgIDs7CiAgICAgICAgICAgIGYpCiAgICAgICAgICAgICAgICBsb2cgIlJ1bm5pbmcgY29uZmlndXJlX2ZpcmV3YWxsZF9ydWxlcyIKICAgICAgICAgICAgICAgIGNvbmZpZ3VyZV9maXJld2FsbGRfcnVsZXMgcG9ydHNfdG9fZW5hYmxlCiAgICAgICAgICAgICAgICA7OwogICAgICAgICAgICB1KQogICAgICAgICAgICAgICAgbG9nICJSdW5uaW5nIHN0ZXAgY29uZmlndXJlX2RldnByb3h5X3NlcnZpY2VzIgogICAgICAgICAgICAgICAgY29uZmlndXJlX2RldnByb3h5X3NlcnZpY2VzCiAgICAgICAgICAgICAgICBlbmFibGVfc2VydmljZXMgc2VydmljZXNfdG9fZW5hYmxlCiAgICAgICAgICAgICAgICA7OwogICAgICAgICAgICBpKQogICAgICAgICAgICAgICAgbG9nICJSdW5uaW5nIHB1bGxfY29udGFpbmVyX2ltYWdlcyIKICAgICAgICAgICAgICAgIHB1bGxfY29udGFpbmVyX2ltYWdlcyBpbWFnZXNfdG9fcHVsbAogICAgICAgICAgICAgICAgOzsKICAgICAgICAgICAgKikKICAgICAgICAgICAgICAgIHVzYWdlIGFsbG93ZWRfb3B0aW9ucwogICAgICAgICAgICAgICAgYWJvcnQgIlVua293biBvcHRpb24gcHJvdmlkZWQiCiAgICAgICAgICAgICAgICA7OwogICAgICAgIGVzYWMKICAgIGRvbmUKICAgIAogICAgZXhpdCAwCn0KCiMgY29uZmlndXJlX3N5c3RlbV9zZXJ2aWNlcyBjcmVhdGVzLCBjb25maWd1cmVzLCBhbmQgZW5hYmxlcyB0aGUgZm9sbG93aW5nIHN5c3RlbWQgc2VydmljZXMgYW5kIHRpbWVycwojIHNlcnZpY2VzCiMJcHJveHkKY29uZmlndXJlX2RldnByb3h5X3NlcnZpY2VzKCkgewoJY29uZmlndXJlX3NlcnZpY2VfcHJveHkKfQoKIyBlbmFibGVfYXJvX3NlcnZpY2VzIGVuYWJsZXMgYWxsIHNlcnZpY2VzIHJlcXVpcmVkIGZvciBhcm8gcnAKZW5hYmxlX2Fyb19zZXJ2aWNlcygpIHsKICAgIGxvZyAic3RhcnRpbmciCgogICAgbG9nICJlbmFibGluZyBhcm8gc2VydmljZXMgJHthcm9fc2VydmljZXNbKl19IgogICAgIyBzaGVsbGNoZWNrIGRpc2FibGU9U0MyMDY4CiAgICBmb3Igc2VydmljZSBpbiAke2Fyb19zZXJ2aWNlc1tAXX07IGRvCiAgICAgICAgbG9nICJFbmFibGluZyAkc2VydmljZSBub3ciCiAgICAgICAgc3lzdGVtY3RsIGVuYWJsZSAiJHNlcnZpY2Uuc2VydmljZSIKICAgIGRvbmUKfQoKIyBjb25maWd1cmVfY2VydHMKY29uZmlndXJlX2NlcnRzKCkgewogICAgbG9nICJzdGFydGluZyIKCgliYXNlNjQgLWQgPDw8IiRQUk9YWUNFUlQiID4vZXRjL3Byb3h5L3Byb3h5LmNydAoJYmFzZTY0IC1kIDw8PCIkUFJPWFlLRVkiID4vZXRjL3Byb3h5L3Byb3h5LmtleQoJYmFzZTY0IC1kIDw8PCIkUFJPWFlDTElFTlRDRVJUIiA+L2V0Yy9wcm94eS9wcm94eS1jbGllbnQuY3J0CgljaG93biAtUiAxMDAwOjEwMDAgL2V0Yy9wcm94eQoJY2htb2QgMDYwMCAvZXRjL3Byb3h5L3Byb3h5LmtleQp9Cgpjb25maWd1cmVfc2VydmljZV9wcm94eSgpIHsKCWxvY2FsIC1yIHN5c2NvbmZpZ19wcm94eV9maWxlbmFtZT0nL2V0Yy9zeXNjb25maWcvcHJveHknCglsb2NhbCAtciBzeXNjb25maWdfcHJveHlfZmlsZT0iUFJPWFlfSU1BR0U9JyRQUk9YWUlNQUdFJyIKCgl3cml0ZV9maWxlIHN5c2NvbmZpZ19wcm94eV9maWxlbmFtZSBzeXNjb25maWdfcHJveHlfZmlsZSB0cnVlCgoJbG9jYWwgLXIgcHJveHlfc2VydmljZV9maWxlbmFtZT0nL2V0Yy9zeXN0ZW1kL3N5c3RlbS9wcm94eS5zZXJ2aWNlJwoJbG9jYWwgLXIgcHJveHlfc2VydmljZV9maWxlPSJbVW5pdF0KQWZ0ZXI9bmV0d29yay1vbmxpbmUudGFyZ2V0CldhbnRzPW5ldHdvcmstb25saW5lLnRhcmdldAoKW1NlcnZpY2VdCkVudmlyb25tZW50RmlsZT0vZXRjL3N5c2NvbmZpZy9wcm94eQpFeGVjU3RhcnRQcmU9LS91c3IvYmluL2RvY2tlciBybSAtZiAlbgpFeGVjU3RhcnQ9L3Vzci9iaW4vZG9ja2VyIHJ1biAtLXJtIC0tbmFtZSAlbiAtcCA0NDM6ODQ0MyAtdiAvZXRjL3Byb3h5Oi9zZWNyZXRzICRQUk9YWV9JTUFHRQpFeGVjU3RvcD0vdXNyL2Jpbi9kb2NrZXIgc3RvcCAlbgpSZXN0YXJ0PWFsd2F5cwpSZXN0YXJ0U2VjPTEKU3RhcnRMaW1pdEludGVydmFsPTAKCltJbnN0YWxsXQpXYW50ZWRCeT1tdWx0aS11c2VyLnRhcmdldCIKCglsb2NhbCAtciBjcm9uX3dlZWtseV9wdWxsX2ltYWdlX2ZpbGVuYW1lPScvZXRjL2Nyb24ud2Vla2x5L3B1bGwtaW1hZ2UnCglsb2NhbCAtciBjcm9uX3dlZWtseV9wdWxsX2ltYWdlX2ZpbGU9IiMhL2Jpbi9iYXNoCmRvY2tlciBwdWxsICRQUk9YWUlNQUdFCnN5c3RlbWN0bCByZXN0YXJ0IHByb3h5LnNlcnZpY2UiCgkKCXdyaXRlX2ZpbGUgY3Jvbl93ZWVrbHlfcHVsbF9pbWFnZV9maWxlbmFtZSBjcm9uX3dlZWtseV9wdWxsX2ltYWdlX2ZpbGUgdHJ1ZQoJY2htb2QgK3ggIiRjcm9uX3dlZWtseV9wdWxsX2ltYWdlX2ZpbGVuYW1lIgoKCWxvY2FsIC1yIGNyb25fZGFpbHlfcmVzdGFydF9wcm94eV9maWxlbmFtZT0nL2V0Yy9jcm9uLmRhaWx5L3Jlc3RhcnQtcHJveHknCglsb2NhbCAtciBjcm9uX2RhaWx5X3Jlc3RhcnRfcHJveHlfZmlsZT0iIyEvYmluL2Jhc2gKc3lzdGVtY3RsIHJlc3RhcnQgcHJveHkuc2VydmljZSIKCQoJd3JpdGVfZmlsZSBjcm9uX2RhaWx5X3Jlc3RhcnRfcHJveHlfZmlsZW5hbWUgY3Jvbl9kYWlseV9yZXN0YXJ0X3Byb3h5X2ZpbGUKCWNobW9kICt4ICIkY3Jvbl9kYWlseV9yZXN0YXJ0X3Byb3h5X2ZpbGVuYW1lIgp9CgpleHBvcnQgQVpVUkVfQ0xPVURfTkFNRT0iJHtBWlVSRUNMT1VETkFNRTo/IkZhaWxlZCB0byBjYXJyeSBvdmVyIHZhcmlhYmxlcyJ9IgoKbWFpbiAiJEAiCg==')))]" + "script": "[base64(concat(base64ToString('c2V0IC1leAoK'),'PROXYIMAGE=$(base64 -d \u003c\u003c\u003c''',base64(parameters('proxyImage')),''')\n','PROXYIMAGEAUTH=$(base64 -d \u003c\u003c\u003c''',base64(parameters('proxyImageAuth')),''')\n','PROXYCERT=''',parameters('proxyCert'),'''\n','PROXYCLIENTCERT=''',parameters('proxyClientCert'),'''\n','PROXYKEY=''',parameters('proxyKey'),'''\n','\n',base64ToString('IyEvYmluL2Jhc2gKCnNldCAtbyBlcnJleGl0IFwKICAgIC1vIG5vdW5zZXQKCmlmIFsgIiR7REVCVUc6LWZhbHNlfSIgPT0gdHJ1ZSBdOyB0aGVuCiAgICBzZXQgLXgKZmkKCm1haW4oKSB7CiAgICAjIHRyYW5zYWN0aW9uIGF0dGVtcHQgcmV0cnkgdGltZSBpbiBzZWNvbmRzCiAgICBsb2NhbCAtcmkgcmV0cnlfd2FpdF90aW1lPTYwCgogICAgIyBzaGVsbGNoZWNrIHNvdXJjZT1jb21tb24uc2gKICAgIHNvdXJjZSBjb21tb24uc2gKCiAgICBsb2NhbCAtcmEgZW5hYmxlX3BvcnRzPSgKICAgICAgICAiNDQzL3RjcCIKICAgICkKCiAgICBsb2NhbCAtcmEgcHJveHlfaW1hZ2VzPSgiJFBST1hZSU1BR0UiKQoJbG9jYWwgLXIgcmVnaXN0cnlfY29uZmlnX2ZpbGU9InsKICAgIFwiYXV0aHNcIjogewogICAgICAgIFwiJHtwcm94eV9pbWFnZXNbMF0lJS8qfVwiOiB7CiAgICAgICAgICAgIFwiYXV0aFwiOiBcIiRQUk9YWUlNQUdFQVVUSFwiCiAgICAgICAgfQogICAgfSIKCiAgICBsb2NhbCAtYXIgZXhjbHVkZV9wa2dzPSgKICAgICAgICAiLXggV0FMaW51eEFnZW50IgogICAgICAgICIteCBXQUxpbnV4QWdlbnQtdWRldiIKICAgICkKCiAgICBsb2NhbCAtcmEgaW5zdGFsbF9wa2dzPSgKICAgICAgICBwb2RtYW4KICAgICAgICBwb2RtYW4tZG9ja2VyCiAgICApCgogICAgbG9jYWwgLXJhIHByb3h5X3NlcnZpY2VzPSgKCQlwcm94eQogICAgKQoKICAgIGxvY2FsIC1yYSB1c2VyX29wdGlvbnM9KCIkQCIpCiAgICBwYXJzZV9ydW5fb3B0aW9ucyB1c2VyX29wdGlvbnMgXAogICAgICAgICAgICAgICAgICAgICAgICBleGNsdWRlX3BrZ3MgXAogICAgICAgICAgICAgICAgICAgICAgICBpbnN0YWxsX3BrZ3MgXAogICAgICAgICAgICAgICAgICAgICAgICBlbmFibGVfcG9ydHMgXAogICAgICAgICAgICAgICAgICAgICAgICBwcm94eV9zZXJ2aWNlcyBcCiAgICAgICAgICAgICAgICAgICAgICAgIHByb3h5X2ltYWdlcwoKICAgIGRuZl91cGRhdGVfcGtncyBwa2dzX3RvX2V4Y2x1ZGUgcmV0cnlfd2FpdF90aW1lCiAgICBkbmZfaW5zdGFsbF9wa2dzIGluc3RhbGxfcGtncyByZXRyeV93YWl0X3RpbWUKICAgIGNvbmZpZ3VyZV9kbmZfY3Jvbl9qb2IKCiAgICBjb25maWd1cmVfZmlyZXdhbGxkX3J1bGVzIGVuYWJsZV9wb3J0cwogICAgcHVsbF9jb250YWluZXJfaW1hZ2VzIHByb3h5X2ltYWdlIHJlZ2lzdHJ5X2NvbmZpZ19maWxlCiAgICBjb25maWd1cmVfZGV2cHJveHlfc2VydmljZXMgcHJveHlfaW1hZ2VzCiAgICBlbmFibGVfc2VydmljZXMgcHJveHlfc2VydmljZXMKICAgIHJlYm9vdF92bQp9Cgp1c2FnZSgpIHsKICAgIGxvY2FsIC1uIG9wdGlvbnM9IiQxIgogICAgbG9nICIkKGJhc2VuYW1lICIkMCIpIFskb3B0aW9uc10KICAgICAgICAtcCBDb25maWd1cmUgcnBtIHJlcG9zaXRvcmllcywgaW1wb3J0IHJlcXVpcmVkIHJwbSBrZXlzLCB1cGRhdGUgJiBpbnN0YWxsIHBhY2thZ2VzIHdpdGggZG5mCiAgICAgICAgLWYgQ29uZmlndXJlIGZpcmV3YWxsZCBkZWZhdWx0IHpvbmUgcnVsZXMKICAgICAgICAtdSBDb25maWd1cmUgc3lzdGVtZCB1bml0IGZpbGVzCiAgICAgICAgLWkgUHVsbCBjb250YWluZXIgaW1hZ2VzCgogICAgICAgIE5vdGU6IHN0ZXBzIHdpbGwgYmUgZXhlY3V0ZWQgaW4gdGhlIG9yZGVyIHRoYXQgZmxhZ3MgYXJlIHByb3ZpZGVkCiAgICAiCn0KCiMgcGFyc2VfcnVuX29wdGlvbnMgdGFrZXMgYWxsIGFyZ3VlbWVudHMgcGFzc2VkIHRvIG1haW4gYW5kIHBhcnNlcyB0aGVtCiMgYWxsb3dpbmcgaW5kaXZpZHVhbCBzdGVwKHMpIHRvIGJlIHJhbiwgcmF0aGVyIHRoYW4gYWxsIHN0ZXBzCiMKIyBUaGlzIGlzIHVzZWZ1bCBmb3IgbG9jYWwgdGVzdGluZywgb3IgcG9zc2libHkgbW9kaWZ5aW5nIHRoZSBib290c3RyYXAgZXhlY3V0aW9uIHZpYSBlbnZpcm9ubWVudCB2YXJpYWJsZXMgaW4gdGhlIGRlcGxveW1lbnQgcGlwZWxpbmUKcGFyc2VfcnVuX29wdGlvbnMoKSB7CiAgICAjIHNoZWxsY2hlY2sgZGlzYWJsZT1TQzIyMDYKICAgIGxvY2FsIC1uIHJ1bl9vcHRpb25zPSIkMSIKICAgIGxvY2FsIC1uIHBrZ3NfdG9fZXhjbHVkZT0iJDIiCiAgICBsb2NhbCAtbiBwa2dzX3RvX2luc3RhbGw9IiQzIgogICAgbG9jYWwgLW4gcG9ydHNfdG9fZW5hYmxlPSIkNCIKICAgIGxvY2FsIC1uIHNlcnZpY2VzX3RvX2VuYWJsZT0iJDUiCiAgICBsb2NhbCAtbiBpbWFnZXNfdG9fcHVsbD0iJDYiCgogICAgaWYgWyAiJHsjcnVuX29wdGlvbnNbQF19IiAtZXEgMCBdOyB0aGVuCiAgICAgICAgbG9nICJSdW5uaW5nIGFsbCBzdGVwcyIKICAgICAgICByZXR1cm4gMAogICAgZmkKCiAgICBsb2NhbCBPUFRJTkQKCWxvY2FsIC1yIGFsbG93ZWRfb3B0aW9ucz0icGZ1aSIKICAgIHdoaWxlIGdldG9wdHMgJHthbGxvd2VkX29wdGlvbnN9IG9wdGlvbnM7IGRvCiAgICAgICAgY2FzZSAiJHtydW5fb3B0aW9uc30iIGluCiAgICAgICAgICAgIHApCiAgICAgICAgICAgICAgICBsb2cgIlJ1bm5pbmcgc3RlcCBkbmZfdXBkYXRlX3BrZ3MiCiAgICAgICAgICAgICAgICBkbmZfdXBkYXRlX3BrZ3MgcGtnc190b19leGNsdWRlIHJldHJ5X3dhaXRfdGltZQoKICAgICAgICAgICAgICAgIGxvZyAiUnVubmluZyBzdGVwIGRuZl9pbnN0YWxsX3BrZ3MiCiAgICAgICAgICAgICAgICBkbmZfaW5zdGFsbF9wa2dzIHBrZ3NfdG9faW5zdGFsbCByZXRyeV93YWl0X3RpbWUKCiAgICAgICAgICAgICAgICBsb2cgIlJ1bm5pbmcgc3RlcCBjb25maWd1cmVfZG5mX2Nyb25fam9iIgogICAgICAgICAgICAgICAgY29uZmlndXJlX2RuZl9jcm9uX2pvYgogICAgICAgICAgICAgICAgOzsKICAgICAgICAgICAgZikKICAgICAgICAgICAgICAgIGxvZyAiUnVubmluZyBjb25maWd1cmVfZmlyZXdhbGxkX3J1bGVzIgogICAgICAgICAgICAgICAgY29uZmlndXJlX2ZpcmV3YWxsZF9ydWxlcyBwb3J0c190b19lbmFibGUKICAgICAgICAgICAgICAgIDs7CiAgICAgICAgICAgIHUpCiAgICAgICAgICAgICAgICBsb2cgIlJ1bm5pbmcgc3RlcCBjb25maWd1cmVfZGV2cHJveHlfc2VydmljZXMiCiAgICAgICAgICAgICAgICBjb25maWd1cmVfZGV2cHJveHlfc2VydmljZXMgcHJveHlfaW1hZ2VzCiAgICAgICAgICAgICAgICBlbmFibGVfc2VydmljZXMgc2VydmljZXNfdG9fZW5hYmxlCiAgICAgICAgICAgICAgICA7OwogICAgICAgICAgICBpKQogICAgICAgICAgICAgICAgbG9nICJSdW5uaW5nIHB1bGxfY29udGFpbmVyX2ltYWdlcyIKICAgICAgICAgICAgICAgIHB1bGxfY29udGFpbmVyX2ltYWdlcyBpbWFnZXNfdG9fcHVsbAogICAgICAgICAgICAgICAgOzsKICAgICAgICAgICAgKikKICAgICAgICAgICAgICAgIHVzYWdlIGFsbG93ZWRfb3B0aW9ucwogICAgICAgICAgICAgICAgYWJvcnQgIlVua293biBvcHRpb24gcHJvdmlkZWQiCiAgICAgICAgICAgICAgICA7OwogICAgICAgIGVzYWMKICAgIGRvbmUKICAgIAogICAgZXhpdCAwCn0KCiMgY29uZmlndXJlX3N5c3RlbV9zZXJ2aWNlcyBjcmVhdGVzLCBjb25maWd1cmVzLCBhbmQgZW5hYmxlcyB0aGUgZm9sbG93aW5nIHN5c3RlbWQgc2VydmljZXMgYW5kIHRpbWVycwojIHNlcnZpY2VzCiMJcHJveHkKY29uZmlndXJlX2RldnByb3h5X3NlcnZpY2VzKCkgewoJY29uZmlndXJlX3NlcnZpY2VfcHJveHkgIiQxIgp9CgojIGVuYWJsZV9hcm9fc2VydmljZXMgZW5hYmxlcyBhbGwgc2VydmljZXMgcmVxdWlyZWQgZm9yIGFybyBycAplbmFibGVfYXJvX3NlcnZpY2VzKCkgewogICAgbG9nICJzdGFydGluZyIKCiAgICBsb2cgImVuYWJsaW5nIGFybyBzZXJ2aWNlcyAke2Fyb19zZXJ2aWNlc1sqXX0iCiAgICAjIHNoZWxsY2hlY2sgZGlzYWJsZT1TQzIwNjgKICAgIGZvciBzZXJ2aWNlIGluICR7YXJvX3NlcnZpY2VzW0BdfTsgZG8KICAgICAgICBsb2cgIkVuYWJsaW5nICRzZXJ2aWNlIG5vdyIKICAgICAgICBzeXN0ZW1jdGwgZW5hYmxlICIkc2VydmljZS5zZXJ2aWNlIgogICAgZG9uZQp9CgojIGNvbmZpZ3VyZV9jZXJ0cwpjb25maWd1cmVfY2VydHMoKSB7CiAgICBsb2cgInN0YXJ0aW5nIgoKCWJhc2U2NCAtZCA8PDwiJFBST1hZQ0VSVCIgPi9ldGMvcHJveHkvcHJveHkuY3J0CgliYXNlNjQgLWQgPDw8IiRQUk9YWUtFWSIgPi9ldGMvcHJveHkvcHJveHkua2V5CgliYXNlNjQgLWQgPDw8IiRQUk9YWUNMSUVOVENFUlQiID4vZXRjL3Byb3h5L3Byb3h5LWNsaWVudC5jcnQKCWNob3duIC1SIDEwMDA6MTAwMCAvZXRjL3Byb3h5CgljaG1vZCAwNjAwIC9ldGMvcHJveHkvcHJveHkua2V5Cn0KCmNvbmZpZ3VyZV9zZXJ2aWNlX3Byb3h5KCkgewoJbG9jYWwgLXIgc3lzY29uZmlnX3Byb3h5X2ZpbGVuYW1lPScvZXRjL3N5c2NvbmZpZy9wcm94eScKCWxvY2FsIC1yIHN5c2NvbmZpZ19wcm94eV9maWxlPSJQUk9YWV9JTUFHRT0nJDEnIgoKCXdyaXRlX2ZpbGUgc3lzY29uZmlnX3Byb3h5X2ZpbGVuYW1lIHN5c2NvbmZpZ19wcm94eV9maWxlIHRydWUKCglsb2NhbCAtciBwcm94eV9zZXJ2aWNlX2ZpbGVuYW1lPScvZXRjL3N5c3RlbWQvc3lzdGVtL3Byb3h5LnNlcnZpY2UnCglsb2NhbCAtciBwcm94eV9zZXJ2aWNlX2ZpbGU9IltVbml0XQpBZnRlcj1uZXR3b3JrLW9ubGluZS50YXJnZXQKV2FudHM9bmV0d29yay1vbmxpbmUudGFyZ2V0CgpbU2VydmljZV0KRW52aXJvbm1lbnRGaWxlPS9ldGMvc3lzY29uZmlnL3Byb3h5CkV4ZWNTdGFydFByZT0tL3Vzci9iaW4vZG9ja2VyIHJtIC1mICVuCkV4ZWNTdGFydD0vdXNyL2Jpbi9kb2NrZXIgcnVuIC0tcm0gLS1uYW1lICVuIC1wIDQ0Mzo4NDQzIC12IC9ldGMvcHJveHk6L3NlY3JldHMgJDEKRXhlY1N0b3A9L3Vzci9iaW4vZG9ja2VyIHN0b3AgJW4KUmVzdGFydD1hbHdheXMKUmVzdGFydFNlYz0xClN0YXJ0TGltaXRJbnRlcnZhbD0wCgpbSW5zdGFsbF0KV2FudGVkQnk9bXVsdGktdXNlci50YXJnZXQiCgogICAgd3JpdGVfZmlsZSBwcm94eV9zZXJ2aWNlX2ZpbGVuYW1lIHByb3h5X3NlcnZpY2VfZmlsZSB0cnVlCgoJbG9jYWwgLXIgY3Jvbl93ZWVrbHlfcHVsbF9pbWFnZV9maWxlbmFtZT0nL2V0Yy9jcm9uLndlZWtseS9wdWxsLWltYWdlJwoJbG9jYWwgLXIgY3Jvbl93ZWVrbHlfcHVsbF9pbWFnZV9maWxlPSIjIS9iaW4vYmFzaApkb2NrZXIgcHVsbCAkMQpzeXN0ZW1jdGwgcmVzdGFydCBwcm94eS5zZXJ2aWNlIgoJCgl3cml0ZV9maWxlIGNyb25fd2Vla2x5X3B1bGxfaW1hZ2VfZmlsZW5hbWUgY3Jvbl93ZWVrbHlfcHVsbF9pbWFnZV9maWxlIHRydWUKCWNobW9kICt4ICIkY3Jvbl93ZWVrbHlfcHVsbF9pbWFnZV9maWxlbmFtZSIKCglsb2NhbCAtciBjcm9uX2RhaWx5X3Jlc3RhcnRfcHJveHlfZmlsZW5hbWU9Jy9ldGMvY3Jvbi5kYWlseS9yZXN0YXJ0LXByb3h5JwoJbG9jYWwgLXIgY3Jvbl9kYWlseV9yZXN0YXJ0X3Byb3h5X2ZpbGU9IiMhL2Jpbi9iYXNoCnN5c3RlbWN0bCByZXN0YXJ0IHByb3h5LnNlcnZpY2UiCgkKCXdyaXRlX2ZpbGUgY3Jvbl9kYWlseV9yZXN0YXJ0X3Byb3h5X2ZpbGVuYW1lIGNyb25fZGFpbHlfcmVzdGFydF9wcm94eV9maWxlCgljaG1vZCAreCAiJGNyb25fZGFpbHlfcmVzdGFydF9wcm94eV9maWxlbmFtZSIKfQoKZXhwb3J0IEFaVVJFX0NMT1VEX05BTUU9IiR7QVpVUkVDTE9VRE5BTUU6PyJGYWlsZWQgdG8gY2Fycnkgb3ZlciB2YXJpYWJsZXMifSIKCm1haW4gIiRAIgo=')))]" }, "provisionAfterExtensions": [ "Microsoft.Azure.Monitor.AzureMonitorLinuxAgent", diff --git a/pkg/deploy/assets/rp-production.json b/pkg/deploy/assets/rp-production.json index 19c4eed5edc..7eb662209c2 100644 --- a/pkg/deploy/assets/rp-production.json +++ b/pkg/deploy/assets/rp-production.json @@ -516,7 +516,7 @@ "autoUpgradeMinorVersion": true, "settings": {}, "protectedSettings": { - "script": "[base64(concat(base64ToString('c2V0IC1leAoK'),'ACRRESOURCEID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('acrResourceId')),''')\n','ADMINAPICLIENTCERTCOMMONNAME=$(base64 -d \u003c\u003c\u003c''',base64(parameters('adminApiClientCertCommonName')),''')\n','ARMAPICLIENTCERTCOMMONNAME=$(base64 -d \u003c\u003c\u003c''',base64(parameters('armApiClientCertCommonName')),''')\n','ARMCLIENTID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('armClientId')),''')\n','AZURECLOUDNAME=$(base64 -d \u003c\u003c\u003c''',base64(parameters('azureCloudName')),''')\n','AZURESECPACKQUALYSURL=$(base64 -d \u003c\u003c\u003c''',base64(parameters('azureSecPackQualysUrl')),''')\n','AZURESECPACKVSATENANTID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('azureSecPackVSATenantId')),''')\n','BILLINGE2ESTORAGEACCOUNTID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('billingE2EStorageAccountId')),''')\n','CLUSTERMDMACCOUNT=$(base64 -d \u003c\u003c\u003c''',base64(parameters('clusterMdmAccount')),''')\n','CLUSTERMDSDACCOUNT=$(base64 -d \u003c\u003c\u003c''',base64(parameters('clusterMdsdAccount')),''')\n','CLUSTERMDSDCONFIGVERSION=$(base64 -d \u003c\u003c\u003c''',base64(parameters('clusterMdsdConfigVersion')),''')\n','CLUSTERMDSDNAMESPACE=$(base64 -d \u003c\u003c\u003c''',base64(parameters('clusterMdsdNamespace')),''')\n','CLUSTERPARENTDOMAINNAME=$(base64 -d \u003c\u003c\u003c''',base64(parameters('clusterParentDomainName')),''')\n','DATABASEACCOUNTNAME=$(base64 -d \u003c\u003c\u003c''',base64(parameters('databaseAccountName')),''')\n','DBTOKENCLIENTID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('dbtokenClientId')),''')\n','FLUENTBITIMAGE=$(base64 -d \u003c\u003c\u003c''',base64(parameters('fluentbitImage')),''')\n','FPCLIENTID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('fpClientId')),''')\n','FPSERVICEPRINCIPALID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('fpServicePrincipalId')),''')\n','GATEWAYDOMAINS=$(base64 -d \u003c\u003c\u003c''',base64(parameters('gatewayDomains')),''')\n','GATEWAYRESOURCEGROUPNAME=$(base64 -d \u003c\u003c\u003c''',base64(parameters('gatewayResourceGroupName')),''')\n','GATEWAYSERVICEPRINCIPALID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('gatewayServicePrincipalId')),''')\n','KEYVAULTDNSSUFFIX=$(base64 -d \u003c\u003c\u003c''',base64(parameters('keyvaultDNSSuffix')),''')\n','KEYVAULTPREFIX=$(base64 -d \u003c\u003c\u003c''',base64(parameters('keyvaultPrefix')),''')\n','MDMFRONTENDURL=$(base64 -d \u003c\u003c\u003c''',base64(parameters('mdmFrontendUrl')),''')\n','MDSDENVIRONMENT=$(base64 -d \u003c\u003c\u003c''',base64(parameters('mdsdEnvironment')),''')\n','PORTALACCESSGROUPIDS=$(base64 -d \u003c\u003c\u003c''',base64(parameters('portalAccessGroupIds')),''')\n','PORTALCLIENTID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('portalClientId')),''')\n','PORTALELEVATEDGROUPIDS=$(base64 -d \u003c\u003c\u003c''',base64(parameters('portalElevatedGroupIds')),''')\n','RPFEATURES=$(base64 -d \u003c\u003c\u003c''',base64(parameters('rpFeatures')),''')\n','RPIMAGE=$(base64 -d \u003c\u003c\u003c''',base64(parameters('rpImage')),''')\n','RPMDMACCOUNT=$(base64 -d \u003c\u003c\u003c''',base64(parameters('rpMdmAccount')),''')\n','RPMDSDACCOUNT=$(base64 -d \u003c\u003c\u003c''',base64(parameters('rpMdsdAccount')),''')\n','RPMDSDCONFIGVERSION=$(base64 -d \u003c\u003c\u003c''',base64(parameters('rpMdsdConfigVersion')),''')\n','RPMDSDNAMESPACE=$(base64 -d \u003c\u003c\u003c''',base64(parameters('rpMdsdNamespace')),''')\n','RPPARENTDOMAINNAME=$(base64 -d \u003c\u003c\u003c''',base64(parameters('rpParentDomainName')),''')\n','CLUSTERSINSTALLVIAHIVE=$(base64 -d \u003c\u003c\u003c''',base64(parameters('clustersInstallViaHive')),''')\n','CLUSTERSADOPTBYHIVE=$(base64 -d \u003c\u003c\u003c''',base64(parameters('clustersAdoptByHive')),''')\n','CLUSTERDEFAULTINSTALLERPULLSPEC=$(base64 -d \u003c\u003c\u003c''',base64(parameters('clusterDefaultInstallerPullspec')),''')\n','USECHECKACCESS=$(base64 -d \u003c\u003c\u003c''',base64(parameters('useCheckAccess')),''')\n','ADMINAPICABUNDLE=''',parameters('adminApiCaBundle'),'''\n','ARMAPICABUNDLE=''',parameters('armApiCaBundle'),'''\n','MDMIMAGE=''/genevamdm:2.2024.328.1744-c5fb79-20240328t1935''\n','LOCATION=$(base64 -d \u003c\u003c\u003c''',base64(resourceGroup().location),''')\n','SUBSCRIPTIONID=$(base64 -d \u003c\u003c\u003c''',base64(subscription().subscriptionId),''')\n','RESOURCEGROUPNAME=$(base64 -d \u003c\u003c\u003c''',base64(resourceGroup().name),''')\n','\n',base64ToString('IyEvYmluL2Jhc2gKCnNldCAtbyBlcnJleGl0IFwKICAgIC1vIG5vdW5zZXQKCmlmIFsgIiR7REVCVUc6LWZhbHNlfSIgPT0gdHJ1ZSBdOyB0aGVuCiAgICBzZXQgLXgKZmkKCm1haW4oKSB7CiAgICAjIHRyYW5zYWN0aW9uIGF0dGVtcHQgcmV0cnkgdGltZSBpbiBzZWNvbmRzCiAgICBsb2NhbCAtcmkgcmV0cnlfd2FpdF90aW1lPTYwCgogICAgIyBzaGVsbGNoZWNrIHNvdXJjZT1jb21tb24uc2gKICAgIHNvdXJjZSBjb21tb24uc2gKCiAgICBsb2NhbCAtYXIgZXhjbHVkZV9wa2dzPSgKICAgICAgICAiLXggV0FMaW51eEFnZW50IgogICAgICAgICIteCBXQUxpbnV4QWdlbnQtdWRldiIKICAgICkKCiAgICBsb2NhbCAtcmEgcnBtX2tleXM9KAogICAgICAgIGh0dHBzOi8vZGwuZmVkb3JhcHJvamVjdC5vcmcvcHViL2VwZWwvUlBNLUdQRy1LRVktRVBFTC04CiAgICAgICAgaHR0cHM6Ly9wYWNrYWdlcy5taWNyb3NvZnQuY29tL2tleXMvbWljcm9zb2Z0LmFzYwogICAgKQoKICAgIGxvY2FsIC1yYSByZXBvX3JwbV9wa2dzPSgKICAgICAgICBodHRwczovL2RsLmZlZG9yYXByb2plY3Qub3JnL3B1Yi9lcGVsL2VwZWwtcmVsZWFzZS1sYXRlc3QtOC5ub2FyY2gucnBtCiAgICApCgogICAgbG9jYWwgLXJhIGluc3RhbGxfcGtncz0oCiAgICAgICAgY2xhbWF2CiAgICAgICAgYXpzZWMtY2xhbWF2CiAgICAgICAgYXpzZWMtbW9uaXRvcgogICAgICAgIGF6dXJlLWNsaQogICAgICAgIGF6dXJlLW1kc2QKICAgICAgICBhenVyZS1zZWN1cml0eQogICAgICAgIHBvZG1hbgogICAgICAgIHBvZG1hbi1kb2NrZXIKICAgICAgICBvcGVuc3NsLXBlcmwKICAgICAgICAjIGhhY2sgLSB3ZSBhcmUgaW5zdGFsbGluZyBweXRob24zIG9uIGhvc3RzIGR1ZSB0byBhbiBpc3N1ZSB3aXRoIEF6dXJlIExpbnV4IEV4dGVuc2lvbnMgaHR0cHM6Ly9naXRodWIuY29tL0F6dXJlL2F6dXJlLWxpbnV4LWV4dGVuc2lvbnMvcHVsbC8xNTA1CiAgICAgICAgcHl0aG9uMwogICAgKQoKICAgIE1ETUlNQUdFPSIke1JQSU1BR0UlJS8qfS8ke01ETUlNQUdFIyMqL30iCiAgICBsb2NhbCAtcmEgaW1hZ2VzPSgKICAgICAgICAiJE1ETUlNQUdFIgogICAgICAgICIkUlBJTUFHRSIKICAgICAgICAiJEZMVUVOVEJJVElNQUdFIgogICAgKQoKICAgIGxvY2FsIC1yYSBlbmFibGVfcG9ydHM9KAogICAgICAgICI0NDMvdGNwIgogICAgICAgICI0NDQvdGNwIgogICAgICAgICI0NDUvdGNwIgogICAgICAgICIyMjIyL3RjcCIKICAgICkKCiAgICBsb2NhbCAtcmEgYXJvX3NlcnZpY2VzPSgKICAgICAgICAiYXJvLWRidG9rZW4iCiAgICAgICAgImFyby1tb25pdG9yIgogICAgICAgICJhcm8tcG9ydGFsIgogICAgICAgICJhcm8tcnAiCiAgICAgICAgImF1b21zIgogICAgICAgICJhenNlY2QiCiAgICAgICAgImF6c2VjbW9uZCIKICAgICAgICAibWRzZCIKICAgICAgICAibWRtIgogICAgICAgICJjaHJvbnlkIgogICAgICAgICJmbHVlbnRiaXQiCiAgICApCgogICAgcGFyc2VfcnVuX29wdGlvbnMgIiRAIiBcCiAgICAgICAgICAgICAgICAgICAgICAgIHJldHJ5X3dhaXRfdGltZSBcCiAgICAgICAgICAgICAgICAgICAgICAgIGV4Y2x1ZGVfcGtncyBcCiAgICAgICAgICAgICAgICAgICAgICAgIHJwbV9rZXlzIFwKICAgICAgICAgICAgICAgICAgICAgICAgcmVwb19ycG1fcGtncyBcCiAgICAgICAgICAgICAgICAgICAgICAgIGluc3RhbGxfcGtncyBcCiAgICAgICAgICAgICAgICAgICAgICAgIGltYWdlcyBcCiAgICAgICAgICAgICAgICAgICAgICAgIGVuYWJsZV9wb3J0cyBcCiAgICAgICAgICAgICAgICAgICAgICAgIGFyb19zZXJ2aWNlcwoKICAgIGNvbmZpZ3VyZV9zc2hkCiAgICBjb25maWd1cmVfcnBtX3JlcG9zIHJldHJ5X3dhaXRfdGltZQoKICAgIGRuZl91cGRhdGVfcGtncyBleGNsdWRlX3BrZ3MgcmV0cnlfd2FpdF90aW1lCgogICAgcnBtX2ltcG9ydF9rZXlzIHJwbV9rZXlzIHJldHJ5X3dhaXRfdGltZQoKICAgIGRuZl9pbnN0YWxsX3BrZ3MgcmVwb19ycG1fcGtncyByZXRyeV93YWl0X3RpbWUKICAgIGRuZl9pbnN0YWxsX3BrZ3MgaW5zdGFsbF9wa2dzIHJldHJ5X3dhaXRfdGltZQogICAgY29uZmlndXJlX2RuZl9jcm9uX2pvYgoKICAgIGNvbmZpZ3VyZV9kaXNrX3BhcnRpdGlvbnMKICAgIGNvbmZpZ3VyZV9sb2dyb3RhdGUKICAgIGNvbmZpZ3VyZV9zZWxpbnV4CgogICAgbWtkaXIgLXAgL3Zhci9sb2cvam91cm5hbAogICAgbWtkaXIgLXAgL3Zhci9saWIvd2FhZ2VudC9NaWNyb3NvZnQuQXp1cmUuS2V5VmF1bHQuU3RvcmUKCiAgICBjb25maWd1cmVfZmlyZXdhbGxkX3J1bGVzIGVuYWJsZV9wb3J0cwoKICAgIHB1bGxfY29udGFpbmVyX2ltYWdlcyBpbWFnZXMKICAgIGNvbmZpZ3VyZV9hcm9fc2VydmljZXMKICAgIGVuYWJsZV9zZXJ2aWNlcwoKICAgIGVuYWJsZV9zZXJ2aWNlcyBhcm9fc2VydmljZXMKCiAgICByZWJvb3Rfdm0KfQoKdXNhZ2UoKSB7CiAgICBsb2NhbCAtbiBvcHRpb25zPSIkMSIKICAgIGxvZyAiJChiYXNlbmFtZSAiJDAiKSBbJG9wdGlvbnNdCiAgICAgICAgLWQgQ29uZmlndXJlIERpc2sgUGFydGl0aW9ucwogICAgICAgIC1wIENvbmZpZ3VyZSBycG0gcmVwb3NpdG9yaWVzLCBpbXBvcnQgcmVxdWlyZWQgcnBtIGtleXMsIHVwZGF0ZSAmIGluc3RhbGwgcGFja2FnZXMgd2l0aCBkbmYKICAgICAgICAtbCBDb25maWd1cmUgbG9ncm90YXRlLmNvbmYKICAgICAgICAtcyBDb25maWd1cmUgc2VsaW51eAogICAgICAgIC1yIENvbmZpZ3VyZSBzc2hkIC0gQWxsb3cgcGFzc3dvcmQgYXV0aGVudGljYWl0b24KICAgICAgICAtZiBDb25maWd1cmUgZmlyZXdhbGxkIGRlZmF1bHQgem9uZSBydWxlcwogICAgICAgIC11IENvbmZpZ3VyZSBzeXN0ZW1kIHVuaXQgZmlsZXMKICAgICAgICAtaSBQdWxsIGNvbnRhaW5lciBpbWFnZXMKCiAgICAgICAgTm90ZTogc3RlcHMgd2lsbCBiZSBleGVjdXRlZCBpbiB0aGUgb3JkZXIgdGhhdCBmbGFncyBhcmUgcHJvdmlkZWQKICAgICIKfQoKIyBwYXJzZV9ydW5fb3B0aW9ucyB0YWtlcyBhbGwgYXJndWVtZW50cyBwYXNzZWQgdG8gbWFpbiBhbmQgcGFyc2VzIHRoZW0KIyBhbGxvd2luZyBpbmRpdmlkdWFsIHN0ZXAocykgdG8gYmUgcmFuLCByYXRoZXIgdGhhbiBhbGwgc3RlcHMKIwojIFRoaXMgaXMgdXNlZnVsIGZvciBsb2NhbCB0ZXN0aW5nLCBvciBwb3NzaWJseSBtb2RpZnlpbmcgdGhlIGJvb3RzdHJhcCBleGVjdXRpb24gdmlhIGVudmlyb25tZW50IHZhcmlhYmxlcyBpbiB0aGUgZGVwbG95bWVudCBwaXBlbGluZQpwYXJzZV9ydW5fb3B0aW9ucygpIHsKICAgICMgc2hlbGxjaGVjayBkaXNhYmxlPVNDMjIwNgogICAgbG9jYWwgLWEgb3B0aW9ucz0oJHsxOi19KQogICAgbG9jYWwgLW4gcmV0cnlfdGltZT0iJDIiCiAgICBsb2NhbCAtbiBwa2dzX3RvX2V4Y2x1ZGU9IiQzIgogICAgbG9jYWwgLW4ga2V5c190b19pbXBvcnQ9IiQ0IgogICAgbG9jYWwgLW4gcnBtX3BrZ3M9IiQ1IgogICAgbG9jYWwgLW4gcGtnc190b19pbnN0YWxsPSIkNiIKICAgIGxvY2FsIC1uIGltYWdlc190b19wdWxsPSIkNyIKICAgIGxvY2FsIC1uIHBvcnRzX3RvX2VuYWJsZT0iJDgiCiAgICBsb2NhbCAtbiBzZXJ2aWNlc190b19lbmFibGU9IiQ5IgoKICAgIGlmIFsgIiR7I29wdGlvbnNbQF19IiAtZXEgMCBdOyB0aGVuCiAgICAgICAgbG9nICJSdW5uaW5nIGFsbCBzdGVwcyIKICAgICAgICByZXR1cm4gMAogICAgZmkKCiAgICBsb2NhbCBPUFRJTkQKICAgIGxvY2FsIC1yIGFsbG93ZWRfb3B0aW9ucz0iZHBsc3JmdWkiCiAgICB3aGlsZSBnZXRvcHRzICR7YWxsb3dlZF9vcHRpb25zfSBvcHRpb25zOyBkbwogICAgICAgIGNhc2UgIiR7b3B0aW9uc30iIGluCiAgICAgICAgICAgIGQpCiAgICAgICAgICAgICAgICBsb2cgIlJ1bm5pbmcgc3RlcCBjb25maWd1cmVfZGlza19wYXJ0aXRpb25zIgogICAgICAgICAgICAgICAgY29uZmlndXJlX2Rpc2tfcGFydGl0aW9ucwogICAgICAgICAgICAgICAgOzsKICAgICAgICAgICAgcCkKICAgICAgICAgICAgICAgIGxvZyAiUnVubmluZyBzdGVwIGNvbmZpZ3VyZV9ycG1fcmVwb3MiCiAgICAgICAgICAgICAgICBjb25maWd1cmVfcnBtX3JlcG9zIGtleXNfdG9faW1wb3J0CgogICAgICAgICAgICAgICAgbG9nICJSdW5uaW5nIHN0ZXAgZG5mX3VwZGF0ZV9wa2dzIgogICAgICAgICAgICAgICAgZG5mX3VwZGF0ZV9wa2dzIHBrZ3NfdG9fZXhjbHVkZSByZXRyeV90aW1lCgogICAgICAgICAgICAgICAgbG9nICJSdW5uaW5nIHN0ZXAgZG5mX2luc3RhbGxfcGtncyBycG1fcGtncyIKICAgICAgICAgICAgICAgIGRuZl9pbnN0YWxsX3BrZ3MgcnBtX3BrZ3MgcmV0cnlfdGltZQoKICAgICAgICAgICAgICAgIGxvZyAiUnVubmluZyBzdGVwIGRuZl9pbnN0YWxsX3BrZ3MgcGtncyIKICAgICAgICAgICAgICAgIGRuZl9pbnN0YWxsX3BrZ3MgcGtnc190b19pbnN0YWxsIHJldHJ5X3RpbWUKICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgbG9nICJSdW5uaW5nIHN0ZXAgY29uZmlndXJlX2RuZl9jcm9uZF9qb2IiCiAgICAgICAgICAgICAgICBjb25maWd1cmVfZG5mX2Nyb25fam9iCiAgICAgICAgICAgICAgICA7OwogICAgICAgICAgICBsKQogICAgICAgICAgICAgICAgbG9nICJSdW5uaW5nIGNvbmZpZ3VyZV9sb2dyb3RhdGUiCiAgICAgICAgICAgICAgICBjb25maWd1cmVfbG9ncm90YXRlCiAgICAgICAgICAgICAgICA7OwogICAgICAgICAgICBzKQogICAgICAgICAgICAgICAgbG9nICJSdW5uaW5nIGNvbmZpZ3VyZV9zZWxpbnV4IgogICAgICAgICAgICAgICAgY29uZmlndXJlX3NlbGludXgKICAgICAgICAgICAgICAgIDs7CiAgICAgICAgICAgIHIpCiAgICAgICAgICAgICAgICBsb2cgIlJ1bm5pbmcgY29uZmlndXJlX3NzaGQiCiAgICAgICAgICAgICAgICBjb25maWd1cmVfc3NoZAogICAgICAgICAgICAgICAgOzsKICAgICAgICAgICAgZikKICAgICAgICAgICAgICAgIGxvZyAiUnVubmluZyBjb25maWd1cmVfZmlyZXdhbGxkX3J1bGVzIgogICAgICAgICAgICAgICAgY29uZmlndXJlX2ZpcmV3YWxsZF9ydWxlcyBwb3J0c190b19lbmFibGUKICAgICAgICAgICAgICAgIDs7CiAgICAgICAgICAgIHUpCiAgICAgICAgICAgICAgICBsb2cgIlJ1bm5pbmcgcHVsbF9jb250YWluZXJfaW1hZ2VzICYgY29uZmlndXJlX3N5c3RlbV9zZXJ2aWNlcyIKICAgICAgICAgICAgICAgIGNvbmZpZ3VyZV9hcm9fc2VydmljZXMKICAgICAgICAgICAgICAgIGVuYWJsZV9zZXJ2aWNlcyBzZXJ2aWNlc190b19lbmFibGUKICAgICAgICAgICAgICAgIDs7CiAgICAgICAgICAgIGkpCiAgICAgICAgICAgICAgICBsb2cgIlJ1bm5pbmcgcHVsbF9jb250YWluZXJfaW1hZ2VzIgogICAgICAgICAgICAgICAgcHVsbF9jb250YWluZXJfaW1hZ2VzIGltYWdlc190b19wdWxsCiAgICAgICAgICAgICAgICA7OwogICAgICAgICAgICAqKQogICAgICAgICAgICAgICAgdXNhZ2UgYWxsb3dlZF9vcHRpb25zCiAgICAgICAgICAgICAgICBhYm9ydCAiVW5rb3duIG9wdGlvbiBwcm92aWRlZCIKICAgICAgICAgICAgICAgIDs7CiAgICAgICAgZXNhYwogICAgZG9uZQogICAgCiAgICBleGl0IDAKfQoKIyBjb25maWd1cmVfcnBtX3JlcG9zCmNvbmZpZ3VyZV9ycG1fcmVwb3MoKSB7CiAgICBsb2cgInN0YXJ0aW5nIgoKICAgIGNvbmZpZ3VyZV9yaHVpX3JlcG8gIiQxIgogICAgY3JlYXRlX2F6dXJlX3JwbV9yZXBvcyAiJDEiCn0KCiMgY29uZmlndXJlX2Rpc2tfcGFydGl0aW9ucwpjb25maWd1cmVfZGlza19wYXJ0aXRpb25zKCkgewogICAgbG9nICJzdGFydGluZyIKICAgIGxvZyAiZXh0ZW5kaW5nIHBhcnRpdGlvbiB0YWJsZSIKCiAgICAjIExpbnV4IGJsb2NrIGRldmljZXMgYXJlIGluY29uc2lzdGVudGx5IG5hbWVkCiAgICAjIGl0J3MgZGlmZmljdWx0IHRvIHRpZSB0aGUgbHZtIHB2IHRvIHRoZSBwaHlzaWNhbCBkaXNrIHVzaW5nIC9kZXYvZGlzayBmaWxlcywgd2hpY2ggaXMgd2h5IGx2cyBpcyB1c2VkIGhlcmUKICAgIHBoeXNpY2FsX2Rpc2s9IiQobHZzIC1vIGRldmljZXMgLWEgfCBoZWFkIC1uMiB8IHRhaWwgLW4xIHwgY3V0IC1kICcgJyAtZiAzIHwgY3V0IC1kIFwoIC1mIDEgfCB0ciAtZCAnWzpkaWdpdDpdJykiCiAgICBncm93cGFydCAiJHBoeXNpY2FsX2Rpc2siIDIKCiAgICBsb2cgImV4dGVuZGluZyBmaWxlc3lzdGVtcyIKICAgIGxvZyAiZXh0ZW5kaW5nIHJvb3QgbHZtIgogICAgbHZleHRlbmQgLWwgKzIwJUZSRUUgL2Rldi9yb290dmcvcm9vdGx2CiAgICBsb2cgImdyb3dpbmcgcm9vdCBmaWxlc3lzdGVtIgogICAgeGZzX2dyb3dmcyAvCgogICAgbG9nICJleHRlbmRpbmcgdmFyIGx2bSIKICAgIGx2ZXh0ZW5kIC1sICsxMDAlRlJFRSAvZGV2L3Jvb3R2Zy92YXJsdgogICAgbG9nICJncm93aW5nIHZhciBmaWxlc3lzdGVtIgogICAgeGZzX2dyb3dmcyAvdmFyCn0KCiMgY3JlYXRlX2F6dXJlX3JwbV9yZXBvcyBjcmVhdGVzIC9ldGMveXVtLnJlcG9zLmQvYXp1cmUucmVwbyByZXBvc2l0b3J5IGZpbGUKY3JlYXRlX2F6dXJlX3JwbV9yZXBvcygpIHsKICAgIGxvZyAic3RhcnRpbmciCgogICAgbG9jYWwgLXIgYXp1cmVfcmVwb19maWxlbmFtZT0nL2V0Yy95dW0ucmVwb3MuZC9henVyZS5yZXBvJwogICAgbG9jYWwgLXIgYXp1cmVfcmVwb19maWxlPSdbYXp1cmUtY2xpXQpuYW1lPWF6dXJlLWNsaQpiYXNldXJsPWh0dHBzOi8vcGFja2FnZXMubWljcm9zb2Z0LmNvbS95dW1yZXBvcy9henVyZS1jbGkKZW5hYmxlZD15ZXMKZ3BnY2hlY2s9eWVzCgpbYXp1cmVjb3JlXQpuYW1lPWF6dXJlY29yZQpiYXNldXJsPWh0dHBzOi8vcGFja2FnZXMubWljcm9zb2Z0LmNvbS95dW1yZXBvcy9henVyZWNvcmUKZW5hYmxlZD15ZXMKZ3BnY2hlY2s9bm8nCgogICAgd3JpdGVfZmlsZSBhenVyZV9yZXBvX2ZpbGVuYW1lIGF6dXJlX3JlcG9fZmlsZSB0cnVlCn0KCiMgY29uZmlndXJlX2Fyb19zZXJ2aWNlcyBjcmVhdGVzLCBjb25maWd1cmVzLCBhbmQgZW5hYmxlcyB0aGUgZm9sbG93aW5nIHN5c3RlbWQgc2VydmljZXMgYW5kIHRpbWVycwojIHNlcnZpY2VzCiMgICBmbHVlbnRiaXQKIyAgIG1kbQojICAgbWRzZAojICAgYXJwLXJwCiMgICBhcm8tZGJ0b2tlbgojICAgYXJvLW1vbml0b3IKIyAgIGFyby1wb3J0YWwKY29uZmlndXJlX2Fyb19zZXJ2aWNlcygpIHsKICAgIGNvbmZpZ3VyZV9zZXJ2aWNlX2ZsdWVudGJpdAogICAgY29uZmlndXJlX3NlcnZpY2VfbWRtCiAgICBjb25maWd1cmVfdGltZXJzX21kbV9tZHNkCiAgICBjb25maWd1cmVfc2VydmljZV9hcm9fcnAKICAgIGNvbmZpZ3VyZV9zZXJ2aWNlX2Fyb19kYnRva2VuCiAgICBjb25maWd1cmVfc2VydmljZV9hcm9fbW9uaXRvcgogICAgY29uZmlndXJlX3NlcnZpY2VfYXJvX3BvcnRhbAogICAgY29uZmlndXJlX3NlcnZpY2VfbWRzZAp9CgojIGNvbmZpZ3VyZV9zZXJ2aWNlX2ZsdWVudGJpdApjb25maWd1cmVfc2VydmljZV9mbHVlbnRiaXQoKSB7CiAgICBsb2cgInN0YXJ0aW5nIgogICAgbG9nICJjb25maWd1cmluZyBmbHVlbnRiaXQgc2VydmljZSIKCiAgICBta2RpciAtcCAvZXRjL2ZsdWVudGJpdC8KICAgIG1rZGlyIC1wIC92YXIvbGliL2ZsdWVudAoKICAgIGxvY2FsIC1yIGZsdWVudGJpdF9jb25mX2ZpbGVuYW1lPScvZXRjL2ZsdWVudGJpdC9mbHVlbnRiaXQuY29uZicKICAgIGxvY2FsIC1yIGZsdWVudGJpdF9jb25mX2ZpbGU9IltJTlBVVF0KTmFtZSBzeXN0ZW1kClRhZyBqb3VybmFsZApTeXN0ZW1kX0ZpbHRlciBfQ09NTT1hcm8KREIgL3Zhci9saWIvZmx1ZW50L2pvdXJuYWxkYgoKW0ZJTFRFUl0KCU5hbWUgbW9kaWZ5CglNYXRjaCBqb3VybmFsZAoJUmVtb3ZlX3dpbGRjYXJkIF8KCVJlbW92ZSBUSU1FU1RBTVAKCltGSUxURVJdCglOYW1lIHJld3JpdGVfdGFnCglNYXRjaCBqb3VybmFsZAoJUnVsZSAkTE9HS0lORCBhc3luY3FvcyBhc3luY3FvcyB0cnVlCgpbRklMVEVSXQoJTmFtZSBtb2RpZnkKCU1hdGNoIGFzeW5jcW9zCglSZW1vdmUgQ0xJRU5UX1BSSU5DSVBBTF9OQU1FCglSZW1vdmUgRklMRQoJUmVtb3ZlIENPTVBPTkVOVAoKW0ZJTFRFUl0KCU5hbWUgcmV3cml0ZV90YWcKCU1hdGNoIGpvdXJuYWxkCglSdWxlICRMT0dLSU5EIGlmeGF1ZGl0IGlmeGF1ZGl0IGZhbHNlCgpbT1VUUFVUXQoJTmFtZSBmb3J3YXJkCglNYXRjaCAqCglQb3J0IDI5MjMwIgoKICAgIHdyaXRlX2ZpbGUgZmx1ZW50Yml0X2NvbmZfZmlsZW5hbWUgZmx1ZW50Yml0X2NvbmZfZmlsZSB0cnVlCgogICAgbG9jYWwgLXIgc3lzY29uZmlnX2ZsdWVudGJpdF9maWxlbmFtZT0nL2V0Yy9zeXNjb25maWcvZmx1ZW50Yml0JwogICAgbG9jYWwgLXIgc3lzY29uZmlnX2ZsdWVudGJpdF9maWxlPSJGTFVFTlRCSVRJTUFHRT0kRkxVRU5UQklUSU1BR0UiCgogICAgd3JpdGVfZmlsZSBzeXNjb25maWdfZmx1ZW50Yml0X2ZpbGVuYW1lIHN5c2NvbmZpZ19mbHVlbnRiaXRfZmlsZSB0cnVlCgogICAgbG9jYWwgLXIgZmx1ZW50Yml0X3NlcnZpY2VfZmlsZW5hbWU9Jy9ldGMvc3lzdGVtZC9zeXN0ZW0vZmx1ZW50Yml0LnNlcnZpY2UnCgogICAgbG9jYWwgLXIgZmx1ZW50Yml0X3NlcnZpY2VfZmlsZT0iW1VuaXRdCkFmdGVyPW5ldHdvcmstb25saW5lLnRhcmdldApXYW50cz1uZXR3b3JrLW9ubGluZS50YXJnZXQKU3RhcnRMaW1pdEludGVydmFsU2VjPTAKCltTZXJ2aWNlXQpSZXN0YXJ0U2VjPTFzCkVudmlyb25tZW50RmlsZT0vZXRjL3N5c2NvbmZpZy9mbHVlbnRiaXQKRXhlY1N0YXJ0UHJlPS0vdXNyL2Jpbi9kb2NrZXIgcm0gLWYgJU4KRXhlY1N0YXJ0PS91c3IvYmluL2RvY2tlciBydW4gXAogIC0tc2VjdXJpdHktb3B0IGxhYmVsPWRpc2FibGUgXAogIC0tZW50cnlwb2ludCAvb3B0L3RkLWFnZW50LWJpdC9iaW4vdGQtYWdlbnQtYml0IFwKICAtLW5ldD1ob3N0IFwKICAtLWhvc3RuYW1lICVIIFwKICAtLW5hbWUgJU4gXAogIC0tcm0gXAogIC0tY2FwLWRyb3AgbmV0X3JhdyBcCiAgLXYgL2V0Yy9mbHVlbnRiaXQvZmx1ZW50Yml0LmNvbmY6L2V0Yy9mbHVlbnRiaXQvZmx1ZW50Yml0LmNvbmYgXAogIC12IC92YXIvbGliL2ZsdWVudDovdmFyL2xpYi9mbHVlbnQ6eiBcCiAgLXYgL3Zhci9sb2cvam91cm5hbDovdmFyL2xvZy9qb3VybmFsOnJvIFwKICAtdiAvZXRjL21hY2hpbmUtaWQ6L2V0Yy9tYWNoaW5lLWlkOnJvIFwKICAkRkxVRU5UQklUSU1BR0UgXAogIC1jIC9ldGMvZmx1ZW50Yml0L2ZsdWVudGJpdC5jb25mCgpFeGVjU3RvcD0vdXNyL2Jpbi9kb2NrZXIgc3RvcCAlTgpSZXN0YXJ0PWFsd2F5cwpSZXN0YXJ0U2VjPTUKU3RhcnRMaW1pdEludGVydmFsPTAKCltJbnN0YWxsXQpXYW50ZWRCeT1tdWx0aS11c2VyLnRhcmdldCIKCiAgICB3cml0ZV9maWxlIGZsdWVudGJpdF9zZXJ2aWNlX2ZpbGVuYW1lIGZsdWVudGJpdF9zZXJ2aWNlX2ZpbGUgdHJ1ZQp9CgojIGNvbmZpZ3VyZV9jZXJ0cwpjb25maWd1cmVfY2VydHMoKSB7CiAgICBsb2cgInN0YXJ0aW5nIgoKICAgIG1rZGlyIC9ldGMvYXJvLXJwCiAgICBiYXNlNjQgLWQgPDw8IiRBRE1JTkFQSUNBQlVORExFIiA+L2V0Yy9hcm8tcnAvYWRtaW4tY2EtYnVuZGxlLnBlbQogICAgaWYgW1sgLW4gIiRBUk1BUElDQUJVTkRMRSIgXV07IHRoZW4KICAgIGJhc2U2NCAtZCA8PDwiJEFSTUFQSUNBQlVORExFIiA+L2V0Yy9hcm8tcnAvYXJtLWNhLWJ1bmRsZS5wZW0KICAgIGZpCiAgICBjaG93biAtUiAxMDAwOjEwMDAgL2V0Yy9hcm8tcnAKCiAgICAjIHNldHRpbmcgTU9OSVRPUklOR19HQ1NfQVVUSF9JRF9UWVBFPUF1dGhLZXlWYXVsdCBzZWVtcyB0byBoYXZlIGNhdXNlZCBtZHNkIG5vdAogICAgIyB0byBob25vdXIgU1NMX0NFUlRfRklMRSBhbnkgbW9yZSwgaGVhdmVuIG9ubHkga25vd3Mgd2h5LgogICAgbWtkaXIgLXAgL3Vzci9saWIvc3NsL2NlcnRzCiAgICBjc3BsaXQgLWYgL3Vzci9saWIvc3NsL2NlcnRzL2NlcnQtIC1iICUwM2QucGVtIC9ldGMvcGtpL3Rscy9jZXJ0cy9jYS1idW5kbGUuY3J0IC9eJC8xICJ7Kn0iID4vZGV2L251bGwKICAgIGNfcmVoYXNoIC91c3IvbGliL3NzbC9jZXJ0cwoKIyB3ZSBsZWF2ZSBjbGllbnRJZCBibGFuayBhcyBsb25nIGFzIG9ubHkgMSBtYW5hZ2VkIGlkZW50aXR5IGFzc2lnbmVkIHRvIHZtc3MKIyBpZiB3ZSBoYXZlIG1vcmUgdGhhbiAxLCB3ZSB3aWxsIG5lZWQgdG8gcG9wdWxhdGUgd2l0aCBjbGllbnRJZCB1c2VkIGZvciBvZmYtbm9kZSBzY2FubmluZwogICAgbG9jYWwgLXIgbm9kZXNjYW5fYWdlbnRfZmlsZW5hbWU9Ii9ldGMvZGVmYXVsdC92c2Etbm9kZXNjYW4tYWdlbnQuY29uZmlnIgogICAgbG9jYWwgLXIgbm9kZXNjYW5fYWdlbnRfZmlsZT0iewogICAgXCJOaWNlXCI6IDE5LAogICAgXCJUaW1lb3V0XCI6IDEwODAwLAogICAgXCJDbGllbnRJZFwiOiBcIlwiLAogICAgXCJUZW5hbnRJZFwiOiAkQVpVUkVTRUNQQUNLVlNBVEVOQU5USUQsCiAgICBcIlF1YWx5c1N0b3JlQmFzZVVybFwiOiAkQVpVUkVTRUNQQUNLUVVBTFlTVVJMLAogICAgXCJQcm9jZXNzVGltZW91dFwiOiAzMDAsCiAgICBcIkNvbW1hbmREZWxheVwiOiAwCiAgfSIKCiAgICB3cml0ZV9maWxlIG5vZGVzY2FuX2FnZW50X2ZpbGVuYW1lIG5vZGVzY2FuX2FnZW50X2ZpbGUgdHJ1ZQp9CgojIGNvbmZpZ3VyZV9zZXJ2aWNlX21kbQpjb25maWd1cmVfc2VydmljZV9tZG0oKSB7CiAgICBsb2cgInN0YXJ0aW5nIgogICAgbG9nICJjb25maWd1cmluZyBtZG0gc2VydmljZSIKCiAgICBsb2NhbCAtciBzeXNjb25maWdfbWRtX2ZpbGVuYW1lPSIvZXRjL3N5c2NvbmZpZy9tZG0iCiAgICBsb2NhbCAtciBzeXNjb25maWdfbWRtX2ZpbGU9Ik1ETUZST05URU5EVVJMPSckTURNRlJPTlRFTkRVUkwnCk1ETUlNQUdFPSckTURNSU1BR0UnCk1ETVNPVVJDRUVOVklST05NRU5UPSckTE9DQVRJT04nCk1ETVNPVVJDRVJPTEU9cnAKTURNU09VUkNFUk9MRUlOU1RBTkNFPVwiJChob3N0bmFtZSlcIiIKCiAgICB3cml0ZV9maWxlIHN5c2NvbmZpZ19tZG1fZmlsZW5hbWUgc3lzY29uZmlnX21kbV9maWxlIHRydWUKCiAgICBta2RpciAtcCAvdmFyL2V0dwogICAgbG9jYWwgLXIgbWRtX3NlcnZpY2VfZmlsZW5hbWU9Ii9ldGMvc3lzdGVtZC9zeXN0ZW0vbWRtLnNlcnZpY2UiCiAgICBsb2NhbCAtciBtZG1fc2VydmljZV9maWxlPSJbVW5pdF0KQWZ0ZXI9bmV0d29yay1vbmxpbmUudGFyZ2V0CldhbnRzPW5ldHdvcmstb25saW5lLnRhcmdldAoKW1NlcnZpY2VdCkVudmlyb25tZW50RmlsZT0vZXRjL3N5c2NvbmZpZy9tZG0KRXhlY1N0YXJ0UHJlPS0vdXNyL2Jpbi9kb2NrZXIgcm0gLWYgJU4KRXhlY1N0YXJ0PS91c3IvYmluL2RvY2tlciBydW4gXAogIC0tZW50cnlwb2ludCAvdXNyL3NiaW4vTWV0cmljc0V4dGVuc2lvbiBcCiAgLS1ob3N0bmFtZSAlSCBcCiAgLS1uYW1lICVOIFwKICAtLXJtIFwKICAtLWNhcC1kcm9wIG5ldF9yYXcgXAogIC1tIDJnIFwKICAtdiAvZXRjL21kbS5wZW06L2V0Yy9tZG0ucGVtIFwKICAtdiAvdmFyL2V0dzovdmFyL2V0dzp6IFwKICAkTURNSU1BR0UgXAogIC1DZXJ0RmlsZSAvZXRjL21kbS5wZW0gXAogIC1Gcm9udEVuZFVybCAkTURNRlJPTlRFTkRVUkwgXAogIC1Mb2dnZXIgQ29uc29sZSBcCiAgLUxvZ0xldmVsIFdhcm5pbmcgXAogIC1Qcml2YXRlS2V5RmlsZSAvZXRjL21kbS5wZW0gXAogIC1Tb3VyY2VFbnZpcm9ubWVudCAkTURNU09VUkNFRU5WSVJPTk1FTlQgXAogIC1Tb3VyY2VSb2xlICRNRE1TT1VSQ0VST0xFIFwKICAtU291cmNlUm9sZUluc3RhbmNlICRNRE1TT1VSQ0VST0xFSU5TVEFOQ0UKRXhlY1N0b3A9L3Vzci9iaW4vZG9ja2VyIHN0b3AgJU4KUmVzdGFydD1hbHdheXMKUmVzdGFydFNlYz0xClN0YXJ0TGltaXRJbnRlcnZhbD0wCgpbSW5zdGFsbF0KV2FudGVkQnk9bXVsdGktdXNlci50YXJnZXQiCgogICAgd3JpdGVfZmlsZSBtZG1fc2VydmljZV9maWxlbmFtZSBtZG1fc2VydmljZV9maWxlIHRydWUKfQoKIyBjb25maWd1cmVfdGltZXJzX21kbV9tZHNkCmNvbmZpZ3VyZV90aW1lcnNfbWRtX21kc2QoKSB7CiAgICBsb2cgInN0YXJ0aW5nIgoKICAgIGZvciB2YXIgaW4gIm1kc2QiICJtZG0iOyBkbwogICAgICAgIGxvY2FsIGRvd25sb2FkX2NyZWRzX3NlcnZpY2VfZmlsZW5hbWU9Ii9ldGMvc3lzdGVtZC9zeXN0ZW0vZG93bmxvYWQtJHZhci1jcmVkZW50aWFscy5zZXJ2aWNlIgogICAgICAgIGxvY2FsIGRvd25sb2FkX2NyZWRzX3NlcnZpY2VfZmlsZT0iW1VuaXRdCkRlc2NyaXB0aW9uPVBlcmlvZGljICR2YXIgY3JlZGVudGlhbHMgcmVmcmVzaAoKW1NlcnZpY2VdClR5cGU9b25lc2hvdApFeGVjU3RhcnQ9L3Vzci9sb2NhbC9iaW4vZG93bmxvYWQtY3JlZGVudGlhbHMuc2ggJHZhciIKCiAgICAgICAgd3JpdGVfZmlsZSBkb3dubG9hZF9jcmVkc19zZXJ2aWNlX2ZpbGVuYW1lIGRvd25sb2FkX2NyZWRzX3NlcnZpY2VfZmlsZSB0cnVlCgogICAgICAgIGxvY2FsIGRvd25sb2FkX2NyZWRzX3RpbWVyX2ZpbGVuYW1lPSIvZXRjL3N5c3RlbWQvc3lzdGVtL2Rvd25sb2FkLSR2YXItY3JlZGVudGlhbHMudGltZXIiCiAgICAgICAgbG9jYWwgZG93bmxvYWRfY3JlZHNfdGltZXJfZmlsZT0iW1VuaXRdCkRlc2NyaXB0aW9uPVBlcmlvZGljICR2YXIgY3JlZGVudGlhbHMgcmVmcmVzaApBZnRlcj1uZXR3b3JrLW9ubGluZS50YXJnZXQKV2FudHM9bmV0d29yay1vbmxpbmUudGFyZ2V0CgpbVGltZXJdCk9uQm9vdFNlYz0wbWluCk9uQ2FsZW5kYXI9MC8xMjowMDowMApBY2N1cmFjeVNlYz01cwoKW0luc3RhbGxdCldhbnRlZEJ5PXRpbWVycy50YXJnZXQiCgogICAgICAgIHdyaXRlX2ZpbGUgZG93bmxvYWRfY3JlZHNfdGltZXJfZmlsZW5hbWUgZG93bmxvYWRfY3JlZHNfdGltZXJfZmlsZSB0cnVlCiAgICBkb25lCgogICAgbG9jYWwgLXIgZG93bmxvYWRfY3JlZHNfc2NyaXB0X2ZpbGVuYW1lPSIvdXNyL2xvY2FsL2Jpbi9kb3dubG9hZC1jcmVkZW50aWFscy5zaCIKICAgIGxvY2FsIC1yIGRvd25sb2FkX2NyZWRzX3NjcmlwdF9maWxlPSIjIS9iaW4vYmFzaApzZXQgLWV1CgpDT01QT05FTlQ9XCQxCmVjaG8gXCJEb3dubG9hZCBcJENPTVBPTkVOVCBjcmVkZW50aWFsc1wiCgpURU1QX0RJUj1cIlwkKG1rdGVtcCAtZClcIgpleHBvcnQgQVpVUkVfQ09ORklHX0RJUj1cIlwkKG1rdGVtcCAtZClcIgoKZWNobyBcIkxvZ2dpbmcgaW50byBBenVyZS4uLlwiClJFVFJJRVM9Mwp3aGlsZSBbWyBcJFJFVFJJRVMgLWd0IDAgXV07IGRvCiAgICBpZiBheiBsb2dpbiAtaSAtLWFsbG93LW5vLXN1YnNjcmlwdGlvbnMKICAgIHRoZW4KICAgICAgICBlY2hvIFwiYXogbG9naW4gc3VjY2Vzc2Z1bFwiCiAgICAgICAgYnJlYWsKICAgIGVsc2UKICAgICAgICBlY2hvIFwiYXogbG9naW4gZmFpbGVkLiBSZXRyeWluZy4uLlwiCiAgICAgICAgbGV0IFJFVFJJRVMtPTEKICAgICAgICBzbGVlcCA1CiAgICBmaQpkb25lCgp0cmFwIFwiY2xlYW51cFwiIEVYSVQKCmNsZWFudXAoKSB7CiAgYXogbG9nb3V0CiAgW1sgXCRURU1QX0RJUiA9fiAvdG1wLy4rIF1dICYmIHJtIC1yZiBcJFRFTVBfRElSCiAgW1sgXCRBWlVSRV9DT05GSUdfRElSID1+IC90bXAvLisgXV0gJiYgcm0gLXJmIFwkQVpVUkVfQ09ORklHX0RJUgp9CgppZiBbWyBcJENPTVBPTkVOVCA9IFwibWRtXCIgXV07IHRoZW4KICBDVVJSRU5UX0NFUlRfRklMRT1cIi9ldGMvbWRtLnBlbVwiCmVsaWYgW1sgXCRDT01QT05FTlRcID0gXCJtZHNkXCIgXV07IHRoZW4KICBDVVJSRU5UX0NFUlRfRklMRT1cIi92YXIvbGliL3dhYWdlbnQvTWljcm9zb2Z0LkF6dXJlLktleVZhdWx0LlN0b3JlL21kc2QucGVtXCIKZWxzZQogIGVjaG8gSW52YWxpZCB1c2FnZSAmJiBleGl0IDEKZmkKClNFQ1JFVF9OQU1FPVwicnAtXCR7Q09NUE9ORU5UfVwiCk5FV19DRVJUX0ZJTEU9XCJcJFRFTVBfRElSL1wkQ09NUE9ORU5ULnBlbVwiCmZvciBhdHRlbXB0IGluIHsxLi41fTsgZG8KICBheiBrZXl2YXVsdCBcCiAgICBzZWNyZXQgXAogICAgZG93bmxvYWQgXAogICAgLS1maWxlIFwiXCRORVdfQ0VSVF9GSUxFXCIgXAogICAgLS1pZCBcImh0dHBzOi8vJEtFWVZBVUxUUFJFRklYLXN2Yy4kS0VZVkFVTFRETlNTVUZGSVgvc2VjcmV0cy9cJFNFQ1JFVF9OQU1FXCIgXAogICAgJiYgYnJlYWsKICBpZiBbWyBcJGF0dGVtcHQgLWx0IDUgXV07IHRoZW4gc2xlZXAgMTA7IGVsc2UgZXhpdCAxOyBmaQpkb25lCgppZiBbIC1mIFwkTkVXX0NFUlRfRklMRSBdOyB0aGVuCiAgaWYgW1sgXCRDT01QT05FTlQgPSBcIm1kc2RcIiBdXTsgdGhlbgogICAgY2hvd24gc3lzbG9nOnN5c2xvZyBcJE5FV19DRVJUX0ZJTEUKICBlbHNlCiAgICBzZWQgLWkgLW5lICcxLC9FTkQgQ0VSVElGSUNBVEUvIHAnIFwkTkVXX0NFUlRfRklMRQogIGZpCgogIG5ld19jZXJ0X3NuPVwiXCQob3BlbnNzbCB4NTA5IC1pbiBcIlwkTkVXX0NFUlRfRklMRVwiIC1ub291dCAtc2VyaWFsIHwgYXdrIC1GPSAne3ByaW50IFwkMn0nKVwiCiAgY3VycmVudF9jZXJ0X3NuPVwiXCQob3BlbnNzbCB4NTA5IC1pbiBcIlwkQ1VSUkVOVF9DRVJUX0ZJTEVcIiAtbm9vdXQgLXNlcmlhbCB8IGF3ayAtRj0gJ3twcmludCBcJDJ9JylcIgogIGlmIFtbICEgLXogXCRuZXdfY2VydF9zbiBdXSAmJiBbWyBcJG5ld19jZXJ0X3NuICE9IFwiXCRjdXJyZW50X2NlcnRfc25cIiBdXTsgdGhlbgogICAgZWNobyB1cGRhdGluZyBjZXJ0aWZpY2F0ZSBmb3IgXCRDT01QT05FTlQKICAgIGNobW9kIDA2MDAgXCRORVdfQ0VSVF9GSUxFCiAgICBtdiBcJE5FV19DRVJUX0ZJTEUgXCRDVVJSRU5UX0NFUlRfRklMRQogIGZpCmVsc2UKICBlY2hvIEZhaWxlZCB0byByZWZyZXNoIGNlcnRpZmljYXRlIGZvciBcJENPTVBPTkVOVCAmJiBleGl0IDEKZmkiCgogICAgd3JpdGVfZmlsZSBkb3dubG9hZF9jcmVkc19zY3JpcHRfZmlsZW5hbWUgZG93bmxvYWRfY3JlZHNfc2NyaXB0X2ZpbGUgdHJ1ZQoKICAgIGNobW9kIHUreCAvdXNyL2xvY2FsL2Jpbi9kb3dubG9hZC1jcmVkZW50aWFscy5zaAoKICAgIHN5c3RlbWN0bCBlbmFibGUgZG93bmxvYWQtbWRzZC1jcmVkZW50aWFscy50aW1lcgogICAgc3lzdGVtY3RsIGVuYWJsZSBkb3dubG9hZC1tZG0tY3JlZGVudGlhbHMudGltZXIKCiAgICAvdXNyL2xvY2FsL2Jpbi9kb3dubG9hZC1jcmVkZW50aWFscy5zaCBtZHNkCiAgICAvdXNyL2xvY2FsL2Jpbi9kb3dubG9hZC1jcmVkZW50aWFscy5zaCBtZG0KCiAgICBsb2NhbCAtciBNRFNEQ0VSVElGSUNBVEVTQU49IiQob3BlbnNzbCB4NTA5IC1pbiAvdmFyL2xpYi93YWFnZW50L01pY3Jvc29mdC5BenVyZS5LZXlWYXVsdC5TdG9yZS9tZHNkLnBlbSAtbm9vdXQgLXN1YmplY3QgfCBzZWQgLWUgJ3MvLipDTiA9IC8vJykiCiAgICBsb2NhbCAtciB3YXRjaF9tZG1fY3JlZHNfc2VydmljZV9maWxlbmFtZT0iL2V0Yy9zeXN0ZW1kL3N5c3RlbS93YXRjaC1tZG0tY3JlZGVudGlhbHMuc2VydmljZSIKICAgIGxvY2FsIC1yIHdhdGNoX21kbV9jcmVkc19zZXJ2aWNlX2ZpbGU9IltVbml0XQpEZXNjcmlwdGlvbj1XYXRjaCBmb3IgY2hhbmdlcyBpbiBtZG0ucGVtIGFuZCByZXN0YXJ0cyB0aGUgbWRtIHNlcnZpY2UKCltTZXJ2aWNlXQpUeXBlPW9uZXNob3QKRXhlY1N0YXJ0PS91c3IvYmluL3N5c3RlbWN0bCByZXN0YXJ0IG1kbS5zZXJ2aWNlCgpbSW5zdGFsbF0KV2FudGVkQnk9bXVsdGktdXNlci50YXJnZXQiCgogICAgd3JpdGVfZmlsZSB3YXRjaF9tZG1fY3JlZHNfc2VydmljZV9maWxlbmFtZSB3YXRjaF9tZG1fY3JlZHNfc2VydmljZV9maWxlIHRydWUKCiAgICBsb2NhbCAtciB3YXRjaF9tZG1fY3JlZHNfcGF0aF9maWxlbmFtZT0nL2V0Yy9zeXN0ZW1kL3N5c3RlbS93YXRjaC1tZG0tY3JlZGVudGlhbHMucGF0aCcKICAgIGxvY2FsIC1yIHdhdGNoX21kbV9jcmVkc19wYXRoX2ZpbGU9J1tQYXRoXQpQYXRoTW9kaWZpZWQ9L2V0Yy9tZG0ucGVtCgpbSW5zdGFsbF0KV2FudGVkQnk9bXVsdGktdXNlci50YXJnZXQnCgogICAgd3JpdGVfZmlsZSB3YXRjaF9tZG1fY3JlZHNfcGF0aF9maWxlbmFtZSB3YXRjaF9tZG1fY3JlZHNfcGF0aF9maWxlIHRydWUKCiAgICBsb2NhbCAtciB3YXRjaF9tZG1fY3JlZHM9J3dhdGNoLW1kbS1jcmVkZW50aWFscy5wYXRoJwogICAgc3lzdGVtY3RsIGVuYWJsZSAiJHdhdGNoX21kbV9jcmVkcyIgfHwgYWJvcnQgImZhaWxlZCB0byBlbmFibGUgJHdhdGNoX21kbV9jcmVkcyIKICAgIHN5c3RlbWN0bCBzdGFydCAiJHdhdGNoX21kbV9jcmVkcyIgfHwgYWJvcnQgImZhaWxlZCB0byBzdGFydCAkd2F0Y2hfbWRtX2NyZWRzIgp9CgojIGNvbmZpZ3VyZV9zZXJ2aWNlX2Fyb19ycApjb25maWd1cmVfc2VydmljZV9hcm9fcnAoKSB7CiAgICBsb2cgInN0YXJ0aW5nIgoKICAgIGxvY2FsIC1yIGFyb19ycF9jb25mX2ZpbGVuYW1lPScvZXRjL3N5c2NvbmZpZy9hcm8tcnAnCiAgICBsb2NhbCAtciBhcm9fcnBfY29uZl9maWxlPSJBQ1JfUkVTT1VSQ0VfSUQ9JyRBQ1JSRVNPVVJDRUlEJwpBRE1JTl9BUElfQ0xJRU5UX0NFUlRfQ09NTU9OX05BTUU9JyRBRE1JTkFQSUNMSUVOVENFUlRDT01NT05OQU1FJwpBUk1fQVBJX0NMSUVOVF9DRVJUX0NPTU1PTl9OQU1FPSckQVJNQVBJQ0xJRU5UQ0VSVENPTU1PTk5BTUUnCkFaVVJFX0FSTV9DTElFTlRfSUQ9JyRBUk1DTElFTlRJRCcKQVpVUkVfRlBfQ0xJRU5UX0lEPSckRlBDTElFTlRJRCcKQVpVUkVfRlBfU0VSVklDRV9QUklOQ0lQQUxfSUQ9JyRGUFNFUlZJQ0VQUklOQ0lQQUxJRCcKQklMTElOR19FMkVfU1RPUkFHRV9BQ0NPVU5UX0lEPSckQklMTElOR0UyRVNUT1JBR0VBQ0NPVU5USUQnCkNMVVNURVJfTURNX0FDQ09VTlQ9JyRDTFVTVEVSTURNQUNDT1VOVCcKQ0xVU1RFUl9NRE1fTkFNRVNQQUNFPVJQCkNMVVNURVJfTURTRF9BQ0NPVU5UPSckQ0xVU1RFUk1EU0RBQ0NPVU5UJwpDTFVTVEVSX01EU0RfQ09ORklHX1ZFUlNJT049JyRDTFVTVEVSTURTRENPTkZJR1ZFUlNJT04nCkNMVVNURVJfTURTRF9OQU1FU1BBQ0U9JyRDTFVTVEVSTURTRE5BTUVTUEFDRScKREFUQUJBU0VfQUNDT1VOVF9OQU1FPSckREFUQUJBU0VBQ0NPVU5UTkFNRScKRE9NQUlOX05BTUU9JyRMT0NBVElPTi4kQ0xVU1RFUlBBUkVOVERPTUFJTk5BTUUnCkdBVEVXQVlfRE9NQUlOUz0nJEdBVEVXQVlET01BSU5TJwpHQVRFV0FZX1JFU09VUkNFR1JPVVA9JyRHQVRFV0FZUkVTT1VSQ0VHUk9VUE5BTUUnCktFWVZBVUxUX1BSRUZJWD0nJEtFWVZBVUxUUFJFRklYJwpNRE1fQUNDT1VOVD0nJFJQTURNQUNDT1VOVCcKTURNX05BTUVTUEFDRT1SUApNRFNEX0VOVklST05NRU5UPSckTURTREVOVklST05NRU5UJwpSUF9GRUFUVVJFUz0nJFJQRkVBVFVSRVMnClJQSU1BR0U9JyRSUElNQUdFJwpBUk9fSU5TVEFMTF9WSUFfSElWRT0nJENMVVNURVJTSU5TVEFMTFZJQUhJVkUnCkFST19ISVZFX0RFRkFVTFRfSU5TVEFMTEVSX1BVTExTUEVDPSckQ0xVU1RFUkRFRkFVTFRJTlNUQUxMRVJQVUxMU1BFQycKQVJPX0FET1BUX0JZX0hJVkU9JyRDTFVTVEVSU0FET1BUQllISVZFJwpVU0VfQ0hFQ0tBQ0NFU1M9JyRVU0VDSEVDS0FDQ0VTUyciCgogICAgd3JpdGVfZmlsZSBhcm9fcnBfY29uZl9maWxlbmFtZSBhcm9fcnBfY29uZl9maWxlIHRydWUKCiAgICBsb2NhbCAtciBhcm9fcnBfc2VydmljZV9maWxlbmFtZT0nL2V0Yy9zeXN0ZW1kL3N5c3RlbS9hcm8tcnAuc2VydmljZScKICAgIGxvY2FsIC1yIGFyb19ycF9zZXJ2aWNlX2ZpbGU9IltVbml0XQpBZnRlcj1uZXR3b3JrLW9ubGluZS50YXJnZXQKV2FudHM9bmV0d29yay1vbmxpbmUudGFyZ2V0CgpbU2VydmljZV0KRW52aXJvbm1lbnRGaWxlPS9ldGMvc3lzY29uZmlnL2Fyby1ycApFeGVjU3RhcnRQcmU9LS91c3IvYmluL2RvY2tlciBybSAtZiAlTgpFeGVjU3RhcnQ9L3Vzci9iaW4vZG9ja2VyIHJ1biBcCiAgLS1ob3N0bmFtZSAlSCBcCiAgLS1uYW1lICVOIFwKICAtLXJtIFwKICAtLWNhcC1kcm9wIG5ldF9yYXcgXAogIC1lIEFDUl9SRVNPVVJDRV9JRCBcCiAgLWUgQURNSU5fQVBJX0NMSUVOVF9DRVJUX0NPTU1PTl9OQU1FIFwKICAtZSBBUk1fQVBJX0NMSUVOVF9DRVJUX0NPTU1PTl9OQU1FIFwKICAtZSBBWlVSRV9BUk1fQ0xJRU5UX0lEIFwKICAtZSBBWlVSRV9GUF9DTElFTlRfSUQgXAogIC1lIEJJTExJTkdfRTJFX1NUT1JBR0VfQUNDT1VOVF9JRCBcCiAgLWUgQ0xVU1RFUl9NRE1fQUNDT1VOVCBcCiAgLWUgQ0xVU1RFUl9NRE1fTkFNRVNQQUNFIFwKICAtZSBDTFVTVEVSX01EU0RfQUNDT1VOVCBcCiAgLWUgQ0xVU1RFUl9NRFNEX0NPTkZJR19WRVJTSU9OIFwKICAtZSBDTFVTVEVSX01EU0RfTkFNRVNQQUNFIFwKICAtZSBEQVRBQkFTRV9BQ0NPVU5UX05BTUUgXAogIC1lIERPTUFJTl9OQU1FIFwKICAtZSBHQVRFV0FZX0RPTUFJTlMgXAogIC1lIEdBVEVXQVlfUkVTT1VSQ0VHUk9VUCBcCiAgLWUgS0VZVkFVTFRfUFJFRklYIFwKICAtZSBNRE1fQUNDT1VOVCBcCiAgLWUgTURNX05BTUVTUEFDRSBcCiAgLWUgTURTRF9FTlZJUk9OTUVOVCBcCiAgLWUgUlBfRkVBVFVSRVMgXAogIC1lIEFST19JTlNUQUxMX1ZJQV9ISVZFIFwKICAtZSBBUk9fSElWRV9ERUZBVUxUX0lOU1RBTExFUl9QVUxMU1BFQyBcCiAgLWUgQVJPX0FET1BUX0JZX0hJVkUgXAogIC1lIFVTRV9DSEVDS0FDQ0VTUyBcCiAgLW0gMmcgXAogIC1wIDQ0Mzo4NDQzIFwKICAtdiAvZXRjL2Fyby1ycDovZXRjL2Fyby1ycCBcCiAgLXYgL3J1bi9zeXN0ZW1kL2pvdXJuYWw6L3J1bi9zeXN0ZW1kL2pvdXJuYWwgXAogIC12IC92YXIvZXR3Oi92YXIvZXR3OnogXAogICRSUElNQUdFIFwKICBycApFeGVjU3RvcD0vdXNyL2Jpbi9kb2NrZXIgc3RvcCAtdCAzNjAwICVOClRpbWVvdXRTdG9wU2VjPTM2MDAKUmVzdGFydD1hbHdheXMKUmVzdGFydFNlYz0xClN0YXJ0TGltaXRJbnRlcnZhbD0wCgpbSW5zdGFsbF0KV2FudGVkQnk9bXVsdGktdXNlci50YXJnZXQiCgogICAgd3JpdGVfZmlsZSBhcm9fcnBfc2VydmljZV9maWxlbmFtZSBhcm9fcnBfc2VydmljZV9maWxlIHRydWUKfQoKIyBjb25maWd1cmVfc2VydmljZV9hcm9fZGJ0b2tlbgpjb25maWd1cmVfc2VydmljZV9hcm9fZGJ0b2tlbigpIHsKICAgIGxvZyAic3RhcnRpbmciCgogICAgbG9jYWwgLXIgYXJvX2RidG9rZW5fc2VydmljZV9jb25mX2ZpbGVuYW1lPScvZXRjL3N5c2NvbmZpZy9hcm8tZGJ0b2tlbicKICAgIGxvY2FsIC1yIGFyb19kYnRva2VuX3NlcnZpY2VfY29uZl9maWxlPSJEQVRBQkFTRV9BQ0NPVU5UX05BTUU9JyREQVRBQkFTRUFDQ09VTlROQU1FJwpBWlVSRV9EQlRPS0VOX0NMSUVOVF9JRD0nJERCVE9LRU5DTElFTlRJRCcKQVpVUkVfR0FURVdBWV9TRVJWSUNFX1BSSU5DSVBBTF9JRD0nJEdBVEVXQVlTRVJWSUNFUFJJTkNJUEFMSUQnCktFWVZBVUxUX1BSRUZJWD0nJEtFWVZBVUxUUFJFRklYJwpNRE1fQUNDT1VOVD0nJFJQTURNQUNDT1VOVCcKTURNX05BTUVTUEFDRT1EQlRva2VuClJQSU1BR0U9JyRSUElNQUdFJyIKCiAgICB3cml0ZV9maWxlIGFyb19kYnRva2VuX3NlcnZpY2VfY29uZl9maWxlbmFtZSBhcm9fZGJ0b2tlbl9zZXJ2aWNlX2NvbmZfZmlsZSB0cnVlCgogICAgbG9jYWwgLXIgYXJvX2RidG9rZW5fc2VydmljZV9maWxlbmFtZT0nL2V0Yy9zeXN0ZW1kL3N5c3RlbS9hcm8tZGJ0b2tlbi5zZXJ2aWNlJwogICAgbG9jYWwgLXIgYXJvX2RidG9rZW5fc2VydmljZV9maWxlPSJbVW5pdF0KQWZ0ZXI9bmV0d29yay1vbmxpbmUudGFyZ2V0CldhbnRzPW5ldHdvcmstb25saW5lLnRhcmdldAoKW1NlcnZpY2VdCkVudmlyb25tZW50RmlsZT0vZXRjL3N5c2NvbmZpZy9hcm8tZGJ0b2tlbgpFeGVjU3RhcnRQcmU9LS91c3IvYmluL2RvY2tlciBybSAtZiAlTgpFeGVjU3RhcnQ9L3Vzci9iaW4vZG9ja2VyIHJ1biBcCiAgLS1ob3N0bmFtZSAlSCBcCiAgLS1uYW1lICVOIFwKICAtLXJtIFwKICAtLWNhcC1kcm9wIG5ldF9yYXcgXAogIC1lIEFaVVJFX0dBVEVXQVlfU0VSVklDRV9QUklOQ0lQQUxfSUQgXAogIC1lIERBVEFCQVNFX0FDQ09VTlRfTkFNRSBcCiAgLWUgQVpVUkVfREJUT0tFTl9DTElFTlRfSUQgXAogIC1lIEtFWVZBVUxUX1BSRUZJWCBcCiAgLWUgTURNX0FDQ09VTlQgXAogIC1lIE1ETV9OQU1FU1BBQ0UgXAogIC1tIDJnIFwKICAtcCA0NDU6ODQ0NSBcCiAgLXYgL3J1bi9zeXN0ZW1kL2pvdXJuYWw6L3J1bi9zeXN0ZW1kL2pvdXJuYWwgXAogIC12IC92YXIvZXR3Oi92YXIvZXR3OnogXAogICRSUElNQUdFIFwKICBkYnRva2VuCkV4ZWNTdG9wPS91c3IvYmluL2RvY2tlciBzdG9wIC10IDM2MDAgJU4KVGltZW91dFN0b3BTZWM9MzYwMApSZXN0YXJ0PWFsd2F5cwpSZXN0YXJ0U2VjPTEKU3RhcnRMaW1pdEludGVydmFsPTAKCltJbnN0YWxsXQpXYW50ZWRCeT1tdWx0aS11c2VyLnRhcmdldCIKCiAgICB3cml0ZV9maWxlIGFyb19kYnRva2VuX3NlcnZpY2VfZmlsZW5hbWUgYXJvX2RidG9rZW5fc2VydmljZV9maWxlIHRydWUKfQoKIyBjb25maWd1cmVfc2VydmljZV9hcm9fbW9uaXRvcgpjb25maWd1cmVfc2VydmljZV9hcm9fbW9uaXRvcigpIHsKICAgIGxvZyAic3RhcnRpbmciCiAgICBsb2cgImNvbmZpZ3VyaW5nIGFyby1tb25pdG9yIHNlcnZpY2UiCgogICAgIyBET01BSU5fTkFNRSwgQ0xVU1RFUl9NRFNEX0FDQ09VTlQsIENMVVNURVJfTURTRF9DT05GSUdfVkVSU0lPTiwgR0FURVdBWV9ET01BSU5TLCBHQVRFV0FZX1JFU09VUkNFR1JPVVAsIE1EU0RfRU5WSVJPTk1FTlQgQ0xVU1RFUl9NRFNEX05BTUVTUEFDRQogICAgIyBhcmUgbm90IHVzZWQsIGJ1dCBjYW4ndCBlYXNpbHkgYmUgcmVmYWN0b3JlZCBvdXQuIFNob3VsZCBiZSByZXZpc2l0ZWQgaW4gdGhlIGZ1dHVyZS4KICAgIGxvY2FsIC1yIGFyb19tb25pdG9yX3NlcnZpY2VfY29uZl9maWxlbmFtZT0nL2V0Yy9zeXNjb25maWcvYXJvLW1vbml0b3InCiAgICBsb2NhbCAtciBhcm9fbW9uaXRvcl9zZXJ2aWNlX2NvbmZfZmlsZT0iQVpVUkVfRlBfQ0xJRU5UX0lEPSckRlBDTElFTlRJRCcKRE9NQUlOX05BTUU9JyRMT0NBVElPTi4kQ0xVU1RFUlBBUkVOVERPTUFJTk5BTUUnCkNMVVNURVJfTURTRF9BQ0NPVU5UPSckQ0xVU1RFUk1EU0RBQ0NPVU5UJwpDTFVTVEVSX01EU0RfQ09ORklHX1ZFUlNJT049JyRDTFVTVEVSTURTRENPTkZJR1ZFUlNJT04nCkdBVEVXQVlfRE9NQUlOUz0nJEdBVEVXQVlET01BSU5TJwpHQVRFV0FZX1JFU09VUkNFR1JPVVA9JyRHQVRFV0FZUkVTT1VSQ0VHUk9VUE5BTUUnCk1EU0RfRU5WSVJPTk1FTlQ9JyRNRFNERU5WSVJPTk1FTlQnCkNMVVNURVJfTURTRF9OQU1FU1BBQ0U9JyRDTFVTVEVSTURTRE5BTUVTUEFDRScKQ0xVU1RFUl9NRE1fQUNDT1VOVD0nJENMVVNURVJNRE1BQ0NPVU5UJwpDTFVTVEVSX01ETV9OQU1FU1BBQ0U9QkJNCkRBVEFCQVNFX0FDQ09VTlRfTkFNRT0nJERBVEFCQVNFQUNDT1VOVE5BTUUnCktFWVZBVUxUX1BSRUZJWD0nJEtFWVZBVUxUUFJFRklYJwpNRE1fQUNDT1VOVD0nJFJQTURNQUNDT1VOVCcKTURNX05BTUVTUEFDRT1CQk0KUlBJTUFHRT0nJFJQSU1BR0UnIgoKICAgIHdyaXRlX2ZpbGUgYXJvX21vbml0b3Jfc2VydmljZV9jb25mX2ZpbGVuYW1lIGFyb19tb25pdG9yX3NlcnZpY2VfY29uZl9maWxlIHRydWUKCiAgICBsb2NhbCAtciBhcm9fbW9uaXRvcl9zZXJ2aWNlX2ZpbGVuYW1lPScvZXRjL3N5c3RlbWQvc3lzdGVtL2Fyby1tb25pdG9yLnNlcnZpY2UnCiAgICBsb2NhbCAtciBhcm9fbW9uaXRvcl9zZXJ2aWNlX2ZpbGU9IltVbml0XQpBZnRlcj1uZXR3b3JrLW9ubGluZS50YXJnZXQKV2FudHM9bmV0d29yay1vbmxpbmUudGFyZ2V0CgpbU2VydmljZV0KRW52aXJvbm1lbnRGaWxlPS9ldGMvc3lzY29uZmlnL2Fyby1tb25pdG9yCkV4ZWNTdGFydFByZT0tL3Vzci9iaW4vZG9ja2VyIHJtIC1mICVOCkV4ZWNTdGFydD0vdXNyL2Jpbi9kb2NrZXIgcnVuIFwKICAtLWhvc3RuYW1lICVIIFwKICAtLW5hbWUgJU4gXAogIC0tcm0gXAogIC0tY2FwLWRyb3AgbmV0X3JhdyBcCiAgLWUgQVpVUkVfRlBfQ0xJRU5UX0lEIFwKICAtZSBET01BSU5fTkFNRSBcCiAgLWUgQ0xVU1RFUl9NRFNEX0FDQ09VTlQgXAogIC1lIENMVVNURVJfTURTRF9DT05GSUdfVkVSU0lPTiBcCiAgLWUgR0FURVdBWV9ET01BSU5TIFwKICAtZSBHQVRFV0FZX1JFU09VUkNFR1JPVVAgXAogIC1lIE1EU0RfRU5WSVJPTk1FTlQgXAogIC1lIENMVVNURVJfTURTRF9OQU1FU1BBQ0UgXAogIC1lIENMVVNURVJfTURNX0FDQ09VTlQgXAogIC1lIENMVVNURVJfTURNX05BTUVTUEFDRSBcCiAgLWUgREFUQUJBU0VfQUNDT1VOVF9OQU1FIFwKICAtZSBLRVlWQVVMVF9QUkVGSVggXAogIC1lIE1ETV9BQ0NPVU5UIFwKICAtZSBNRE1fTkFNRVNQQUNFIFwKICAtbSAyLjVnIFwKICAtdiAvcnVuL3N5c3RlbWQvam91cm5hbDovcnVuL3N5c3RlbWQvam91cm5hbCBcCiAgLXYgL3Zhci9ldHc6L3Zhci9ldHc6eiBcCiAgJFJQSU1BR0UgXAogIG1vbml0b3IKUmVzdGFydD1hbHdheXMKUmVzdGFydFNlYz0xClN0YXJ0TGltaXRJbnRlcnZhbD0wCgpbSW5zdGFsbF0KV2FudGVkQnk9bXVsdGktdXNlci50YXJnZXQiCgogICAgd3JpdGVfZmlsZSBhcm9fbW9uaXRvcl9zZXJ2aWNlX2ZpbGVuYW1lIGFyb19tb25pdG9yX3NlcnZpY2VfZmlsZSB0cnVlCn0KCiMgY29uZmlndXJlX3NlcnZpY2VfYXJvX3BvcnRhbApjb25maWd1cmVfc2VydmljZV9hcm9fcG9ydGFsKCkgewogICAgbG9nICJzdGFydGluZyIKCiAgICBsb2NhbCAtciBhcm9fcG9ydGFsX3NlcnZpY2VfY29uZl9maWxlbmFtZT0nL2V0Yy9zeXNjb25maWcvYXJvLXBvcnRhbCcKICAgIGxvY2FsIC1yIGFyb19wb3J0YWxfc2VydmljZV9jb25mX2ZpbGU9IkFaVVJFX1BPUlRBTF9BQ0NFU1NfR1JPVVBfSURTPSckUE9SVEFMQUNDRVNTR1JPVVBJRFMnCkFaVVJFX1BPUlRBTF9DTElFTlRfSUQ9JyRQT1JUQUxDTElFTlRJRCcKQVpVUkVfUE9SVEFMX0VMRVZBVEVEX0dST1VQX0lEUz0nJFBPUlRBTEVMRVZBVEVER1JPVVBJRFMnCkRBVEFCQVNFX0FDQ09VTlRfTkFNRT0nJERBVEFCQVNFQUNDT1VOVE5BTUUnCktFWVZBVUxUX1BSRUZJWD0nJEtFWVZBVUxUUFJFRklYJwpNRE1fQUNDT1VOVD0nJFJQTURNQUNDT1VOVCcKTURNX05BTUVTUEFDRT1Qb3J0YWwKUE9SVEFMX0hPU1ROQU1FPSckTE9DQVRJT04uYWRtaW4uJFJQUEFSRU5URE9NQUlOTkFNRScKUlBJTUFHRT0nJFJQSU1BR0UnIgoKICAgIHdyaXRlX2ZpbGUgYXJvX3BvcnRhbF9zZXJ2aWNlX2NvbmZfZmlsZW5hbWUgYXJvX3BvcnRhbF9zZXJ2aWNlX2NvbmZfZmlsZSB0cnVlCgogICAgbG9jYWwgLXIgYXJvX3BvcnRhbF9zZXJ2aWNlX2ZpbGVuYW1lPScvZXRjL3N5c3RlbWQvc3lzdGVtL2Fyby1wb3J0YWwuc2VydmljZScKICAgIGxvY2FsIC1yIGFyb19wb3J0YWxfc2VydmljZV9maWxlPSJbVW5pdF0KQWZ0ZXI9bmV0d29yay1vbmxpbmUudGFyZ2V0CldhbnRzPW5ldHdvcmstb25saW5lLnRhcmdldApTdGFydExpbWl0SW50ZXJ2YWw9MAoKW1NlcnZpY2VdCkVudmlyb25tZW50RmlsZT0vZXRjL3N5c2NvbmZpZy9hcm8tcG9ydGFsCkV4ZWNTdGFydFByZT0tL3Vzci9iaW4vZG9ja2VyIHJtIC1mICVOCkV4ZWNTdGFydD0vdXNyL2Jpbi9kb2NrZXIgcnVuIFwKICAtLWhvc3RuYW1lICVIIFwKICAtLW5hbWUgJU4gXAogIC0tcm0gXAogIC0tY2FwLWRyb3AgbmV0X3JhdyBcCiAgLWUgQVpVUkVfUE9SVEFMX0FDQ0VTU19HUk9VUF9JRFMgXAogIC1lIEFaVVJFX1BPUlRBTF9DTElFTlRfSUQgXAogIC1lIEFaVVJFX1BPUlRBTF9FTEVWQVRFRF9HUk9VUF9JRFMgXAogIC1lIERBVEFCQVNFX0FDQ09VTlRfTkFNRSBcCiAgLWUgS0VZVkFVTFRfUFJFRklYIFwKICAtZSBNRE1fQUNDT1VOVCBcCiAgLWUgTURNX05BTUVTUEFDRSBcCiAgLWUgUE9SVEFMX0hPU1ROQU1FIFwKICAtbSAyZyBcCiAgLXAgNDQ0Ojg0NDQgXAogIC1wIDIyMjI6MjIyMiBcCiAgLXYgL3J1bi9zeXN0ZW1kL2pvdXJuYWw6L3J1bi9zeXN0ZW1kL2pvdXJuYWwgXAogIC12IC92YXIvZXR3Oi92YXIvZXR3OnogXAogICRSUElNQUdFIFwKICBwb3J0YWwKUmVzdGFydD1hbHdheXMKUmVzdGFydFNlYz0xCgpbSW5zdGFsbF0KV2FudGVkQnk9bXVsdGktdXNlci50YXJnZXQiCgogICAgd3JpdGVfZmlsZSBhcm9fcG9ydGFsX3NlcnZpY2VfZmlsZW5hbWUgYXJvX3BvcnRhbF9zZXJ2aWNlX2ZpbGUgdHJ1ZQp9CgojIGNvbmZpZ3VyZV9zZXJ2aWNlX21kc2QKY29uZmlndXJlX3NlcnZpY2VfbWRzZCgpIHsKICAgIGxvZyAic3RhcnRpbmciCgogICAgbG9jYWwgLXIgbWRzZF9zZXJ2aWNlX2Rpcj0iL2V0Yy9zeXN0ZW1kL3N5c3RlbS9tZHNkLnNlcnZpY2UuZCIKICAgIG1rZGlyIC1wICIkbWRzZF9zZXJ2aWNlX2RpciIKCiAgICBsb2NhbCAtciBtZHNkX292ZXJyaWRlX2NvbmZfZmlsZW5hbWU9IiRtZHNkX3NlcnZpY2VfZGlyL292ZXJyaWRlLmNvbmYiCiAgICBsb2NhbCAtciBtZHNkX292ZXJyaWRlX2NvbmZfZmlsZT0iW1VuaXRdCkFmdGVyPW5ldHdvcmstb25saW5lLnRhcmdldCIKCiAgICB3cml0ZV9maWxlIG1kc2Rfb3ZlcnJpZGVfY29uZl9maWxlbmFtZSBtZHNkX292ZXJyaWRlX2NvbmZfZmlsZSB0cnVlCgogICAgbG9jYWwgLXIgZGVmYXVsdF9tZHNkX2ZpbGVuYW1lPSIvZXRjL2RlZmF1bHQvbWRzZCIKICAgIGxvY2FsIC1yIGRlZmF1bHRfbWRzZF9maWxlPSJNRFNEX1JPTEVfUFJFRklYPS92YXIvcnVuL21kc2QvZGVmYXVsdApNRFNEX09QVElPTlM9XCItQSAtZCAtciBcJE1EU0RfUk9MRV9QUkVGSVhcIgoKZXhwb3J0IE1PTklUT1JJTkdfR0NTX0VOVklST05NRU5UPSckTURTREVOVklST05NRU5UJwpleHBvcnQgTU9OSVRPUklOR19HQ1NfQUNDT1VOVD0nJFJQTURTREFDQ09VTlQnCmV4cG9ydCBNT05JVE9SSU5HX0dDU19SRUdJT049JyRMT0NBVElPTicKZXhwb3J0IE1PTklUT1JJTkdfR0NTX0FVVEhfSURfVFlQRT1BdXRoS2V5VmF1bHQKZXhwb3J0IE1PTklUT1JJTkdfR0NTX0FVVEhfSUQ9JyRNRFNEQ0VSVElGSUNBVEVTQU4nCmV4cG9ydCBNT05JVE9SSU5HX0dDU19OQU1FU1BBQ0U9JyRSUE1EU0ROQU1FU1BBQ0UnCmV4cG9ydCBNT05JVE9SSU5HX0NPTkZJR19WRVJTSU9OPSckUlBNRFNEQ09ORklHVkVSU0lPTicKZXhwb3J0IE1PTklUT1JJTkdfVVNFX0dFTkVWQV9DT05GSUdfU0VSVklDRT10cnVlCgpleHBvcnQgTU9OSVRPUklOR19URU5BTlQ9JyRMT0NBVElPTicKZXhwb3J0IE1PTklUT1JJTkdfUk9MRT1ycApleHBvcnQgTU9OSVRPUklOR19ST0xFX0lOU1RBTkNFPVwiJChob3N0bmFtZSlcIgoKZXhwb3J0IE1EU0RfTVNHUEFDS19TT1JUX0NPTFVNTlM9MVwiIgoKICAgIHdyaXRlX2ZpbGUgZGVmYXVsdF9tZHNkX2ZpbGVuYW1lIGRlZmF1bHRfbWRzZF9maWxlIHRydWUKCn0KCiMgcnVuX2F6c2VjZF9jb25maWdfc2NhbgpydW5fYXpzZWNkX2NvbmZpZ19zY2FuKCkgewogICAgbG9nICJzdGFydGluZyIKCiAgICBsb2NhbCAtYXIgY29uZmlncz0oCiAgICAgICAgImJhc2VsaW5lIgogICAgICAgICJjbGFtYXYiCiAgICAgICAgInNvZnR3YXJlIgogICAgKQoKICAgIGxvZyAiU2Nhbm5pbmcgY29uZmlndXJhdGlvbiBmaWxlcyAke2NvbmZpZ3NbKl19IgogICAgIyBzaGVsbGNoZWNrIGRpc2FibGU9U0MyMDY4CiAgICBmb3Igc2NhbiBpbiAke2NvbmZpZ3NbQF19OyBkbwogICAgICAgIGxvZyAiU2Nhbm5pbmcgY29uZmlnIGZpbGUgJHNjYW4gbm93IgogICAgICAgIC91c3IvbG9jYWwvYmluL2F6c2VjZCBjb25maWcgLXMgIiRzY2FuIiAtZCBQMUQKICAgIGRvbmUKfQoKZXhwb3J0IEFaVVJFX0NMT1VEX05BTUU9IiR7QVpVUkVDTE9VRE5BTUU6PyJGYWlsZWQgdG8gY2Fycnkgb3ZlciB2YXJpYWJsZXMifSIKCm1haW4gIiRAIgo=')))]" + "script": "[base64(concat(base64ToString('c2V0IC1leAoK'),'ACRRESOURCEID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('acrResourceId')),''')\n','ADMINAPICLIENTCERTCOMMONNAME=$(base64 -d \u003c\u003c\u003c''',base64(parameters('adminApiClientCertCommonName')),''')\n','ARMAPICLIENTCERTCOMMONNAME=$(base64 -d \u003c\u003c\u003c''',base64(parameters('armApiClientCertCommonName')),''')\n','ARMCLIENTID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('armClientId')),''')\n','AZURECLOUDNAME=$(base64 -d \u003c\u003c\u003c''',base64(parameters('azureCloudName')),''')\n','AZURESECPACKQUALYSURL=$(base64 -d \u003c\u003c\u003c''',base64(parameters('azureSecPackQualysUrl')),''')\n','AZURESECPACKVSATENANTID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('azureSecPackVSATenantId')),''')\n','BILLINGE2ESTORAGEACCOUNTID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('billingE2EStorageAccountId')),''')\n','CLUSTERMDMACCOUNT=$(base64 -d \u003c\u003c\u003c''',base64(parameters('clusterMdmAccount')),''')\n','CLUSTERMDSDACCOUNT=$(base64 -d \u003c\u003c\u003c''',base64(parameters('clusterMdsdAccount')),''')\n','CLUSTERMDSDCONFIGVERSION=$(base64 -d \u003c\u003c\u003c''',base64(parameters('clusterMdsdConfigVersion')),''')\n','CLUSTERMDSDNAMESPACE=$(base64 -d \u003c\u003c\u003c''',base64(parameters('clusterMdsdNamespace')),''')\n','CLUSTERPARENTDOMAINNAME=$(base64 -d \u003c\u003c\u003c''',base64(parameters('clusterParentDomainName')),''')\n','DATABASEACCOUNTNAME=$(base64 -d \u003c\u003c\u003c''',base64(parameters('databaseAccountName')),''')\n','DBTOKENCLIENTID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('dbtokenClientId')),''')\n','FLUENTBITIMAGE=$(base64 -d \u003c\u003c\u003c''',base64(parameters('fluentbitImage')),''')\n','FPCLIENTID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('fpClientId')),''')\n','FPSERVICEPRINCIPALID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('fpServicePrincipalId')),''')\n','GATEWAYDOMAINS=$(base64 -d \u003c\u003c\u003c''',base64(parameters('gatewayDomains')),''')\n','GATEWAYRESOURCEGROUPNAME=$(base64 -d \u003c\u003c\u003c''',base64(parameters('gatewayResourceGroupName')),''')\n','GATEWAYSERVICEPRINCIPALID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('gatewayServicePrincipalId')),''')\n','KEYVAULTDNSSUFFIX=$(base64 -d \u003c\u003c\u003c''',base64(parameters('keyvaultDNSSuffix')),''')\n','KEYVAULTPREFIX=$(base64 -d \u003c\u003c\u003c''',base64(parameters('keyvaultPrefix')),''')\n','MDMFRONTENDURL=$(base64 -d \u003c\u003c\u003c''',base64(parameters('mdmFrontendUrl')),''')\n','MDSDENVIRONMENT=$(base64 -d \u003c\u003c\u003c''',base64(parameters('mdsdEnvironment')),''')\n','PORTALACCESSGROUPIDS=$(base64 -d \u003c\u003c\u003c''',base64(parameters('portalAccessGroupIds')),''')\n','PORTALCLIENTID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('portalClientId')),''')\n','PORTALELEVATEDGROUPIDS=$(base64 -d \u003c\u003c\u003c''',base64(parameters('portalElevatedGroupIds')),''')\n','RPFEATURES=$(base64 -d \u003c\u003c\u003c''',base64(parameters('rpFeatures')),''')\n','RPIMAGE=$(base64 -d \u003c\u003c\u003c''',base64(parameters('rpImage')),''')\n','RPMDMACCOUNT=$(base64 -d \u003c\u003c\u003c''',base64(parameters('rpMdmAccount')),''')\n','RPMDSDACCOUNT=$(base64 -d \u003c\u003c\u003c''',base64(parameters('rpMdsdAccount')),''')\n','RPMDSDCONFIGVERSION=$(base64 -d \u003c\u003c\u003c''',base64(parameters('rpMdsdConfigVersion')),''')\n','RPMDSDNAMESPACE=$(base64 -d \u003c\u003c\u003c''',base64(parameters('rpMdsdNamespace')),''')\n','RPPARENTDOMAINNAME=$(base64 -d \u003c\u003c\u003c''',base64(parameters('rpParentDomainName')),''')\n','CLUSTERSINSTALLVIAHIVE=$(base64 -d \u003c\u003c\u003c''',base64(parameters('clustersInstallViaHive')),''')\n','CLUSTERSADOPTBYHIVE=$(base64 -d \u003c\u003c\u003c''',base64(parameters('clustersAdoptByHive')),''')\n','CLUSTERDEFAULTINSTALLERPULLSPEC=$(base64 -d \u003c\u003c\u003c''',base64(parameters('clusterDefaultInstallerPullspec')),''')\n','USECHECKACCESS=$(base64 -d \u003c\u003c\u003c''',base64(parameters('useCheckAccess')),''')\n','ADMINAPICABUNDLE=''',parameters('adminApiCaBundle'),'''\n','ARMAPICABUNDLE=''',parameters('armApiCaBundle'),'''\n','MDMIMAGE=''/genevamdm:2.2024.328.1744-c5fb79-20240328t1935''\n','LOCATION=$(base64 -d \u003c\u003c\u003c''',base64(resourceGroup().location),''')\n','SUBSCRIPTIONID=$(base64 -d \u003c\u003c\u003c''',base64(subscription().subscriptionId),''')\n','RESOURCEGROUPNAME=$(base64 -d \u003c\u003c\u003c''',base64(resourceGroup().name),''')\n','\n',base64ToString('IyEvYmluL2Jhc2gKCnNldCAtbyBlcnJleGl0IFwKICAgIC1vIG5vdW5zZXQKCmlmIFsgIiR7REVCVUc6LWZhbHNlfSIgPT0gdHJ1ZSBdOyB0aGVuCiAgICBzZXQgLXgKZmkKCm1haW4oKSB7CiAgICAjIHRyYW5zYWN0aW9uIGF0dGVtcHQgcmV0cnkgdGltZSBpbiBzZWNvbmRzCiAgICBsb2NhbCAtcmkgcmV0cnlfd2FpdF90aW1lPTYwCgogICAgIyBzaGVsbGNoZWNrIHNvdXJjZT1jb21tb24uc2gKICAgIHNvdXJjZSBjb21tb24uc2gKCiAgICBsb2NhbCAtYXIgZXhjbHVkZV9wa2dzPSgKICAgICAgICAiLXggV0FMaW51eEFnZW50IgogICAgICAgICIteCBXQUxpbnV4QWdlbnQtdWRldiIKICAgICkKCiAgICBsb2NhbCAtcmEgcnBtX2tleXM9KAogICAgICAgIGh0dHBzOi8vZGwuZmVkb3JhcHJvamVjdC5vcmcvcHViL2VwZWwvUlBNLUdQRy1LRVktRVBFTC04CiAgICAgICAgaHR0cHM6Ly9wYWNrYWdlcy5taWNyb3NvZnQuY29tL2tleXMvbWljcm9zb2Z0LmFzYwogICAgKQoKICAgIGxvY2FsIC1yYSByZXBvX3JwbV9wa2dzPSgKICAgICAgICBodHRwczovL2RsLmZlZG9yYXByb2plY3Qub3JnL3B1Yi9lcGVsL2VwZWwtcmVsZWFzZS1sYXRlc3QtOC5ub2FyY2gucnBtCiAgICApCgogICAgbG9jYWwgLXJhIGluc3RhbGxfcGtncz0oCiAgICAgICAgY2xhbWF2CiAgICAgICAgYXpzZWMtY2xhbWF2CiAgICAgICAgYXpzZWMtbW9uaXRvcgogICAgICAgIGF6dXJlLWNsaQogICAgICAgIGF6dXJlLW1kc2QKICAgICAgICBhenVyZS1zZWN1cml0eQogICAgICAgIHBvZG1hbgogICAgICAgIHBvZG1hbi1kb2NrZXIKICAgICAgICBvcGVuc3NsLXBlcmwKICAgICAgICAjIGhhY2sgLSB3ZSBhcmUgaW5zdGFsbGluZyBweXRob24zIG9uIGhvc3RzIGR1ZSB0byBhbiBpc3N1ZSB3aXRoIEF6dXJlIExpbnV4IEV4dGVuc2lvbnMgaHR0cHM6Ly9naXRodWIuY29tL0F6dXJlL2F6dXJlLWxpbnV4LWV4dGVuc2lvbnMvcHVsbC8xNTA1CiAgICAgICAgcHl0aG9uMwogICAgKQoKICAgIE1ETUlNQUdFPSIke1JQSU1BR0UlJS8qfS8ke01ETUlNQUdFIyMqL30iCiAgICBsb2NhbCAtcmEgaW1hZ2VzPSgKICAgICAgICAiJE1ETUlNQUdFIgogICAgICAgICIkUlBJTUFHRSIKICAgICAgICAiJEZMVUVOVEJJVElNQUdFIgogICAgKQoKICAgIGxvY2FsIC1yYSBlbmFibGVfcG9ydHM9KAogICAgICAgICI0NDMvdGNwIgogICAgICAgICI0NDQvdGNwIgogICAgICAgICI0NDUvdGNwIgogICAgICAgICIyMjIyL3RjcCIKICAgICkKCiAgICBsb2NhbCAtcmEgYXJvX3NlcnZpY2VzPSgKICAgICAgICAiYXJvLWRidG9rZW4iCiAgICAgICAgImFyby1tb25pdG9yIgogICAgICAgICJhcm8tcG9ydGFsIgogICAgICAgICJhcm8tcnAiCiAgICAgICAgImF1b21zIgogICAgICAgICJhenNlY2QiCiAgICAgICAgImF6c2VjbW9uZCIKICAgICAgICAibWRzZCIKICAgICAgICAibWRtIgogICAgICAgICJjaHJvbnlkIgogICAgICAgICJmbHVlbnRiaXQiCiAgICApCgogICAgbG9jYWwgLXJhIHVzZXJfb3B0aW9ucz0oIiRAIikKICAgIHBhcnNlX3J1bl9vcHRpb25zIHVzZXJfb3B0aW9ucyBcCiAgICAgICAgICAgICAgICAgICAgICAgIHJldHJ5X3dhaXRfdGltZSBcCiAgICAgICAgICAgICAgICAgICAgICAgIGV4Y2x1ZGVfcGtncyBcCiAgICAgICAgICAgICAgICAgICAgICAgIHJwbV9rZXlzIFwKICAgICAgICAgICAgICAgICAgICAgICAgcmVwb19ycG1fcGtncyBcCiAgICAgICAgICAgICAgICAgICAgICAgIGluc3RhbGxfcGtncyBcCiAgICAgICAgICAgICAgICAgICAgICAgIGltYWdlcyBcCiAgICAgICAgICAgICAgICAgICAgICAgIGVuYWJsZV9wb3J0cyBcCiAgICAgICAgICAgICAgICAgICAgICAgIGFyb19zZXJ2aWNlcwoKICAgIGNvbmZpZ3VyZV9zc2hkCiAgICBjb25maWd1cmVfcnBtX3JlcG9zIHJldHJ5X3dhaXRfdGltZQoKICAgIGRuZl91cGRhdGVfcGtncyBleGNsdWRlX3BrZ3MgcmV0cnlfd2FpdF90aW1lCgogICAgcnBtX2ltcG9ydF9rZXlzIHJwbV9rZXlzIHJldHJ5X3dhaXRfdGltZQoKICAgIGRuZl9pbnN0YWxsX3BrZ3MgcmVwb19ycG1fcGtncyByZXRyeV93YWl0X3RpbWUKICAgIGRuZl9pbnN0YWxsX3BrZ3MgaW5zdGFsbF9wa2dzIHJldHJ5X3dhaXRfdGltZQogICAgY29uZmlndXJlX2RuZl9jcm9uX2pvYgoKICAgIGNvbmZpZ3VyZV9kaXNrX3BhcnRpdGlvbnMKICAgIGNvbmZpZ3VyZV9sb2dyb3RhdGUKICAgIGNvbmZpZ3VyZV9zZWxpbnV4CgogICAgbWtkaXIgLXAgL3Zhci9sb2cvam91cm5hbAogICAgbWtkaXIgLXAgL3Zhci9saWIvd2FhZ2VudC9NaWNyb3NvZnQuQXp1cmUuS2V5VmF1bHQuU3RvcmUKCiAgICBjb25maWd1cmVfZmlyZXdhbGxkX3J1bGVzIGVuYWJsZV9wb3J0cwoKICAgIHB1bGxfY29udGFpbmVyX2ltYWdlcyBpbWFnZXMKICAgIGNvbmZpZ3VyZV9hcm9fc2VydmljZXMKICAgIGVuYWJsZV9zZXJ2aWNlcwoKICAgIGVuYWJsZV9zZXJ2aWNlcyBhcm9fc2VydmljZXMKCiAgICByZWJvb3Rfdm0KfQoKdXNhZ2UoKSB7CiAgICBsb2NhbCAtbiBvcHRpb25zPSIkMSIKICAgIGxvZyAiJChiYXNlbmFtZSAiJDAiKSBbJG9wdGlvbnNdCiAgICAgICAgLWQgQ29uZmlndXJlIERpc2sgUGFydGl0aW9ucwogICAgICAgIC1wIENvbmZpZ3VyZSBycG0gcmVwb3NpdG9yaWVzLCBpbXBvcnQgcmVxdWlyZWQgcnBtIGtleXMsIHVwZGF0ZSAmIGluc3RhbGwgcGFja2FnZXMgd2l0aCBkbmYKICAgICAgICAtbCBDb25maWd1cmUgbG9ncm90YXRlLmNvbmYKICAgICAgICAtcyBDb25maWd1cmUgc2VsaW51eAogICAgICAgIC1yIENvbmZpZ3VyZSBzc2hkIC0gQWxsb3cgcGFzc3dvcmQgYXV0aGVudGljYWl0b24KICAgICAgICAtZiBDb25maWd1cmUgZmlyZXdhbGxkIGRlZmF1bHQgem9uZSBydWxlcwogICAgICAgIC11IENvbmZpZ3VyZSBzeXN0ZW1kIHVuaXQgZmlsZXMKICAgICAgICAtaSBQdWxsIGNvbnRhaW5lciBpbWFnZXMKCiAgICAgICAgTm90ZTogc3RlcHMgd2lsbCBiZSBleGVjdXRlZCBpbiB0aGUgb3JkZXIgdGhhdCBmbGFncyBhcmUgcHJvdmlkZWQKICAgICIKfQoKIyBwYXJzZV9ydW5fb3B0aW9ucyB0YWtlcyBhbGwgYXJndWVtZW50cyBwYXNzZWQgdG8gbWFpbiBhbmQgcGFyc2VzIHRoZW0KIyBhbGxvd2luZyBpbmRpdmlkdWFsIHN0ZXAocykgdG8gYmUgcmFuLCByYXRoZXIgdGhhbiBhbGwgc3RlcHMKIwojIFRoaXMgaXMgdXNlZnVsIGZvciBsb2NhbCB0ZXN0aW5nLCBvciBwb3NzaWJseSBtb2RpZnlpbmcgdGhlIGJvb3RzdHJhcCBleGVjdXRpb24gdmlhIGVudmlyb25tZW50IHZhcmlhYmxlcyBpbiB0aGUgZGVwbG95bWVudCBwaXBlbGluZQpwYXJzZV9ydW5fb3B0aW9ucygpIHsKICAgICMgc2hlbGxjaGVjayBkaXNhYmxlPVNDMjIwNgogICAgbG9jYWwgLW4gcnVuX29wdGlvbnM9IiQxIgogICAgbG9jYWwgLW4gcmV0cnlfdGltZT0iJDIiCiAgICBsb2NhbCAtbiBwa2dzX3RvX2V4Y2x1ZGU9IiQzIgogICAgbG9jYWwgLW4ga2V5c190b19pbXBvcnQ9IiQ0IgogICAgbG9jYWwgLW4gcnBtX3BrZ3M9IiQ1IgogICAgbG9jYWwgLW4gcGtnc190b19pbnN0YWxsPSIkNiIKICAgIGxvY2FsIC1uIGltYWdlc190b19wdWxsPSIkNyIKICAgIGxvY2FsIC1uIHBvcnRzX3RvX2VuYWJsZT0iJDgiCiAgICBsb2NhbCAtbiBzZXJ2aWNlc190b19lbmFibGU9IiQ5IgoKICAgIGlmIFsgIiR7I3J1bl9vcHRpb25zW0BdfSIgLWVxIDAgXTsgdGhlbgogICAgICAgIGxvZyAiUnVubmluZyBhbGwgc3RlcHMiCiAgICAgICAgcmV0dXJuIDAKICAgIGZpCgogICAgbG9jYWwgT1BUSU5ECiAgICBsb2NhbCAtciBhbGxvd2VkX29wdGlvbnM9ImRwbHNyZnVpIgogICAgd2hpbGUgZ2V0b3B0cyAke2FsbG93ZWRfb3B0aW9uc30gb3B0aW9uczsgZG8KICAgICAgICBjYXNlICIke3J1bl9vcHRpb25zfSIgaW4KICAgICAgICAgICAgZCkKICAgICAgICAgICAgICAgIGxvZyAiUnVubmluZyBzdGVwIGNvbmZpZ3VyZV9kaXNrX3BhcnRpdGlvbnMiCiAgICAgICAgICAgICAgICBjb25maWd1cmVfZGlza19wYXJ0aXRpb25zCiAgICAgICAgICAgICAgICA7OwogICAgICAgICAgICBwKQogICAgICAgICAgICAgICAgbG9nICJSdW5uaW5nIHN0ZXAgY29uZmlndXJlX3JwbV9yZXBvcyIKICAgICAgICAgICAgICAgIGNvbmZpZ3VyZV9ycG1fcmVwb3Mga2V5c190b19pbXBvcnQKCiAgICAgICAgICAgICAgICBsb2cgIlJ1bm5pbmcgc3RlcCBkbmZfdXBkYXRlX3BrZ3MiCiAgICAgICAgICAgICAgICBkbmZfdXBkYXRlX3BrZ3MgcGtnc190b19leGNsdWRlIHJldHJ5X3RpbWUKCiAgICAgICAgICAgICAgICBsb2cgIlJ1bm5pbmcgc3RlcCBkbmZfaW5zdGFsbF9wa2dzIHJwbV9wa2dzIgogICAgICAgICAgICAgICAgZG5mX2luc3RhbGxfcGtncyBycG1fcGtncyByZXRyeV90aW1lCgogICAgICAgICAgICAgICAgbG9nICJSdW5uaW5nIHN0ZXAgZG5mX2luc3RhbGxfcGtncyBwa2dzIgogICAgICAgICAgICAgICAgZG5mX2luc3RhbGxfcGtncyBwa2dzX3RvX2luc3RhbGwgcmV0cnlfdGltZQogICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICBsb2cgIlJ1bm5pbmcgc3RlcCBjb25maWd1cmVfZG5mX2Nyb25kX2pvYiIKICAgICAgICAgICAgICAgIGNvbmZpZ3VyZV9kbmZfY3Jvbl9qb2IKICAgICAgICAgICAgICAgIDs7CiAgICAgICAgICAgIGwpCiAgICAgICAgICAgICAgICBsb2cgIlJ1bm5pbmcgY29uZmlndXJlX2xvZ3JvdGF0ZSIKICAgICAgICAgICAgICAgIGNvbmZpZ3VyZV9sb2dyb3RhdGUKICAgICAgICAgICAgICAgIDs7CiAgICAgICAgICAgIHMpCiAgICAgICAgICAgICAgICBsb2cgIlJ1bm5pbmcgY29uZmlndXJlX3NlbGludXgiCiAgICAgICAgICAgICAgICBjb25maWd1cmVfc2VsaW51eAogICAgICAgICAgICAgICAgOzsKICAgICAgICAgICAgcikKICAgICAgICAgICAgICAgIGxvZyAiUnVubmluZyBjb25maWd1cmVfc3NoZCIKICAgICAgICAgICAgICAgIGNvbmZpZ3VyZV9zc2hkCiAgICAgICAgICAgICAgICA7OwogICAgICAgICAgICBmKQogICAgICAgICAgICAgICAgbG9nICJSdW5uaW5nIGNvbmZpZ3VyZV9maXJld2FsbGRfcnVsZXMiCiAgICAgICAgICAgICAgICBjb25maWd1cmVfZmlyZXdhbGxkX3J1bGVzIHBvcnRzX3RvX2VuYWJsZQogICAgICAgICAgICAgICAgOzsKICAgICAgICAgICAgdSkKICAgICAgICAgICAgICAgIGxvZyAiUnVubmluZyBwdWxsX2NvbnRhaW5lcl9pbWFnZXMgJiBjb25maWd1cmVfc3lzdGVtX3NlcnZpY2VzIgogICAgICAgICAgICAgICAgY29uZmlndXJlX2Fyb19zZXJ2aWNlcwogICAgICAgICAgICAgICAgZW5hYmxlX3NlcnZpY2VzIHNlcnZpY2VzX3RvX2VuYWJsZQogICAgICAgICAgICAgICAgOzsKICAgICAgICAgICAgaSkKICAgICAgICAgICAgICAgIGxvZyAiUnVubmluZyBwdWxsX2NvbnRhaW5lcl9pbWFnZXMiCiAgICAgICAgICAgICAgICBwdWxsX2NvbnRhaW5lcl9pbWFnZXMgaW1hZ2VzX3RvX3B1bGwKICAgICAgICAgICAgICAgIDs7CiAgICAgICAgICAgICopCiAgICAgICAgICAgICAgICB1c2FnZSBhbGxvd2VkX29wdGlvbnMKICAgICAgICAgICAgICAgIGFib3J0ICJVbmtvd24gb3B0aW9uIHByb3ZpZGVkIgogICAgICAgICAgICAgICAgOzsKICAgICAgICBlc2FjCiAgICBkb25lCiAgICAKICAgIGV4aXQgMAp9CgojIGNvbmZpZ3VyZV9ycG1fcmVwb3MKY29uZmlndXJlX3JwbV9yZXBvcygpIHsKICAgIGxvZyAic3RhcnRpbmciCgogICAgY29uZmlndXJlX3JodWlfcmVwbyAiJDEiCiAgICBjcmVhdGVfYXp1cmVfcnBtX3JlcG9zICIkMSIKfQoKIyBjb25maWd1cmVfZGlza19wYXJ0aXRpb25zCmNvbmZpZ3VyZV9kaXNrX3BhcnRpdGlvbnMoKSB7CiAgICBsb2cgInN0YXJ0aW5nIgogICAgbG9nICJleHRlbmRpbmcgcGFydGl0aW9uIHRhYmxlIgoKICAgICMgTGludXggYmxvY2sgZGV2aWNlcyBhcmUgaW5jb25zaXN0ZW50bHkgbmFtZWQKICAgICMgaXQncyBkaWZmaWN1bHQgdG8gdGllIHRoZSBsdm0gcHYgdG8gdGhlIHBoeXNpY2FsIGRpc2sgdXNpbmcgL2Rldi9kaXNrIGZpbGVzLCB3aGljaCBpcyB3aHkgbHZzIGlzIHVzZWQgaGVyZQogICAgcGh5c2ljYWxfZGlzaz0iJChsdnMgLW8gZGV2aWNlcyAtYSB8IGhlYWQgLW4yIHwgdGFpbCAtbjEgfCBjdXQgLWQgJyAnIC1mIDMgfCBjdXQgLWQgXCggLWYgMSB8IHRyIC1kICdbOmRpZ2l0Ol0nKSIKICAgIGdyb3dwYXJ0ICIkcGh5c2ljYWxfZGlzayIgMgoKICAgIGxvZyAiZXh0ZW5kaW5nIGZpbGVzeXN0ZW1zIgogICAgbG9nICJleHRlbmRpbmcgcm9vdCBsdm0iCiAgICBsdmV4dGVuZCAtbCArMjAlRlJFRSAvZGV2L3Jvb3R2Zy9yb290bHYKICAgIGxvZyAiZ3Jvd2luZyByb290IGZpbGVzeXN0ZW0iCiAgICB4ZnNfZ3Jvd2ZzIC8KCiAgICBsb2cgImV4dGVuZGluZyB2YXIgbHZtIgogICAgbHZleHRlbmQgLWwgKzEwMCVGUkVFIC9kZXYvcm9vdHZnL3Zhcmx2CiAgICBsb2cgImdyb3dpbmcgdmFyIGZpbGVzeXN0ZW0iCiAgICB4ZnNfZ3Jvd2ZzIC92YXIKfQoKIyBjcmVhdGVfYXp1cmVfcnBtX3JlcG9zIGNyZWF0ZXMgL2V0Yy95dW0ucmVwb3MuZC9henVyZS5yZXBvIHJlcG9zaXRvcnkgZmlsZQpjcmVhdGVfYXp1cmVfcnBtX3JlcG9zKCkgewogICAgbG9nICJzdGFydGluZyIKCiAgICBsb2NhbCAtciBhenVyZV9yZXBvX2ZpbGVuYW1lPScvZXRjL3l1bS5yZXBvcy5kL2F6dXJlLnJlcG8nCiAgICBsb2NhbCAtciBhenVyZV9yZXBvX2ZpbGU9J1thenVyZS1jbGldCm5hbWU9YXp1cmUtY2xpCmJhc2V1cmw9aHR0cHM6Ly9wYWNrYWdlcy5taWNyb3NvZnQuY29tL3l1bXJlcG9zL2F6dXJlLWNsaQplbmFibGVkPXllcwpncGdjaGVjaz15ZXMKClthenVyZWNvcmVdCm5hbWU9YXp1cmVjb3JlCmJhc2V1cmw9aHR0cHM6Ly9wYWNrYWdlcy5taWNyb3NvZnQuY29tL3l1bXJlcG9zL2F6dXJlY29yZQplbmFibGVkPXllcwpncGdjaGVjaz1ubycKCiAgICB3cml0ZV9maWxlIGF6dXJlX3JlcG9fZmlsZW5hbWUgYXp1cmVfcmVwb19maWxlIHRydWUKfQoKIyBjb25maWd1cmVfYXJvX3NlcnZpY2VzIGNyZWF0ZXMsIGNvbmZpZ3VyZXMsIGFuZCBlbmFibGVzIHRoZSBmb2xsb3dpbmcgc3lzdGVtZCBzZXJ2aWNlcyBhbmQgdGltZXJzCiMgc2VydmljZXMKIyAgIGZsdWVudGJpdAojICAgbWRtCiMgICBtZHNkCiMgICBhcnAtcnAKIyAgIGFyby1kYnRva2VuCiMgICBhcm8tbW9uaXRvcgojICAgYXJvLXBvcnRhbApjb25maWd1cmVfYXJvX3NlcnZpY2VzKCkgewogICAgY29uZmlndXJlX3NlcnZpY2VfZmx1ZW50Yml0CiAgICBjb25maWd1cmVfc2VydmljZV9tZG0KICAgIGNvbmZpZ3VyZV90aW1lcnNfbWRtX21kc2QKICAgIGNvbmZpZ3VyZV9zZXJ2aWNlX2Fyb19ycAogICAgY29uZmlndXJlX3NlcnZpY2VfYXJvX2RidG9rZW4KICAgIGNvbmZpZ3VyZV9zZXJ2aWNlX2Fyb19tb25pdG9yCiAgICBjb25maWd1cmVfc2VydmljZV9hcm9fcG9ydGFsCiAgICBjb25maWd1cmVfc2VydmljZV9tZHNkCn0KCiMgY29uZmlndXJlX3NlcnZpY2VfZmx1ZW50Yml0CmNvbmZpZ3VyZV9zZXJ2aWNlX2ZsdWVudGJpdCgpIHsKICAgIGxvZyAic3RhcnRpbmciCiAgICBsb2cgImNvbmZpZ3VyaW5nIGZsdWVudGJpdCBzZXJ2aWNlIgoKICAgIG1rZGlyIC1wIC9ldGMvZmx1ZW50Yml0LwogICAgbWtkaXIgLXAgL3Zhci9saWIvZmx1ZW50CgogICAgbG9jYWwgLXIgZmx1ZW50Yml0X2NvbmZfZmlsZW5hbWU9Jy9ldGMvZmx1ZW50Yml0L2ZsdWVudGJpdC5jb25mJwogICAgbG9jYWwgLXIgZmx1ZW50Yml0X2NvbmZfZmlsZT0iW0lOUFVUXQpOYW1lIHN5c3RlbWQKVGFnIGpvdXJuYWxkClN5c3RlbWRfRmlsdGVyIF9DT01NPWFybwpEQiAvdmFyL2xpYi9mbHVlbnQvam91cm5hbGRiCgpbRklMVEVSXQoJTmFtZSBtb2RpZnkKCU1hdGNoIGpvdXJuYWxkCglSZW1vdmVfd2lsZGNhcmQgXwoJUmVtb3ZlIFRJTUVTVEFNUAoKW0ZJTFRFUl0KCU5hbWUgcmV3cml0ZV90YWcKCU1hdGNoIGpvdXJuYWxkCglSdWxlICRMT0dLSU5EIGFzeW5jcW9zIGFzeW5jcW9zIHRydWUKCltGSUxURVJdCglOYW1lIG1vZGlmeQoJTWF0Y2ggYXN5bmNxb3MKCVJlbW92ZSBDTElFTlRfUFJJTkNJUEFMX05BTUUKCVJlbW92ZSBGSUxFCglSZW1vdmUgQ09NUE9ORU5UCgpbRklMVEVSXQoJTmFtZSByZXdyaXRlX3RhZwoJTWF0Y2ggam91cm5hbGQKCVJ1bGUgJExPR0tJTkQgaWZ4YXVkaXQgaWZ4YXVkaXQgZmFsc2UKCltPVVRQVVRdCglOYW1lIGZvcndhcmQKCU1hdGNoICoKCVBvcnQgMjkyMzAiCgogICAgd3JpdGVfZmlsZSBmbHVlbnRiaXRfY29uZl9maWxlbmFtZSBmbHVlbnRiaXRfY29uZl9maWxlIHRydWUKCiAgICBsb2NhbCAtciBzeXNjb25maWdfZmx1ZW50Yml0X2ZpbGVuYW1lPScvZXRjL3N5c2NvbmZpZy9mbHVlbnRiaXQnCiAgICBsb2NhbCAtciBzeXNjb25maWdfZmx1ZW50Yml0X2ZpbGU9IkZMVUVOVEJJVElNQUdFPSRGTFVFTlRCSVRJTUFHRSIKCiAgICB3cml0ZV9maWxlIHN5c2NvbmZpZ19mbHVlbnRiaXRfZmlsZW5hbWUgc3lzY29uZmlnX2ZsdWVudGJpdF9maWxlIHRydWUKCiAgICBsb2NhbCAtciBmbHVlbnRiaXRfc2VydmljZV9maWxlbmFtZT0nL2V0Yy9zeXN0ZW1kL3N5c3RlbS9mbHVlbnRiaXQuc2VydmljZScKCiAgICBsb2NhbCAtciBmbHVlbnRiaXRfc2VydmljZV9maWxlPSJbVW5pdF0KQWZ0ZXI9bmV0d29yay1vbmxpbmUudGFyZ2V0CldhbnRzPW5ldHdvcmstb25saW5lLnRhcmdldApTdGFydExpbWl0SW50ZXJ2YWxTZWM9MAoKW1NlcnZpY2VdClJlc3RhcnRTZWM9MXMKRW52aXJvbm1lbnRGaWxlPS9ldGMvc3lzY29uZmlnL2ZsdWVudGJpdApFeGVjU3RhcnRQcmU9LS91c3IvYmluL2RvY2tlciBybSAtZiAlTgpFeGVjU3RhcnQ9L3Vzci9iaW4vZG9ja2VyIHJ1biBcCiAgLS1zZWN1cml0eS1vcHQgbGFiZWw9ZGlzYWJsZSBcCiAgLS1lbnRyeXBvaW50IC9vcHQvdGQtYWdlbnQtYml0L2Jpbi90ZC1hZ2VudC1iaXQgXAogIC0tbmV0PWhvc3QgXAogIC0taG9zdG5hbWUgJUggXAogIC0tbmFtZSAlTiBcCiAgLS1ybSBcCiAgLS1jYXAtZHJvcCBuZXRfcmF3IFwKICAtdiAvZXRjL2ZsdWVudGJpdC9mbHVlbnRiaXQuY29uZjovZXRjL2ZsdWVudGJpdC9mbHVlbnRiaXQuY29uZiBcCiAgLXYgL3Zhci9saWIvZmx1ZW50Oi92YXIvbGliL2ZsdWVudDp6IFwKICAtdiAvdmFyL2xvZy9qb3VybmFsOi92YXIvbG9nL2pvdXJuYWw6cm8gXAogIC12IC9ldGMvbWFjaGluZS1pZDovZXRjL21hY2hpbmUtaWQ6cm8gXAogICRGTFVFTlRCSVRJTUFHRSBcCiAgLWMgL2V0Yy9mbHVlbnRiaXQvZmx1ZW50Yml0LmNvbmYKCkV4ZWNTdG9wPS91c3IvYmluL2RvY2tlciBzdG9wICVOClJlc3RhcnQ9YWx3YXlzClJlc3RhcnRTZWM9NQpTdGFydExpbWl0SW50ZXJ2YWw9MAoKW0luc3RhbGxdCldhbnRlZEJ5PW11bHRpLXVzZXIudGFyZ2V0IgoKICAgIHdyaXRlX2ZpbGUgZmx1ZW50Yml0X3NlcnZpY2VfZmlsZW5hbWUgZmx1ZW50Yml0X3NlcnZpY2VfZmlsZSB0cnVlCn0KCiMgY29uZmlndXJlX2NlcnRzCmNvbmZpZ3VyZV9jZXJ0cygpIHsKICAgIGxvZyAic3RhcnRpbmciCgogICAgbWtkaXIgL2V0Yy9hcm8tcnAKICAgIGJhc2U2NCAtZCA8PDwiJEFETUlOQVBJQ0FCVU5ETEUiID4vZXRjL2Fyby1ycC9hZG1pbi1jYS1idW5kbGUucGVtCiAgICBpZiBbWyAtbiAiJEFSTUFQSUNBQlVORExFIiBdXTsgdGhlbgogICAgYmFzZTY0IC1kIDw8PCIkQVJNQVBJQ0FCVU5ETEUiID4vZXRjL2Fyby1ycC9hcm0tY2EtYnVuZGxlLnBlbQogICAgZmkKICAgIGNob3duIC1SIDEwMDA6MTAwMCAvZXRjL2Fyby1ycAoKICAgICMgc2V0dGluZyBNT05JVE9SSU5HX0dDU19BVVRIX0lEX1RZUEU9QXV0aEtleVZhdWx0IHNlZW1zIHRvIGhhdmUgY2F1c2VkIG1kc2Qgbm90CiAgICAjIHRvIGhvbm91ciBTU0xfQ0VSVF9GSUxFIGFueSBtb3JlLCBoZWF2ZW4gb25seSBrbm93cyB3aHkuCiAgICBta2RpciAtcCAvdXNyL2xpYi9zc2wvY2VydHMKICAgIGNzcGxpdCAtZiAvdXNyL2xpYi9zc2wvY2VydHMvY2VydC0gLWIgJTAzZC5wZW0gL2V0Yy9wa2kvdGxzL2NlcnRzL2NhLWJ1bmRsZS5jcnQgL14kLzEgInsqfSIgPi9kZXYvbnVsbAogICAgY19yZWhhc2ggL3Vzci9saWIvc3NsL2NlcnRzCgojIHdlIGxlYXZlIGNsaWVudElkIGJsYW5rIGFzIGxvbmcgYXMgb25seSAxIG1hbmFnZWQgaWRlbnRpdHkgYXNzaWduZWQgdG8gdm1zcwojIGlmIHdlIGhhdmUgbW9yZSB0aGFuIDEsIHdlIHdpbGwgbmVlZCB0byBwb3B1bGF0ZSB3aXRoIGNsaWVudElkIHVzZWQgZm9yIG9mZi1ub2RlIHNjYW5uaW5nCiAgICBsb2NhbCAtciBub2Rlc2Nhbl9hZ2VudF9maWxlbmFtZT0iL2V0Yy9kZWZhdWx0L3ZzYS1ub2Rlc2Nhbi1hZ2VudC5jb25maWciCiAgICBsb2NhbCAtciBub2Rlc2Nhbl9hZ2VudF9maWxlPSJ7CiAgICBcIk5pY2VcIjogMTksCiAgICBcIlRpbWVvdXRcIjogMTA4MDAsCiAgICBcIkNsaWVudElkXCI6IFwiXCIsCiAgICBcIlRlbmFudElkXCI6ICRBWlVSRVNFQ1BBQ0tWU0FURU5BTlRJRCwKICAgIFwiUXVhbHlzU3RvcmVCYXNlVXJsXCI6ICRBWlVSRVNFQ1BBQ0tRVUFMWVNVUkwsCiAgICBcIlByb2Nlc3NUaW1lb3V0XCI6IDMwMCwKICAgIFwiQ29tbWFuZERlbGF5XCI6IDAKICB9IgoKICAgIHdyaXRlX2ZpbGUgbm9kZXNjYW5fYWdlbnRfZmlsZW5hbWUgbm9kZXNjYW5fYWdlbnRfZmlsZSB0cnVlCn0KCiMgY29uZmlndXJlX3NlcnZpY2VfbWRtCmNvbmZpZ3VyZV9zZXJ2aWNlX21kbSgpIHsKICAgIGxvZyAic3RhcnRpbmciCiAgICBsb2cgImNvbmZpZ3VyaW5nIG1kbSBzZXJ2aWNlIgoKICAgIGxvY2FsIC1yIHN5c2NvbmZpZ19tZG1fZmlsZW5hbWU9Ii9ldGMvc3lzY29uZmlnL21kbSIKICAgIGxvY2FsIC1yIHN5c2NvbmZpZ19tZG1fZmlsZT0iTURNRlJPTlRFTkRVUkw9JyRNRE1GUk9OVEVORFVSTCcKTURNSU1BR0U9JyRNRE1JTUFHRScKTURNU09VUkNFRU5WSVJPTk1FTlQ9JyRMT0NBVElPTicKTURNU09VUkNFUk9MRT1ycApNRE1TT1VSQ0VST0xFSU5TVEFOQ0U9XCIkKGhvc3RuYW1lKVwiIgoKICAgIHdyaXRlX2ZpbGUgc3lzY29uZmlnX21kbV9maWxlbmFtZSBzeXNjb25maWdfbWRtX2ZpbGUgdHJ1ZQoKICAgIG1rZGlyIC1wIC92YXIvZXR3CiAgICBsb2NhbCAtciBtZG1fc2VydmljZV9maWxlbmFtZT0iL2V0Yy9zeXN0ZW1kL3N5c3RlbS9tZG0uc2VydmljZSIKICAgIGxvY2FsIC1yIG1kbV9zZXJ2aWNlX2ZpbGU9IltVbml0XQpBZnRlcj1uZXR3b3JrLW9ubGluZS50YXJnZXQKV2FudHM9bmV0d29yay1vbmxpbmUudGFyZ2V0CgpbU2VydmljZV0KRW52aXJvbm1lbnRGaWxlPS9ldGMvc3lzY29uZmlnL21kbQpFeGVjU3RhcnRQcmU9LS91c3IvYmluL2RvY2tlciBybSAtZiAlTgpFeGVjU3RhcnQ9L3Vzci9iaW4vZG9ja2VyIHJ1biBcCiAgLS1lbnRyeXBvaW50IC91c3Ivc2Jpbi9NZXRyaWNzRXh0ZW5zaW9uIFwKICAtLWhvc3RuYW1lICVIIFwKICAtLW5hbWUgJU4gXAogIC0tcm0gXAogIC0tY2FwLWRyb3AgbmV0X3JhdyBcCiAgLW0gMmcgXAogIC12IC9ldGMvbWRtLnBlbTovZXRjL21kbS5wZW0gXAogIC12IC92YXIvZXR3Oi92YXIvZXR3OnogXAogICRNRE1JTUFHRSBcCiAgLUNlcnRGaWxlIC9ldGMvbWRtLnBlbSBcCiAgLUZyb250RW5kVXJsICRNRE1GUk9OVEVORFVSTCBcCiAgLUxvZ2dlciBDb25zb2xlIFwKICAtTG9nTGV2ZWwgV2FybmluZyBcCiAgLVByaXZhdGVLZXlGaWxlIC9ldGMvbWRtLnBlbSBcCiAgLVNvdXJjZUVudmlyb25tZW50ICRNRE1TT1VSQ0VFTlZJUk9OTUVOVCBcCiAgLVNvdXJjZVJvbGUgJE1ETVNPVVJDRVJPTEUgXAogIC1Tb3VyY2VSb2xlSW5zdGFuY2UgJE1ETVNPVVJDRVJPTEVJTlNUQU5DRQpFeGVjU3RvcD0vdXNyL2Jpbi9kb2NrZXIgc3RvcCAlTgpSZXN0YXJ0PWFsd2F5cwpSZXN0YXJ0U2VjPTEKU3RhcnRMaW1pdEludGVydmFsPTAKCltJbnN0YWxsXQpXYW50ZWRCeT1tdWx0aS11c2VyLnRhcmdldCIKCiAgICB3cml0ZV9maWxlIG1kbV9zZXJ2aWNlX2ZpbGVuYW1lIG1kbV9zZXJ2aWNlX2ZpbGUgdHJ1ZQp9CgojIGNvbmZpZ3VyZV90aW1lcnNfbWRtX21kc2QKY29uZmlndXJlX3RpbWVyc19tZG1fbWRzZCgpIHsKICAgIGxvZyAic3RhcnRpbmciCgogICAgZm9yIHZhciBpbiAibWRzZCIgIm1kbSI7IGRvCiAgICAgICAgbG9jYWwgZG93bmxvYWRfY3JlZHNfc2VydmljZV9maWxlbmFtZT0iL2V0Yy9zeXN0ZW1kL3N5c3RlbS9kb3dubG9hZC0kdmFyLWNyZWRlbnRpYWxzLnNlcnZpY2UiCiAgICAgICAgbG9jYWwgZG93bmxvYWRfY3JlZHNfc2VydmljZV9maWxlPSJbVW5pdF0KRGVzY3JpcHRpb249UGVyaW9kaWMgJHZhciBjcmVkZW50aWFscyByZWZyZXNoCgpbU2VydmljZV0KVHlwZT1vbmVzaG90CkV4ZWNTdGFydD0vdXNyL2xvY2FsL2Jpbi9kb3dubG9hZC1jcmVkZW50aWFscy5zaCAkdmFyIgoKICAgICAgICB3cml0ZV9maWxlIGRvd25sb2FkX2NyZWRzX3NlcnZpY2VfZmlsZW5hbWUgZG93bmxvYWRfY3JlZHNfc2VydmljZV9maWxlIHRydWUKCiAgICAgICAgbG9jYWwgZG93bmxvYWRfY3JlZHNfdGltZXJfZmlsZW5hbWU9Ii9ldGMvc3lzdGVtZC9zeXN0ZW0vZG93bmxvYWQtJHZhci1jcmVkZW50aWFscy50aW1lciIKICAgICAgICBsb2NhbCBkb3dubG9hZF9jcmVkc190aW1lcl9maWxlPSJbVW5pdF0KRGVzY3JpcHRpb249UGVyaW9kaWMgJHZhciBjcmVkZW50aWFscyByZWZyZXNoCkFmdGVyPW5ldHdvcmstb25saW5lLnRhcmdldApXYW50cz1uZXR3b3JrLW9ubGluZS50YXJnZXQKCltUaW1lcl0KT25Cb290U2VjPTBtaW4KT25DYWxlbmRhcj0wLzEyOjAwOjAwCkFjY3VyYWN5U2VjPTVzCgpbSW5zdGFsbF0KV2FudGVkQnk9dGltZXJzLnRhcmdldCIKCiAgICAgICAgd3JpdGVfZmlsZSBkb3dubG9hZF9jcmVkc190aW1lcl9maWxlbmFtZSBkb3dubG9hZF9jcmVkc190aW1lcl9maWxlIHRydWUKICAgIGRvbmUKCiAgICBsb2NhbCAtciBkb3dubG9hZF9jcmVkc19zY3JpcHRfZmlsZW5hbWU9Ii91c3IvbG9jYWwvYmluL2Rvd25sb2FkLWNyZWRlbnRpYWxzLnNoIgogICAgbG9jYWwgLXIgZG93bmxvYWRfY3JlZHNfc2NyaXB0X2ZpbGU9IiMhL2Jpbi9iYXNoCnNldCAtZXUKCkNPTVBPTkVOVD1cJDEKZWNobyBcIkRvd25sb2FkIFwkQ09NUE9ORU5UIGNyZWRlbnRpYWxzXCIKClRFTVBfRElSPVwiXCQobWt0ZW1wIC1kKVwiCmV4cG9ydCBBWlVSRV9DT05GSUdfRElSPVwiXCQobWt0ZW1wIC1kKVwiCgplY2hvIFwiTG9nZ2luZyBpbnRvIEF6dXJlLi4uXCIKUkVUUklFUz0zCndoaWxlIFtbIFwkUkVUUklFUyAtZ3QgMCBdXTsgZG8KICAgIGlmIGF6IGxvZ2luIC1pIC0tYWxsb3ctbm8tc3Vic2NyaXB0aW9ucwogICAgdGhlbgogICAgICAgIGVjaG8gXCJheiBsb2dpbiBzdWNjZXNzZnVsXCIKICAgICAgICBicmVhawogICAgZWxzZQogICAgICAgIGVjaG8gXCJheiBsb2dpbiBmYWlsZWQuIFJldHJ5aW5nLi4uXCIKICAgICAgICBsZXQgUkVUUklFUy09MQogICAgICAgIHNsZWVwIDUKICAgIGZpCmRvbmUKCnRyYXAgXCJjbGVhbnVwXCIgRVhJVAoKY2xlYW51cCgpIHsKICBheiBsb2dvdXQKICBbWyBcJFRFTVBfRElSID1+IC90bXAvLisgXV0gJiYgcm0gLXJmIFwkVEVNUF9ESVIKICBbWyBcJEFaVVJFX0NPTkZJR19ESVIgPX4gL3RtcC8uKyBdXSAmJiBybSAtcmYgXCRBWlVSRV9DT05GSUdfRElSCn0KCmlmIFtbIFwkQ09NUE9ORU5UID0gXCJtZG1cIiBdXTsgdGhlbgogIENVUlJFTlRfQ0VSVF9GSUxFPVwiL2V0Yy9tZG0ucGVtXCIKZWxpZiBbWyBcJENPTVBPTkVOVFwgPSBcIm1kc2RcIiBdXTsgdGhlbgogIENVUlJFTlRfQ0VSVF9GSUxFPVwiL3Zhci9saWIvd2FhZ2VudC9NaWNyb3NvZnQuQXp1cmUuS2V5VmF1bHQuU3RvcmUvbWRzZC5wZW1cIgplbHNlCiAgZWNobyBJbnZhbGlkIHVzYWdlICYmIGV4aXQgMQpmaQoKU0VDUkVUX05BTUU9XCJycC1cJHtDT01QT05FTlR9XCIKTkVXX0NFUlRfRklMRT1cIlwkVEVNUF9ESVIvXCRDT01QT05FTlQucGVtXCIKZm9yIGF0dGVtcHQgaW4gezEuLjV9OyBkbwogIGF6IGtleXZhdWx0IFwKICAgIHNlY3JldCBcCiAgICBkb3dubG9hZCBcCiAgICAtLWZpbGUgXCJcJE5FV19DRVJUX0ZJTEVcIiBcCiAgICAtLWlkIFwiaHR0cHM6Ly8kS0VZVkFVTFRQUkVGSVgtc3ZjLiRLRVlWQVVMVEROU1NVRkZJWC9zZWNyZXRzL1wkU0VDUkVUX05BTUVcIiBcCiAgICAmJiBicmVhawogIGlmIFtbIFwkYXR0ZW1wdCAtbHQgNSBdXTsgdGhlbiBzbGVlcCAxMDsgZWxzZSBleGl0IDE7IGZpCmRvbmUKCmlmIFsgLWYgXCRORVdfQ0VSVF9GSUxFIF07IHRoZW4KICBpZiBbWyBcJENPTVBPTkVOVCA9IFwibWRzZFwiIF1dOyB0aGVuCiAgICBjaG93biBzeXNsb2c6c3lzbG9nIFwkTkVXX0NFUlRfRklMRQogIGVsc2UKICAgIHNlZCAtaSAtbmUgJzEsL0VORCBDRVJUSUZJQ0FURS8gcCcgXCRORVdfQ0VSVF9GSUxFCiAgZmkKCiAgbmV3X2NlcnRfc249XCJcJChvcGVuc3NsIHg1MDkgLWluIFwiXCRORVdfQ0VSVF9GSUxFXCIgLW5vb3V0IC1zZXJpYWwgfCBhd2sgLUY9ICd7cHJpbnQgXCQyfScpXCIKICBjdXJyZW50X2NlcnRfc249XCJcJChvcGVuc3NsIHg1MDkgLWluIFwiXCRDVVJSRU5UX0NFUlRfRklMRVwiIC1ub291dCAtc2VyaWFsIHwgYXdrIC1GPSAne3ByaW50IFwkMn0nKVwiCiAgaWYgW1sgISAteiBcJG5ld19jZXJ0X3NuIF1dICYmIFtbIFwkbmV3X2NlcnRfc24gIT0gXCJcJGN1cnJlbnRfY2VydF9zblwiIF1dOyB0aGVuCiAgICBlY2hvIHVwZGF0aW5nIGNlcnRpZmljYXRlIGZvciBcJENPTVBPTkVOVAogICAgY2htb2QgMDYwMCBcJE5FV19DRVJUX0ZJTEUKICAgIG12IFwkTkVXX0NFUlRfRklMRSBcJENVUlJFTlRfQ0VSVF9GSUxFCiAgZmkKZWxzZQogIGVjaG8gRmFpbGVkIHRvIHJlZnJlc2ggY2VydGlmaWNhdGUgZm9yIFwkQ09NUE9ORU5UICYmIGV4aXQgMQpmaSIKCiAgICB3cml0ZV9maWxlIGRvd25sb2FkX2NyZWRzX3NjcmlwdF9maWxlbmFtZSBkb3dubG9hZF9jcmVkc19zY3JpcHRfZmlsZSB0cnVlCgogICAgY2htb2QgdSt4IC91c3IvbG9jYWwvYmluL2Rvd25sb2FkLWNyZWRlbnRpYWxzLnNoCgogICAgc3lzdGVtY3RsIGVuYWJsZSBkb3dubG9hZC1tZHNkLWNyZWRlbnRpYWxzLnRpbWVyCiAgICBzeXN0ZW1jdGwgZW5hYmxlIGRvd25sb2FkLW1kbS1jcmVkZW50aWFscy50aW1lcgoKICAgIC91c3IvbG9jYWwvYmluL2Rvd25sb2FkLWNyZWRlbnRpYWxzLnNoIG1kc2QKICAgIC91c3IvbG9jYWwvYmluL2Rvd25sb2FkLWNyZWRlbnRpYWxzLnNoIG1kbQoKICAgIGxvY2FsIC1yIE1EU0RDRVJUSUZJQ0FURVNBTj0iJChvcGVuc3NsIHg1MDkgLWluIC92YXIvbGliL3dhYWdlbnQvTWljcm9zb2Z0LkF6dXJlLktleVZhdWx0LlN0b3JlL21kc2QucGVtIC1ub291dCAtc3ViamVjdCB8IHNlZCAtZSAncy8uKkNOID0gLy8nKSIKICAgIGxvY2FsIC1yIHdhdGNoX21kbV9jcmVkc19zZXJ2aWNlX2ZpbGVuYW1lPSIvZXRjL3N5c3RlbWQvc3lzdGVtL3dhdGNoLW1kbS1jcmVkZW50aWFscy5zZXJ2aWNlIgogICAgbG9jYWwgLXIgd2F0Y2hfbWRtX2NyZWRzX3NlcnZpY2VfZmlsZT0iW1VuaXRdCkRlc2NyaXB0aW9uPVdhdGNoIGZvciBjaGFuZ2VzIGluIG1kbS5wZW0gYW5kIHJlc3RhcnRzIHRoZSBtZG0gc2VydmljZQoKW1NlcnZpY2VdClR5cGU9b25lc2hvdApFeGVjU3RhcnQ9L3Vzci9iaW4vc3lzdGVtY3RsIHJlc3RhcnQgbWRtLnNlcnZpY2UKCltJbnN0YWxsXQpXYW50ZWRCeT1tdWx0aS11c2VyLnRhcmdldCIKCiAgICB3cml0ZV9maWxlIHdhdGNoX21kbV9jcmVkc19zZXJ2aWNlX2ZpbGVuYW1lIHdhdGNoX21kbV9jcmVkc19zZXJ2aWNlX2ZpbGUgdHJ1ZQoKICAgIGxvY2FsIC1yIHdhdGNoX21kbV9jcmVkc19wYXRoX2ZpbGVuYW1lPScvZXRjL3N5c3RlbWQvc3lzdGVtL3dhdGNoLW1kbS1jcmVkZW50aWFscy5wYXRoJwogICAgbG9jYWwgLXIgd2F0Y2hfbWRtX2NyZWRzX3BhdGhfZmlsZT0nW1BhdGhdClBhdGhNb2RpZmllZD0vZXRjL21kbS5wZW0KCltJbnN0YWxsXQpXYW50ZWRCeT1tdWx0aS11c2VyLnRhcmdldCcKCiAgICB3cml0ZV9maWxlIHdhdGNoX21kbV9jcmVkc19wYXRoX2ZpbGVuYW1lIHdhdGNoX21kbV9jcmVkc19wYXRoX2ZpbGUgdHJ1ZQoKICAgIGxvY2FsIC1yIHdhdGNoX21kbV9jcmVkcz0nd2F0Y2gtbWRtLWNyZWRlbnRpYWxzLnBhdGgnCiAgICBzeXN0ZW1jdGwgZW5hYmxlICIkd2F0Y2hfbWRtX2NyZWRzIiB8fCBhYm9ydCAiZmFpbGVkIHRvIGVuYWJsZSAkd2F0Y2hfbWRtX2NyZWRzIgogICAgc3lzdGVtY3RsIHN0YXJ0ICIkd2F0Y2hfbWRtX2NyZWRzIiB8fCBhYm9ydCAiZmFpbGVkIHRvIHN0YXJ0ICR3YXRjaF9tZG1fY3JlZHMiCn0KCiMgY29uZmlndXJlX3NlcnZpY2VfYXJvX3JwCmNvbmZpZ3VyZV9zZXJ2aWNlX2Fyb19ycCgpIHsKICAgIGxvZyAic3RhcnRpbmciCgogICAgbG9jYWwgLXIgYXJvX3JwX2NvbmZfZmlsZW5hbWU9Jy9ldGMvc3lzY29uZmlnL2Fyby1ycCcKICAgIGxvY2FsIC1yIGFyb19ycF9jb25mX2ZpbGU9IkFDUl9SRVNPVVJDRV9JRD0nJEFDUlJFU09VUkNFSUQnCkFETUlOX0FQSV9DTElFTlRfQ0VSVF9DT01NT05fTkFNRT0nJEFETUlOQVBJQ0xJRU5UQ0VSVENPTU1PTk5BTUUnCkFSTV9BUElfQ0xJRU5UX0NFUlRfQ09NTU9OX05BTUU9JyRBUk1BUElDTElFTlRDRVJUQ09NTU9OTkFNRScKQVpVUkVfQVJNX0NMSUVOVF9JRD0nJEFSTUNMSUVOVElEJwpBWlVSRV9GUF9DTElFTlRfSUQ9JyRGUENMSUVOVElEJwpBWlVSRV9GUF9TRVJWSUNFX1BSSU5DSVBBTF9JRD0nJEZQU0VSVklDRVBSSU5DSVBBTElEJwpCSUxMSU5HX0UyRV9TVE9SQUdFX0FDQ09VTlRfSUQ9JyRCSUxMSU5HRTJFU1RPUkFHRUFDQ09VTlRJRCcKQ0xVU1RFUl9NRE1fQUNDT1VOVD0nJENMVVNURVJNRE1BQ0NPVU5UJwpDTFVTVEVSX01ETV9OQU1FU1BBQ0U9UlAKQ0xVU1RFUl9NRFNEX0FDQ09VTlQ9JyRDTFVTVEVSTURTREFDQ09VTlQnCkNMVVNURVJfTURTRF9DT05GSUdfVkVSU0lPTj0nJENMVVNURVJNRFNEQ09ORklHVkVSU0lPTicKQ0xVU1RFUl9NRFNEX05BTUVTUEFDRT0nJENMVVNURVJNRFNETkFNRVNQQUNFJwpEQVRBQkFTRV9BQ0NPVU5UX05BTUU9JyREQVRBQkFTRUFDQ09VTlROQU1FJwpET01BSU5fTkFNRT0nJExPQ0FUSU9OLiRDTFVTVEVSUEFSRU5URE9NQUlOTkFNRScKR0FURVdBWV9ET01BSU5TPSckR0FURVdBWURPTUFJTlMnCkdBVEVXQVlfUkVTT1VSQ0VHUk9VUD0nJEdBVEVXQVlSRVNPVVJDRUdST1VQTkFNRScKS0VZVkFVTFRfUFJFRklYPSckS0VZVkFVTFRQUkVGSVgnCk1ETV9BQ0NPVU5UPSckUlBNRE1BQ0NPVU5UJwpNRE1fTkFNRVNQQUNFPVJQCk1EU0RfRU5WSVJPTk1FTlQ9JyRNRFNERU5WSVJPTk1FTlQnClJQX0ZFQVRVUkVTPSckUlBGRUFUVVJFUycKUlBJTUFHRT0nJFJQSU1BR0UnCkFST19JTlNUQUxMX1ZJQV9ISVZFPSckQ0xVU1RFUlNJTlNUQUxMVklBSElWRScKQVJPX0hJVkVfREVGQVVMVF9JTlNUQUxMRVJfUFVMTFNQRUM9JyRDTFVTVEVSREVGQVVMVElOU1RBTExFUlBVTExTUEVDJwpBUk9fQURPUFRfQllfSElWRT0nJENMVVNURVJTQURPUFRCWUhJVkUnClVTRV9DSEVDS0FDQ0VTUz0nJFVTRUNIRUNLQUNDRVNTJyIKCiAgICB3cml0ZV9maWxlIGFyb19ycF9jb25mX2ZpbGVuYW1lIGFyb19ycF9jb25mX2ZpbGUgdHJ1ZQoKICAgIGxvY2FsIC1yIGFyb19ycF9zZXJ2aWNlX2ZpbGVuYW1lPScvZXRjL3N5c3RlbWQvc3lzdGVtL2Fyby1ycC5zZXJ2aWNlJwogICAgbG9jYWwgLXIgYXJvX3JwX3NlcnZpY2VfZmlsZT0iW1VuaXRdCkFmdGVyPW5ldHdvcmstb25saW5lLnRhcmdldApXYW50cz1uZXR3b3JrLW9ubGluZS50YXJnZXQKCltTZXJ2aWNlXQpFbnZpcm9ubWVudEZpbGU9L2V0Yy9zeXNjb25maWcvYXJvLXJwCkV4ZWNTdGFydFByZT0tL3Vzci9iaW4vZG9ja2VyIHJtIC1mICVOCkV4ZWNTdGFydD0vdXNyL2Jpbi9kb2NrZXIgcnVuIFwKICAtLWhvc3RuYW1lICVIIFwKICAtLW5hbWUgJU4gXAogIC0tcm0gXAogIC0tY2FwLWRyb3AgbmV0X3JhdyBcCiAgLWUgQUNSX1JFU09VUkNFX0lEIFwKICAtZSBBRE1JTl9BUElfQ0xJRU5UX0NFUlRfQ09NTU9OX05BTUUgXAogIC1lIEFSTV9BUElfQ0xJRU5UX0NFUlRfQ09NTU9OX05BTUUgXAogIC1lIEFaVVJFX0FSTV9DTElFTlRfSUQgXAogIC1lIEFaVVJFX0ZQX0NMSUVOVF9JRCBcCiAgLWUgQklMTElOR19FMkVfU1RPUkFHRV9BQ0NPVU5UX0lEIFwKICAtZSBDTFVTVEVSX01ETV9BQ0NPVU5UIFwKICAtZSBDTFVTVEVSX01ETV9OQU1FU1BBQ0UgXAogIC1lIENMVVNURVJfTURTRF9BQ0NPVU5UIFwKICAtZSBDTFVTVEVSX01EU0RfQ09ORklHX1ZFUlNJT04gXAogIC1lIENMVVNURVJfTURTRF9OQU1FU1BBQ0UgXAogIC1lIERBVEFCQVNFX0FDQ09VTlRfTkFNRSBcCiAgLWUgRE9NQUlOX05BTUUgXAogIC1lIEdBVEVXQVlfRE9NQUlOUyBcCiAgLWUgR0FURVdBWV9SRVNPVVJDRUdST1VQIFwKICAtZSBLRVlWQVVMVF9QUkVGSVggXAogIC1lIE1ETV9BQ0NPVU5UIFwKICAtZSBNRE1fTkFNRVNQQUNFIFwKICAtZSBNRFNEX0VOVklST05NRU5UIFwKICAtZSBSUF9GRUFUVVJFUyBcCiAgLWUgQVJPX0lOU1RBTExfVklBX0hJVkUgXAogIC1lIEFST19ISVZFX0RFRkFVTFRfSU5TVEFMTEVSX1BVTExTUEVDIFwKICAtZSBBUk9fQURPUFRfQllfSElWRSBcCiAgLWUgVVNFX0NIRUNLQUNDRVNTIFwKICAtbSAyZyBcCiAgLXAgNDQzOjg0NDMgXAogIC12IC9ldGMvYXJvLXJwOi9ldGMvYXJvLXJwIFwKICAtdiAvcnVuL3N5c3RlbWQvam91cm5hbDovcnVuL3N5c3RlbWQvam91cm5hbCBcCiAgLXYgL3Zhci9ldHc6L3Zhci9ldHc6eiBcCiAgJFJQSU1BR0UgXAogIHJwCkV4ZWNTdG9wPS91c3IvYmluL2RvY2tlciBzdG9wIC10IDM2MDAgJU4KVGltZW91dFN0b3BTZWM9MzYwMApSZXN0YXJ0PWFsd2F5cwpSZXN0YXJ0U2VjPTEKU3RhcnRMaW1pdEludGVydmFsPTAKCltJbnN0YWxsXQpXYW50ZWRCeT1tdWx0aS11c2VyLnRhcmdldCIKCiAgICB3cml0ZV9maWxlIGFyb19ycF9zZXJ2aWNlX2ZpbGVuYW1lIGFyb19ycF9zZXJ2aWNlX2ZpbGUgdHJ1ZQp9CgojIGNvbmZpZ3VyZV9zZXJ2aWNlX2Fyb19kYnRva2VuCmNvbmZpZ3VyZV9zZXJ2aWNlX2Fyb19kYnRva2VuKCkgewogICAgbG9nICJzdGFydGluZyIKCiAgICBsb2NhbCAtciBhcm9fZGJ0b2tlbl9zZXJ2aWNlX2NvbmZfZmlsZW5hbWU9Jy9ldGMvc3lzY29uZmlnL2Fyby1kYnRva2VuJwogICAgbG9jYWwgLXIgYXJvX2RidG9rZW5fc2VydmljZV9jb25mX2ZpbGU9IkRBVEFCQVNFX0FDQ09VTlRfTkFNRT0nJERBVEFCQVNFQUNDT1VOVE5BTUUnCkFaVVJFX0RCVE9LRU5fQ0xJRU5UX0lEPSckREJUT0tFTkNMSUVOVElEJwpBWlVSRV9HQVRFV0FZX1NFUlZJQ0VfUFJJTkNJUEFMX0lEPSckR0FURVdBWVNFUlZJQ0VQUklOQ0lQQUxJRCcKS0VZVkFVTFRfUFJFRklYPSckS0VZVkFVTFRQUkVGSVgnCk1ETV9BQ0NPVU5UPSckUlBNRE1BQ0NPVU5UJwpNRE1fTkFNRVNQQUNFPURCVG9rZW4KUlBJTUFHRT0nJFJQSU1BR0UnIgoKICAgIHdyaXRlX2ZpbGUgYXJvX2RidG9rZW5fc2VydmljZV9jb25mX2ZpbGVuYW1lIGFyb19kYnRva2VuX3NlcnZpY2VfY29uZl9maWxlIHRydWUKCiAgICBsb2NhbCAtciBhcm9fZGJ0b2tlbl9zZXJ2aWNlX2ZpbGVuYW1lPScvZXRjL3N5c3RlbWQvc3lzdGVtL2Fyby1kYnRva2VuLnNlcnZpY2UnCiAgICBsb2NhbCAtciBhcm9fZGJ0b2tlbl9zZXJ2aWNlX2ZpbGU9IltVbml0XQpBZnRlcj1uZXR3b3JrLW9ubGluZS50YXJnZXQKV2FudHM9bmV0d29yay1vbmxpbmUudGFyZ2V0CgpbU2VydmljZV0KRW52aXJvbm1lbnRGaWxlPS9ldGMvc3lzY29uZmlnL2Fyby1kYnRva2VuCkV4ZWNTdGFydFByZT0tL3Vzci9iaW4vZG9ja2VyIHJtIC1mICVOCkV4ZWNTdGFydD0vdXNyL2Jpbi9kb2NrZXIgcnVuIFwKICAtLWhvc3RuYW1lICVIIFwKICAtLW5hbWUgJU4gXAogIC0tcm0gXAogIC0tY2FwLWRyb3AgbmV0X3JhdyBcCiAgLWUgQVpVUkVfR0FURVdBWV9TRVJWSUNFX1BSSU5DSVBBTF9JRCBcCiAgLWUgREFUQUJBU0VfQUNDT1VOVF9OQU1FIFwKICAtZSBBWlVSRV9EQlRPS0VOX0NMSUVOVF9JRCBcCiAgLWUgS0VZVkFVTFRfUFJFRklYIFwKICAtZSBNRE1fQUNDT1VOVCBcCiAgLWUgTURNX05BTUVTUEFDRSBcCiAgLW0gMmcgXAogIC1wIDQ0NTo4NDQ1IFwKICAtdiAvcnVuL3N5c3RlbWQvam91cm5hbDovcnVuL3N5c3RlbWQvam91cm5hbCBcCiAgLXYgL3Zhci9ldHc6L3Zhci9ldHc6eiBcCiAgJFJQSU1BR0UgXAogIGRidG9rZW4KRXhlY1N0b3A9L3Vzci9iaW4vZG9ja2VyIHN0b3AgLXQgMzYwMCAlTgpUaW1lb3V0U3RvcFNlYz0zNjAwClJlc3RhcnQ9YWx3YXlzClJlc3RhcnRTZWM9MQpTdGFydExpbWl0SW50ZXJ2YWw9MAoKW0luc3RhbGxdCldhbnRlZEJ5PW11bHRpLXVzZXIudGFyZ2V0IgoKICAgIHdyaXRlX2ZpbGUgYXJvX2RidG9rZW5fc2VydmljZV9maWxlbmFtZSBhcm9fZGJ0b2tlbl9zZXJ2aWNlX2ZpbGUgdHJ1ZQp9CgojIGNvbmZpZ3VyZV9zZXJ2aWNlX2Fyb19tb25pdG9yCmNvbmZpZ3VyZV9zZXJ2aWNlX2Fyb19tb25pdG9yKCkgewogICAgbG9nICJzdGFydGluZyIKICAgIGxvZyAiY29uZmlndXJpbmcgYXJvLW1vbml0b3Igc2VydmljZSIKCiAgICAjIERPTUFJTl9OQU1FLCBDTFVTVEVSX01EU0RfQUNDT1VOVCwgQ0xVU1RFUl9NRFNEX0NPTkZJR19WRVJTSU9OLCBHQVRFV0FZX0RPTUFJTlMsIEdBVEVXQVlfUkVTT1VSQ0VHUk9VUCwgTURTRF9FTlZJUk9OTUVOVCBDTFVTVEVSX01EU0RfTkFNRVNQQUNFCiAgICAjIGFyZSBub3QgdXNlZCwgYnV0IGNhbid0IGVhc2lseSBiZSByZWZhY3RvcmVkIG91dC4gU2hvdWxkIGJlIHJldmlzaXRlZCBpbiB0aGUgZnV0dXJlLgogICAgbG9jYWwgLXIgYXJvX21vbml0b3Jfc2VydmljZV9jb25mX2ZpbGVuYW1lPScvZXRjL3N5c2NvbmZpZy9hcm8tbW9uaXRvcicKICAgIGxvY2FsIC1yIGFyb19tb25pdG9yX3NlcnZpY2VfY29uZl9maWxlPSJBWlVSRV9GUF9DTElFTlRfSUQ9JyRGUENMSUVOVElEJwpET01BSU5fTkFNRT0nJExPQ0FUSU9OLiRDTFVTVEVSUEFSRU5URE9NQUlOTkFNRScKQ0xVU1RFUl9NRFNEX0FDQ09VTlQ9JyRDTFVTVEVSTURTREFDQ09VTlQnCkNMVVNURVJfTURTRF9DT05GSUdfVkVSU0lPTj0nJENMVVNURVJNRFNEQ09ORklHVkVSU0lPTicKR0FURVdBWV9ET01BSU5TPSckR0FURVdBWURPTUFJTlMnCkdBVEVXQVlfUkVTT1VSQ0VHUk9VUD0nJEdBVEVXQVlSRVNPVVJDRUdST1VQTkFNRScKTURTRF9FTlZJUk9OTUVOVD0nJE1EU0RFTlZJUk9OTUVOVCcKQ0xVU1RFUl9NRFNEX05BTUVTUEFDRT0nJENMVVNURVJNRFNETkFNRVNQQUNFJwpDTFVTVEVSX01ETV9BQ0NPVU5UPSckQ0xVU1RFUk1ETUFDQ09VTlQnCkNMVVNURVJfTURNX05BTUVTUEFDRT1CQk0KREFUQUJBU0VfQUNDT1VOVF9OQU1FPSckREFUQUJBU0VBQ0NPVU5UTkFNRScKS0VZVkFVTFRfUFJFRklYPSckS0VZVkFVTFRQUkVGSVgnCk1ETV9BQ0NPVU5UPSckUlBNRE1BQ0NPVU5UJwpNRE1fTkFNRVNQQUNFPUJCTQpSUElNQUdFPSckUlBJTUFHRSciCgogICAgd3JpdGVfZmlsZSBhcm9fbW9uaXRvcl9zZXJ2aWNlX2NvbmZfZmlsZW5hbWUgYXJvX21vbml0b3Jfc2VydmljZV9jb25mX2ZpbGUgdHJ1ZQoKICAgIGxvY2FsIC1yIGFyb19tb25pdG9yX3NlcnZpY2VfZmlsZW5hbWU9Jy9ldGMvc3lzdGVtZC9zeXN0ZW0vYXJvLW1vbml0b3Iuc2VydmljZScKICAgIGxvY2FsIC1yIGFyb19tb25pdG9yX3NlcnZpY2VfZmlsZT0iW1VuaXRdCkFmdGVyPW5ldHdvcmstb25saW5lLnRhcmdldApXYW50cz1uZXR3b3JrLW9ubGluZS50YXJnZXQKCltTZXJ2aWNlXQpFbnZpcm9ubWVudEZpbGU9L2V0Yy9zeXNjb25maWcvYXJvLW1vbml0b3IKRXhlY1N0YXJ0UHJlPS0vdXNyL2Jpbi9kb2NrZXIgcm0gLWYgJU4KRXhlY1N0YXJ0PS91c3IvYmluL2RvY2tlciBydW4gXAogIC0taG9zdG5hbWUgJUggXAogIC0tbmFtZSAlTiBcCiAgLS1ybSBcCiAgLS1jYXAtZHJvcCBuZXRfcmF3IFwKICAtZSBBWlVSRV9GUF9DTElFTlRfSUQgXAogIC1lIERPTUFJTl9OQU1FIFwKICAtZSBDTFVTVEVSX01EU0RfQUNDT1VOVCBcCiAgLWUgQ0xVU1RFUl9NRFNEX0NPTkZJR19WRVJTSU9OIFwKICAtZSBHQVRFV0FZX0RPTUFJTlMgXAogIC1lIEdBVEVXQVlfUkVTT1VSQ0VHUk9VUCBcCiAgLWUgTURTRF9FTlZJUk9OTUVOVCBcCiAgLWUgQ0xVU1RFUl9NRFNEX05BTUVTUEFDRSBcCiAgLWUgQ0xVU1RFUl9NRE1fQUNDT1VOVCBcCiAgLWUgQ0xVU1RFUl9NRE1fTkFNRVNQQUNFIFwKICAtZSBEQVRBQkFTRV9BQ0NPVU5UX05BTUUgXAogIC1lIEtFWVZBVUxUX1BSRUZJWCBcCiAgLWUgTURNX0FDQ09VTlQgXAogIC1lIE1ETV9OQU1FU1BBQ0UgXAogIC1tIDIuNWcgXAogIC12IC9ydW4vc3lzdGVtZC9qb3VybmFsOi9ydW4vc3lzdGVtZC9qb3VybmFsIFwKICAtdiAvdmFyL2V0dzovdmFyL2V0dzp6IFwKICAkUlBJTUFHRSBcCiAgbW9uaXRvcgpSZXN0YXJ0PWFsd2F5cwpSZXN0YXJ0U2VjPTEKU3RhcnRMaW1pdEludGVydmFsPTAKCltJbnN0YWxsXQpXYW50ZWRCeT1tdWx0aS11c2VyLnRhcmdldCIKCiAgICB3cml0ZV9maWxlIGFyb19tb25pdG9yX3NlcnZpY2VfZmlsZW5hbWUgYXJvX21vbml0b3Jfc2VydmljZV9maWxlIHRydWUKfQoKIyBjb25maWd1cmVfc2VydmljZV9hcm9fcG9ydGFsCmNvbmZpZ3VyZV9zZXJ2aWNlX2Fyb19wb3J0YWwoKSB7CiAgICBsb2cgInN0YXJ0aW5nIgoKICAgIGxvY2FsIC1yIGFyb19wb3J0YWxfc2VydmljZV9jb25mX2ZpbGVuYW1lPScvZXRjL3N5c2NvbmZpZy9hcm8tcG9ydGFsJwogICAgbG9jYWwgLXIgYXJvX3BvcnRhbF9zZXJ2aWNlX2NvbmZfZmlsZT0iQVpVUkVfUE9SVEFMX0FDQ0VTU19HUk9VUF9JRFM9JyRQT1JUQUxBQ0NFU1NHUk9VUElEUycKQVpVUkVfUE9SVEFMX0NMSUVOVF9JRD0nJFBPUlRBTENMSUVOVElEJwpBWlVSRV9QT1JUQUxfRUxFVkFURURfR1JPVVBfSURTPSckUE9SVEFMRUxFVkFURURHUk9VUElEUycKREFUQUJBU0VfQUNDT1VOVF9OQU1FPSckREFUQUJBU0VBQ0NPVU5UTkFNRScKS0VZVkFVTFRfUFJFRklYPSckS0VZVkFVTFRQUkVGSVgnCk1ETV9BQ0NPVU5UPSckUlBNRE1BQ0NPVU5UJwpNRE1fTkFNRVNQQUNFPVBvcnRhbApQT1JUQUxfSE9TVE5BTUU9JyRMT0NBVElPTi5hZG1pbi4kUlBQQVJFTlRET01BSU5OQU1FJwpSUElNQUdFPSckUlBJTUFHRSciCgogICAgd3JpdGVfZmlsZSBhcm9fcG9ydGFsX3NlcnZpY2VfY29uZl9maWxlbmFtZSBhcm9fcG9ydGFsX3NlcnZpY2VfY29uZl9maWxlIHRydWUKCiAgICBsb2NhbCAtciBhcm9fcG9ydGFsX3NlcnZpY2VfZmlsZW5hbWU9Jy9ldGMvc3lzdGVtZC9zeXN0ZW0vYXJvLXBvcnRhbC5zZXJ2aWNlJwogICAgbG9jYWwgLXIgYXJvX3BvcnRhbF9zZXJ2aWNlX2ZpbGU9IltVbml0XQpBZnRlcj1uZXR3b3JrLW9ubGluZS50YXJnZXQKV2FudHM9bmV0d29yay1vbmxpbmUudGFyZ2V0ClN0YXJ0TGltaXRJbnRlcnZhbD0wCgpbU2VydmljZV0KRW52aXJvbm1lbnRGaWxlPS9ldGMvc3lzY29uZmlnL2Fyby1wb3J0YWwKRXhlY1N0YXJ0UHJlPS0vdXNyL2Jpbi9kb2NrZXIgcm0gLWYgJU4KRXhlY1N0YXJ0PS91c3IvYmluL2RvY2tlciBydW4gXAogIC0taG9zdG5hbWUgJUggXAogIC0tbmFtZSAlTiBcCiAgLS1ybSBcCiAgLS1jYXAtZHJvcCBuZXRfcmF3IFwKICAtZSBBWlVSRV9QT1JUQUxfQUNDRVNTX0dST1VQX0lEUyBcCiAgLWUgQVpVUkVfUE9SVEFMX0NMSUVOVF9JRCBcCiAgLWUgQVpVUkVfUE9SVEFMX0VMRVZBVEVEX0dST1VQX0lEUyBcCiAgLWUgREFUQUJBU0VfQUNDT1VOVF9OQU1FIFwKICAtZSBLRVlWQVVMVF9QUkVGSVggXAogIC1lIE1ETV9BQ0NPVU5UIFwKICAtZSBNRE1fTkFNRVNQQUNFIFwKICAtZSBQT1JUQUxfSE9TVE5BTUUgXAogIC1tIDJnIFwKICAtcCA0NDQ6ODQ0NCBcCiAgLXAgMjIyMjoyMjIyIFwKICAtdiAvcnVuL3N5c3RlbWQvam91cm5hbDovcnVuL3N5c3RlbWQvam91cm5hbCBcCiAgLXYgL3Zhci9ldHc6L3Zhci9ldHc6eiBcCiAgJFJQSU1BR0UgXAogIHBvcnRhbApSZXN0YXJ0PWFsd2F5cwpSZXN0YXJ0U2VjPTEKCltJbnN0YWxsXQpXYW50ZWRCeT1tdWx0aS11c2VyLnRhcmdldCIKCiAgICB3cml0ZV9maWxlIGFyb19wb3J0YWxfc2VydmljZV9maWxlbmFtZSBhcm9fcG9ydGFsX3NlcnZpY2VfZmlsZSB0cnVlCn0KCiMgY29uZmlndXJlX3NlcnZpY2VfbWRzZApjb25maWd1cmVfc2VydmljZV9tZHNkKCkgewogICAgbG9nICJzdGFydGluZyIKCiAgICBsb2NhbCAtciBtZHNkX3NlcnZpY2VfZGlyPSIvZXRjL3N5c3RlbWQvc3lzdGVtL21kc2Quc2VydmljZS5kIgogICAgbWtkaXIgLXAgIiRtZHNkX3NlcnZpY2VfZGlyIgoKICAgIGxvY2FsIC1yIG1kc2Rfb3ZlcnJpZGVfY29uZl9maWxlbmFtZT0iJG1kc2Rfc2VydmljZV9kaXIvb3ZlcnJpZGUuY29uZiIKICAgIGxvY2FsIC1yIG1kc2Rfb3ZlcnJpZGVfY29uZl9maWxlPSJbVW5pdF0KQWZ0ZXI9bmV0d29yay1vbmxpbmUudGFyZ2V0IgoKICAgIHdyaXRlX2ZpbGUgbWRzZF9vdmVycmlkZV9jb25mX2ZpbGVuYW1lIG1kc2Rfb3ZlcnJpZGVfY29uZl9maWxlIHRydWUKCiAgICBsb2NhbCAtciBkZWZhdWx0X21kc2RfZmlsZW5hbWU9Ii9ldGMvZGVmYXVsdC9tZHNkIgogICAgbG9jYWwgLXIgZGVmYXVsdF9tZHNkX2ZpbGU9Ik1EU0RfUk9MRV9QUkVGSVg9L3Zhci9ydW4vbWRzZC9kZWZhdWx0Ck1EU0RfT1BUSU9OUz1cIi1BIC1kIC1yIFwkTURTRF9ST0xFX1BSRUZJWFwiCgpleHBvcnQgTU9OSVRPUklOR19HQ1NfRU5WSVJPTk1FTlQ9JyRNRFNERU5WSVJPTk1FTlQnCmV4cG9ydCBNT05JVE9SSU5HX0dDU19BQ0NPVU5UPSckUlBNRFNEQUNDT1VOVCcKZXhwb3J0IE1PTklUT1JJTkdfR0NTX1JFR0lPTj0nJExPQ0FUSU9OJwpleHBvcnQgTU9OSVRPUklOR19HQ1NfQVVUSF9JRF9UWVBFPUF1dGhLZXlWYXVsdApleHBvcnQgTU9OSVRPUklOR19HQ1NfQVVUSF9JRD0nJE1EU0RDRVJUSUZJQ0FURVNBTicKZXhwb3J0IE1PTklUT1JJTkdfR0NTX05BTUVTUEFDRT0nJFJQTURTRE5BTUVTUEFDRScKZXhwb3J0IE1PTklUT1JJTkdfQ09ORklHX1ZFUlNJT049JyRSUE1EU0RDT05GSUdWRVJTSU9OJwpleHBvcnQgTU9OSVRPUklOR19VU0VfR0VORVZBX0NPTkZJR19TRVJWSUNFPXRydWUKCmV4cG9ydCBNT05JVE9SSU5HX1RFTkFOVD0nJExPQ0FUSU9OJwpleHBvcnQgTU9OSVRPUklOR19ST0xFPXJwCmV4cG9ydCBNT05JVE9SSU5HX1JPTEVfSU5TVEFOQ0U9XCIkKGhvc3RuYW1lKVwiCgpleHBvcnQgTURTRF9NU0dQQUNLX1NPUlRfQ09MVU1OUz0xXCIiCgogICAgd3JpdGVfZmlsZSBkZWZhdWx0X21kc2RfZmlsZW5hbWUgZGVmYXVsdF9tZHNkX2ZpbGUgdHJ1ZQoKfQoKIyBydW5fYXpzZWNkX2NvbmZpZ19zY2FuCnJ1bl9henNlY2RfY29uZmlnX3NjYW4oKSB7CiAgICBsb2cgInN0YXJ0aW5nIgoKICAgIGxvY2FsIC1hciBjb25maWdzPSgKICAgICAgICAiYmFzZWxpbmUiCiAgICAgICAgImNsYW1hdiIKICAgICAgICAic29mdHdhcmUiCiAgICApCgogICAgbG9nICJTY2FubmluZyBjb25maWd1cmF0aW9uIGZpbGVzICR7Y29uZmlnc1sqXX0iCiAgICAjIHNoZWxsY2hlY2sgZGlzYWJsZT1TQzIwNjgKICAgIGZvciBzY2FuIGluICR7Y29uZmlnc1tAXX07IGRvCiAgICAgICAgbG9nICJTY2FubmluZyBjb25maWcgZmlsZSAkc2NhbiBub3ciCiAgICAgICAgL3Vzci9sb2NhbC9iaW4vYXpzZWNkIGNvbmZpZyAtcyAiJHNjYW4iIC1kIFAxRAogICAgZG9uZQp9CgpleHBvcnQgQVpVUkVfQ0xPVURfTkFNRT0iJHtBWlVSRUNMT1VETkFNRTo/IkZhaWxlZCB0byBjYXJyeSBvdmVyIHZhcmlhYmxlcyJ9IgoKbWFpbiAiJEAiCg==')))]" } } } diff --git a/pkg/deploy/generator/scripts/devProxyVMSS.sh b/pkg/deploy/generator/scripts/devProxyVMSS.sh index f7816f47294..b7ead0a35cf 100644 --- a/pkg/deploy/generator/scripts/devProxyVMSS.sh +++ b/pkg/deploy/generator/scripts/devProxyVMSS.sh @@ -133,18 +133,6 @@ configure_devproxy_services() { configure_service_proxy "$1" } -# enable_aro_services enables all services required for aro rp -enable_aro_services() { - log "starting" - - log "enabling aro services ${aro_services[*]}" - # shellcheck disable=SC2068 - for service in ${aro_services[@]}; do - log "Enabling $service now" - systemctl enable "$service.service" - done -} - # configure_certs configure_certs() { log "starting" @@ -157,8 +145,9 @@ configure_certs() { } configure_service_proxy() { + local -n proxy_image="$1" local -r sysconfig_proxy_filename='/etc/sysconfig/proxy' - local -r sysconfig_proxy_file="PROXY_IMAGE='$1'" + local -r sysconfig_proxy_file="PROXY_IMAGE='$proxy_image'" write_file sysconfig_proxy_filename sysconfig_proxy_file true @@ -170,7 +159,7 @@ Wants=network-online.target [Service] EnvironmentFile=/etc/sysconfig/proxy ExecStartPre=-/usr/bin/docker rm -f %n -ExecStart=/usr/bin/docker run --rm --name %n -p 443:8443 -v /etc/proxy:/secrets $1 +ExecStart=/usr/bin/docker run --rm --name %n -p 443:8443 -v /etc/proxy:/secrets $proxy_image ExecStop=/usr/bin/docker stop %n Restart=always RestartSec=1 @@ -183,7 +172,7 @@ WantedBy=multi-user.target" local -r cron_weekly_pull_image_filename='/etc/cron.weekly/pull-image' local -r cron_weekly_pull_image_file="#!/bin/bash -docker pull $1 +docker pull $proxy_image systemctl restart proxy.service" write_file cron_weekly_pull_image_filename cron_weekly_pull_image_file true From 8786bf160ba69bc42b33ecbf3c3388e9dcc77c57 Mon Sep 17 00:00:00 2001 From: Steven Fairchild Date: Thu, 18 Apr 2024 12:03:04 -0400 Subject: [PATCH 29/38] Correct docker json config file, overwrite daily proxy restart cron job --- pkg/deploy/generator/scripts/devProxyVMSS.sh | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pkg/deploy/generator/scripts/devProxyVMSS.sh b/pkg/deploy/generator/scripts/devProxyVMSS.sh index b7ead0a35cf..04be87f9aa1 100644 --- a/pkg/deploy/generator/scripts/devProxyVMSS.sh +++ b/pkg/deploy/generator/scripts/devProxyVMSS.sh @@ -24,7 +24,8 @@ main() { \"${proxy_images[0]%%/*}\": { \"auth\": \"$PROXYIMAGEAUTH\" } - }" + } +}" local -ar exclude_pkgs=( "-x WALinuxAgent" @@ -182,7 +183,7 @@ systemctl restart proxy.service" local -r cron_daily_restart_proxy_file="#!/bin/bash systemctl restart proxy.service" - write_file cron_daily_restart_proxy_filename cron_daily_restart_proxy_file + write_file cron_daily_restart_proxy_filename cron_daily_restart_proxy_file true chmod +x "$cron_daily_restart_proxy_filename" } From 86036378a219f5524e15be124eb59da277c7d790 Mon Sep 17 00:00:00 2001 From: Steven Fairchild Date: Thu, 18 Apr 2024 15:20:59 -0400 Subject: [PATCH 30/38] WIP remove parse_run_options --- pkg/deploy/generator/scripts/common.sh | 2 +- pkg/deploy/generator/scripts/devProxyVMSS.sh | 112 +++---------- pkg/deploy/generator/scripts/rpVMSS.sh | 163 ++++--------------- 3 files changed, 50 insertions(+), 227 deletions(-) diff --git a/pkg/deploy/generator/scripts/common.sh b/pkg/deploy/generator/scripts/common.sh index 436c89366a4..2f66da56789 100644 --- a/pkg/deploy/generator/scripts/common.sh +++ b/pkg/deploy/generator/scripts/common.sh @@ -120,7 +120,7 @@ configure_firewalld_rules() { sysctl --system - log "Enabling ports ${enable_ports[*]} on default firewalld zone" + log "Enabling ports ${ports[*]} on default firewalld zone" # shellcheck disable=SC2068 for port in ${ports[@]}; do log "Enabling port $port now" diff --git a/pkg/deploy/generator/scripts/devProxyVMSS.sh b/pkg/deploy/generator/scripts/devProxyVMSS.sh index 04be87f9aa1..9866313e007 100644 --- a/pkg/deploy/generator/scripts/devProxyVMSS.sh +++ b/pkg/deploy/generator/scripts/devProxyVMSS.sh @@ -14,10 +14,27 @@ main() { # shellcheck source=common.sh source common.sh + local -ar exclude_pkgs=( + "-x WALinuxAgent" + "-x WALinuxAgent-udev" + ) + + dnf_update_pkgs pkgs_to_exclude retry_wait_time + + local -ra install_pkgs=( + podman + podman-docker + ) + + dnf_install_pkgs install_pkgs retry_wait_time + configure_dnf_cron_job + local -ra enable_ports=( "443/tcp" ) + configure_firewalld_rules enable_ports + local -ra proxy_images=("$PROXYIMAGE") local -r registry_config_file="{ \"auths\": { @@ -27,106 +44,17 @@ main() { } }" - local -ar exclude_pkgs=( - "-x WALinuxAgent" - "-x WALinuxAgent-udev" - ) - - local -ra install_pkgs=( - podman - podman-docker - ) + pull_container_images proxy_image registry_config_file + configure_devproxy_services proxy_images local -ra proxy_services=( - proxy + proxy ) - local -ra user_options=("$@") - parse_run_options user_options \ - exclude_pkgs \ - install_pkgs \ - enable_ports \ - proxy_services \ - proxy_images - - dnf_update_pkgs pkgs_to_exclude retry_wait_time - dnf_install_pkgs install_pkgs retry_wait_time - configure_dnf_cron_job - - configure_firewalld_rules enable_ports - pull_container_images proxy_image registry_config_file - configure_devproxy_services proxy_images enable_services proxy_services reboot_vm } -usage() { - local -n options="$1" - log "$(basename "$0") [$options] - -p Configure rpm repositories, import required rpm keys, update & install packages with dnf - -f Configure firewalld default zone rules - -u Configure systemd unit files - -i Pull container images - - Note: steps will be executed in the order that flags are provided - " -} - -# parse_run_options takes all arguements passed to main and parses them -# allowing individual step(s) to be ran, rather than all steps -# -# This is useful for local testing, or possibly modifying the bootstrap execution via environment variables in the deployment pipeline -parse_run_options() { - # shellcheck disable=SC2206 - local -n run_options="$1" - local -n pkgs_to_exclude="$2" - local -n pkgs_to_install="$3" - local -n ports_to_enable="$4" - local -n services_to_enable="$5" - local -n images_to_pull="$6" - - if [ "${#run_options[@]}" -eq 0 ]; then - log "Running all steps" - return 0 - fi - - local OPTIND - local -r allowed_options="pfui" - while getopts ${allowed_options} options; do - case "${run_options}" in - p) - log "Running step dnf_update_pkgs" - dnf_update_pkgs pkgs_to_exclude retry_wait_time - - log "Running step dnf_install_pkgs" - dnf_install_pkgs pkgs_to_install retry_wait_time - - log "Running step configure_dnf_cron_job" - configure_dnf_cron_job - ;; - f) - log "Running configure_firewalld_rules" - configure_firewalld_rules ports_to_enable - ;; - u) - log "Running step configure_devproxy_services" - configure_devproxy_services proxy_images - enable_services services_to_enable - ;; - i) - log "Running pull_container_images" - pull_container_images images_to_pull - ;; - *) - usage allowed_options - abort "Unkown option provided" - ;; - esac - done - - exit 0 -} - # configure_system_services creates, configures, and enables the following systemd services and timers # services # proxy diff --git a/pkg/deploy/generator/scripts/rpVMSS.sh b/pkg/deploy/generator/scripts/rpVMSS.sh index 906bdfd1cde..4f377a9d3fe 100644 --- a/pkg/deploy/generator/scripts/rpVMSS.sh +++ b/pkg/deploy/generator/scripts/rpVMSS.sh @@ -14,20 +14,29 @@ main() { # shellcheck source=common.sh source common.sh + configure_sshd + configure_rpm_repos retry_wait_time + local -ar exclude_pkgs=( "-x WALinuxAgent" "-x WALinuxAgent-udev" ) + dnf_update_pkgs exclude_pkgs retry_wait_time + local -ra rpm_keys=( https://dl.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-8 https://packages.microsoft.com/keys/microsoft.asc ) + rpm_import_keys rpm_keys retry_wait_time + local -ra repo_rpm_pkgs=( https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm ) + dnf_install_pkgs repo_rpm_pkgs retry_wait_time + local -ra install_pkgs=( clamav azsec-clamav @@ -42,12 +51,15 @@ main() { python3 ) - MDMIMAGE="${RPIMAGE%%/*}/${MDMIMAGE##*/}" - local -ra images=( - "$MDMIMAGE" - "$RPIMAGE" - "$FLUENTBITIMAGE" - ) + dnf_install_pkgs install_pkgs retry_wait_time + configure_dnf_cron_job + + configure_disk_partitions + configure_logrotate + configure_selinux + + mkdir -p /var/log/journal + mkdir -p /var/lib/waagent/Microsoft.Azure.KeyVault.Store local -ra enable_ports=( "443/tcp" @@ -56,6 +68,17 @@ main() { "2222/tcp" ) + configure_firewalld_rules enable_ports + + MDMIMAGE="${RPIMAGE%%/*}/${MDMIMAGE##*/}" + local -ra images=( + "$MDMIMAGE" + "$RPIMAGE" + "$FLUENTBITIMAGE" + ) + + pull_container_images images + local -ra aro_services=( "aro-dbtoken" "aro-monitor" @@ -70,38 +93,6 @@ main() { "fluentbit" ) - local -ra user_options=("$@") - parse_run_options user_options \ - retry_wait_time \ - exclude_pkgs \ - rpm_keys \ - repo_rpm_pkgs \ - install_pkgs \ - images \ - enable_ports \ - aro_services - - configure_sshd - configure_rpm_repos retry_wait_time - - dnf_update_pkgs exclude_pkgs retry_wait_time - - rpm_import_keys rpm_keys retry_wait_time - - dnf_install_pkgs repo_rpm_pkgs retry_wait_time - dnf_install_pkgs install_pkgs retry_wait_time - configure_dnf_cron_job - - configure_disk_partitions - configure_logrotate - configure_selinux - - mkdir -p /var/log/journal - mkdir -p /var/lib/waagent/Microsoft.Azure.KeyVault.Store - - configure_firewalld_rules enable_ports - - pull_container_images images configure_aro_services enable_services @@ -110,102 +101,6 @@ main() { reboot_vm } -usage() { - local -n options="$1" - log "$(basename "$0") [$options] - -d Configure Disk Partitions - -p Configure rpm repositories, import required rpm keys, update & install packages with dnf - -l Configure logrotate.conf - -s Configure selinux - -r Configure sshd - Allow password authenticaiton - -f Configure firewalld default zone rules - -u Configure systemd unit files - -i Pull container images - - Note: steps will be executed in the order that flags are provided - " -} - -# parse_run_options takes all arguements passed to main and parses them -# allowing individual step(s) to be ran, rather than all steps -# -# This is useful for local testing, or possibly modifying the bootstrap execution via environment variables in the deployment pipeline -parse_run_options() { - # shellcheck disable=SC2206 - local -n run_options="$1" - local -n retry_time="$2" - local -n pkgs_to_exclude="$3" - local -n keys_to_import="$4" - local -n rpm_pkgs="$5" - local -n pkgs_to_install="$6" - local -n images_to_pull="$7" - local -n ports_to_enable="$8" - local -n services_to_enable="$9" - - if [ "${#run_options[@]}" -eq 0 ]; then - log "Running all steps" - return 0 - fi - - local OPTIND - local -r allowed_options="dplsrfui" - while getopts ${allowed_options} options; do - case "${run_options}" in - d) - log "Running step configure_disk_partitions" - configure_disk_partitions - ;; - p) - log "Running step configure_rpm_repos" - configure_rpm_repos keys_to_import - - log "Running step dnf_update_pkgs" - dnf_update_pkgs pkgs_to_exclude retry_time - - log "Running step dnf_install_pkgs rpm_pkgs" - dnf_install_pkgs rpm_pkgs retry_time - - log "Running step dnf_install_pkgs pkgs" - dnf_install_pkgs pkgs_to_install retry_time - - log "Running step configure_dnf_crond_job" - configure_dnf_cron_job - ;; - l) - log "Running configure_logrotate" - configure_logrotate - ;; - s) - log "Running configure_selinux" - configure_selinux - ;; - r) - log "Running configure_sshd" - configure_sshd - ;; - f) - log "Running configure_firewalld_rules" - configure_firewalld_rules ports_to_enable - ;; - u) - log "Running pull_container_images & configure_system_services" - configure_aro_services - enable_services services_to_enable - ;; - i) - log "Running pull_container_images" - pull_container_images images_to_pull - ;; - *) - usage allowed_options - abort "Unkown option provided" - ;; - esac - done - - exit 0 -} - # configure_rpm_repos configure_rpm_repos() { log "starting" From f29f2fa9c655271596c7fc379420b9d69ee3c5b3 Mon Sep 17 00:00:00 2001 From: Steven Fairchild Date: Fri, 19 Apr 2024 09:55:23 -0400 Subject: [PATCH 31/38] WIP committing to restore changes from stash --- pkg/deploy/generator/scripts/gatewayVMSS.sh | 2 +- pkg/deploy/generator/scripts/rpVMSS.sh | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/pkg/deploy/generator/scripts/gatewayVMSS.sh b/pkg/deploy/generator/scripts/gatewayVMSS.sh index 64b4232309f..83089fa3efe 100644 --- a/pkg/deploy/generator/scripts/gatewayVMSS.sh +++ b/pkg/deploy/generator/scripts/gatewayVMSS.sh @@ -757,7 +757,7 @@ WantedBy=multi-user.target' systemctl start "$watch_mdm_creds" || abort "failed to start $watch_mdm_creds" } -# configure_service_aro_rp +# configure_service_aro_gateway configure_service_aro_gateway() { local -n log_dir="$1" log "starting" diff --git a/pkg/deploy/generator/scripts/rpVMSS.sh b/pkg/deploy/generator/scripts/rpVMSS.sh index 4f377a9d3fe..424c40af8bf 100644 --- a/pkg/deploy/generator/scripts/rpVMSS.sh +++ b/pkg/deploy/generator/scripts/rpVMSS.sh @@ -750,6 +750,7 @@ WantedBy=multi-user.target" # configure_service_mdsd configure_service_mdsd() { + local -n mdsd log "starting" local -r mdsd_service_dir="/etc/systemd/system/mdsd.service.d" From b0d90d613deaaffff6adb9d77cc444242a0da126 Mon Sep 17 00:00:00 2001 From: Steven Fairchild Date: Fri, 19 Apr 2024 10:02:54 -0400 Subject: [PATCH 32/38] Import stash --- pkg/deploy/generator/scripts/common.sh | 478 +++++++++++ pkg/deploy/generator/scripts/gatewayVMSS.sh | 832 ++------------------ pkg/deploy/generator/scripts/rpVMSS.sh | 522 ++---------- 3 files changed, 580 insertions(+), 1252 deletions(-) diff --git a/pkg/deploy/generator/scripts/common.sh b/pkg/deploy/generator/scripts/common.sh index 2f66da56789..f69e30dbf2c 100644 --- a/pkg/deploy/generator/scripts/common.sh +++ b/pkg/deploy/generator/scripts/common.sh @@ -131,7 +131,9 @@ configure_firewalld_rules() { } # configure_logrotate clobbers /etc/logrotate.conf +# TODO add writing of dropin files configure_logrotate() { + local -n dropin_files="$1" log "starting" local -r logrotate_conf_filename='/etc/logrotate.conf' @@ -170,6 +172,13 @@ include /etc/logrotate.d }' write_file logrotate_conf_filename logrotate_conf_file true + + local -r logrotate_d="/etc/logrotate.d" + log "Writing logrotate files to $logrotate_d" + for dropin_name in "${!dropin_files[@]}"; do + local -r dropin_file="$logrotate_d/$dropin_name" + write_file "$dropin_file" "${dropin_files["$dropin_name"]}" + done } # pull_container_images @@ -291,3 +300,472 @@ dnf update -y" chmod +x "$cron_weekly_dnf_update_filename" } +# create_azure_rpm_repos creates /etc/yum.repos.d/azure.repo repository file +create_azure_rpm_repos() { + log "starting" + + local -r azure_repo_filename='/etc/yum.repos.d/azure.repo' + local -r azure_repo_file='[azure-cli] +name=azure-cli +baseurl=https://packages.microsoft.com/yumrepos/azure-cli +enabled=yes +gpgcheck=yes + +[azurecore] +name=azurecore +baseurl=https://packages.microsoft.com/yumrepos/azurecore +enabled=yes +gpgcheck=no' + + write_file azure_repo_filename azure_repo_file true +} + +# configure_disk_partitions +configure_disk_partitions() { + log "starting" + log "extending partition table" + + # Linux block devices are inconsistently named + # it's difficult to tie the lvm pv to the physical disk using /dev/disk files, which is why lvs is used here + physical_disk="$(lvs -o devices -a | head -n2 | tail -n1 | cut -d ' ' -f 3 | cut -d \( -f 1 | tr -d '[:digit:]')" + growpart "$physical_disk" 2 + + log "extending filesystems" + log "extending root lvm" + lvextend -l +20%FREE /dev/rootvg/rootlv + log "growing root filesystem" + xfs_growfs / + + log "extending var lvm" + lvextend -l +100%FREE /dev/rootvg/varlv + log "growing var filesystem" + xfs_growfs /var +} + +# configure_certs +configure_certs() { + log "starting" + + mkdir /etc/aro-rp + base64 -d <<<"$ADMINAPICABUNDLE" >/etc/aro-rp/admin-ca-bundle.pem + if [[ -n "$ARMAPICABUNDLE" ]]; then + base64 -d <<<"$ARMAPICABUNDLE" >/etc/aro-rp/arm-ca-bundle.pem + fi + chown -R 1000:1000 /etc/aro-rp + + # setting MONITORING_GCS_AUTH_ID_TYPE=AuthKeyVault seems to have caused mdsd not + # to honour SSL_CERT_FILE any more, heaven only knows why. + mkdir -p /usr/lib/ssl/certs + csplit -f /usr/lib/ssl/certs/cert- -b %03d.pem /etc/pki/tls/certs/ca-bundle.crt /^$/1 "{*}" >/dev/null + c_rehash /usr/lib/ssl/certs + +# we leave clientId blank as long as only 1 managed identity assigned to vmss +# if we have more than 1, we will need to populate with clientId used for off-node scanning + local -r nodescan_agent_filename="/etc/default/vsa-nodescan-agent.config" + local -r nodescan_agent_file="{ + \"Nice\": 19, + \"Timeout\": 10800, + \"ClientId\": \"\", + \"TenantId\": $AZURESECPACKVSATENANTID, + \"QualysStoreBaseUrl\": $AZURESECPACKQUALYSURL, + \"ProcessTimeout\": 300, + \"CommandDelay\": 0 + }" + + write_file nodescan_agent_filename nodescan_agent_file true +} + +# configure_service_mdm +configure_service_mdm() { + log "starting" + log "configuring mdm service" + + local -r sysconfig_mdm_filename="/etc/sysconfig/mdm" + local -r sysconfig_mdm_file="MDMFRONTENDURL='$MDMFRONTENDURL' +MDMIMAGE='$MDMIMAGE' +MDMSOURCEENVIRONMENT='$LOCATION' +MDMSOURCEROLE=gateway +MDMSOURCEROLEINSTANCE=\"$(hostname)\"" + + write_file sysconfig_mdm_filename sysconfig_mdm_file true + + mkdir -p /var/etw + local -r mdm_service_filename="/etc/systemd/system/mdm.service" + local -r mdm_service_file="[Unit] +After=network-online.target +Wants=network-online.target + +[Service] +EnvironmentFile=/etc/sysconfig/mdm +ExecStartPre=-/usr/bin/docker rm -f %N +ExecStart=/usr/bin/docker run \ + --entrypoint /usr/sbin/MetricsExtension \ + --hostname %H \ + --name %N \ + --rm \ + --cap-drop net_raw \ + -m 2g \ + -v /etc/mdm.pem:/etc/mdm.pem \ + -v /var/etw:/var/etw:z \ + $MDMIMAGE \ + -CertFile /etc/mdm.pem \ + -FrontEndUrl $MDMFRONTENDURL \ + -Logger Console \ + -LogLevel Warning \ + -PrivateKeyFile /etc/mdm.pem \ + -SourceEnvironment $MDMSOURCEENVIRONMENT \ + -SourceRole $MDMSOURCEROLE \ + -SourceRoleInstance $MDMSOURCEROLEINSTANCE +ExecStop=/usr/bin/docker stop %N +Restart=always +RestartSec=1 +StartLimitInterval=0 + +[Install] +WantedBy=multi-user.target" + + write_file mdm_service_filename mdm_service_file true +} + +# configure_timers_mdm_mdsd +configure_timers_mdm_mdsd() { + log "starting" + + for var in "mdsd" "mdm"; do + local download_creds_service_filename="/etc/systemd/system/download-$var-credentials.service" + local download_creds_service_file="[Unit] +Description=Periodic $var credentials refresh + +[Service] +Type=oneshot +ExecStart=/usr/local/bin/download-credentials.sh $var" + + write_file download_creds_service_filename download_creds_service_file true + + local download_creds_timer_filename="/etc/systemd/system/download-$var-credentials.timer" + local download_creds_timer_file="[Unit] +Description=Periodic $var credentials refresh +After=network-online.target +Wants=network-online.target + +[Timer] +OnBootSec=0min +OnCalendar=0/12:00:00 +AccuracySec=5s + +[Install] +WantedBy=timers.target" + + write_file download_creds_timer_filename download_creds_timer_file true + done + + local -r download_creds_script_filename="/usr/local/bin/download-credentials.sh" + local -r download_creds_script_file="#!/bin/bash +set -eu + +COMPONENT=\$1 +echo \"Download \$COMPONENT credentials\" + +TEMP_DIR=\"\$(mktemp -d)\" +export AZURE_CONFIG_DIR=\"\$(mktemp -d)\" + +echo \"Logging into Azure...\" +RETRIES=3 +while [[ \$RETRIES -gt 0 ]]; do + if az login -i --allow-no-subscriptions + then + echo \"az login successful\" + break + else + echo \"az login failed. Retrying...\" + let RETRIES-=1 + sleep 5 + fi +done + +trap \"cleanup\" EXIT + +cleanup() { + az logout + [[ \$TEMP_DIR =~ /tmp/.+ ]] && rm -rf \$TEMP_DIR + [[ \$AZURE_CONFIG_DIR =~ /tmp/.+ ]] && rm -rf \$AZURE_CONFIG_DIR +} + +if [[ \$COMPONENT = \"mdm\" ]]; then + CURRENT_CERT_FILE=\"/etc/mdm.pem\" +elif [[ \$COMPONENT\ = \"mdsd\" ]]; then + CURRENT_CERT_FILE=\"/var/lib/waagent/Microsoft.Azure.KeyVault.Store/mdsd.pem\" +else + echo Invalid usage && exit 1 +fi + +SECRET_NAME=\"gwy-\${COMPONENT}\" +NEW_CERT_FILE=\"\$TEMP_DIR/\$COMPONENT.pem\" +for attempt in {1..5}; do + az keyvault \ + secret \ + download \ + --file \"\$NEW_CERT_FILE\" \ + --id \"https://$KEYVAULTPREFIX-gwy.$KEYVAULTDNSSUFFIX/secrets/\$SECRET_NAME\" \ + && break + if [[ \$attempt -lt 5 ]]; then sleep 10; else exit 1; fi +done + +if [ -f \$NEW_CERT_FILE ]; then + if [[ \$COMPONENT = \"mdsd\" ]]; then + chown syslog:syslog \$NEW_CERT_FILE + else + sed -i -ne '1,/END CERTIFICATE/ p' \$NEW_CERT_FILE + fi + + new_cert_sn=\"\$(openssl x509 -in \"\$NEW_CERT_FILE\" -noout -serial | awk -F= '{print \$2}')\" + current_cert_sn=\"\$(openssl x509 -in \"\$CURRENT_CERT_FILE\" -noout -serial | awk -F= '{print \$2}')\" + if [[ ! -z \$new_cert_sn ]] && [[ \$new_cert_sn != \"\$current_cert_sn\" ]]; then + echo updating certificate for \$COMPONENT + chmod 0600 \$NEW_CERT_FILE + mv \$NEW_CERT_FILE \$CURRENT_CERT_FILE + fi +else + echo Failed to refresh certificate for \$COMPONENT && exit 1 +fi" + + write_file download_creds_script_filename download_creds_script_file true + + chmod u+x /usr/local/bin/download-credentials.sh + + # TODO place this in enable services section + systemctl enable download-mdsd-credentials.timer + systemctl enable download-mdm-credentials.timer + + /usr/local/bin/download-credentials.sh mdsd + /usr/local/bin/download-credentials.sh mdm + + local -r MDSDCERTIFICATESAN="$(openssl x509 -in /var/lib/waagent/Microsoft.Azure.KeyVault.Store/mdsd.pem -noout -subject | sed -e 's/.*CN = //')" + local -r watch_mdm_creds_service_filename="/etc/systemd/system/watch-mdm-credentials.service" + local -r watch_mdm_creds_service_file="[Unit] +Description=Watch for changes in mdm.pem and restarts the mdm service + +[Service] +Type=oneshot +ExecStart=/usr/bin/systemctl restart mdm.service + +[Install] +WantedBy=multi-user.target" + + write_file watch_mdm_creds_service_filename watch_mdm_creds_service_file true + + local -r watch_mdm_creds_path_filename='/etc/systemd/system/watch-mdm-credentials.path' + local -r watch_mdm_creds_path_file='[Path] +PathModified=/etc/mdm.pem + +[Install] +WantedBy=multi-user.target' + + write_file watch_mdm_creds_path_filename watch_mdm_creds_path_file true + + local -r watch_mdm_creds='watch-mdm-credentials.path' + systemctl enable "$watch_mdm_creds" || abort "failed to enable $watch_mdm_creds" + systemctl start "$watch_mdm_creds" || abort "failed to start $watch_mdm_creds" +} + +# configure_service_fluentbit +configure_service_fluentbit() { + local -n fluentbit_conf_file="$1" + local -n fluentbit_image="$2" + log "starting" + log "configuring fluentbit service" + + if [[ -n $fluentbit_conf_file ]]; then + abort "$1 fluentbit config file cannot be empty" + elif [[ -n $fluentbit_image ]]; then + abort "$2 fluentbit image cannot be empty" + fi + + mkdir -p /etc/fluentbit/ + mkdir -p /var/lib/fluent + + local -r fluentbit_conf_filename='/etc/fluentbit/fluentbit.conf' + write_file fluentbit_conf_filename fluentbit_conf_file true + + local -r sysconfig_fluentbit_filename='/etc/sysconfig/fluentbit' + local -r sysconfig_fluentbit_file="FLUENTBITIMAGE=$fluentbit_image" + + write_file sysconfig_fluentbit_filename sysconfig_fluentbit_file true + + local -r fluentbit_service_filename='/etc/systemd/system/fluentbit.service' + + local -r fluentbit_service_file="[Unit] +After=network-online.target +Wants=network-online.target +StartLimitIntervalSec=0 + +[Service] +RestartSec=1s +EnvironmentFile=/etc/sysconfig/fluentbit +ExecStartPre=-/usr/bin/docker rm -f %N +ExecStart=/usr/bin/docker run \ + --security-opt label=disable \ + --entrypoint /opt/td-agent-bit/bin/td-agent-bit \ + --net=host \ + --hostname %H \ + --name %N \ + --rm \ + --cap-drop net_raw \ + -v /etc/fluentbit/fluentbit.conf:/etc/fluentbit/fluentbit.conf \ + -v /var/lib/fluent:/var/lib/fluent:z \ + -v /var/log/journal:/var/log/journal:ro \ + -v /etc/machine-id:/etc/machine-id:ro \ + $fluentbit_image \ + -c /etc/fluentbit/fluentbit.conf + +ExecStop=/usr/bin/docker stop %N +Restart=always +RestartSec=5 +StartLimitInterval=0 + +[Install] +WantedBy=multi-user.target" + + write_file fluentbit_service_filename fluentbit_service_file true +} + +# configure_service_aro_dbtoken +configure_service_aro_dbtoken() { + local -n dbtoken_conf="$1" + local -n log_dir="${2:-}" + log "starting" + + local -r aro_dbtoken_service_conf_filename='/etc/sysconfig/aro-dbtoken' + + write_file aro_dbtoken_service_conf_filename aro_dbtoken_service_conf_file true + + local -r aro_dbtoken_service_filename='/etc/systemd/system/aro-dbtoken.service' + # TODO add test if log_dir is empty, else + local -r aro_dbtoken_service_file="[Unit] +After=network-online.target +Wants=network-online.target + +[Service] +EnvironmentFile=/etc/sysconfig/aro-dbtoken +ExecStartPre=-/usr/bin/docker rm -f %N +ExecStart=/usr/bin/docker run \ + --hostname %H \ + --name %N \ + --rm \ + --cap-drop net_raw \ + -e AZURE_GATEWAY_SERVICE_PRINCIPAL_ID \ + -e DATABASE_ACCOUNT_NAME \ + -e AZURE_DBTOKEN_CLIENT_ID \ + -e KEYVAULT_PREFIX \ + -e MDM_ACCOUNT \ + -e MDM_NAMESPACE \ + -m 2g \ + -p 445:8445 \ + -v /run/systemd/journal:/run/systemd/journal \ + -v /var/etw:/var/etw:z \ + $RPIMAGE \ + dbtoken +ExecStop=/usr/bin/docker stop -t 3600 %N +TimeoutStopSec=3600 +Restart=always +RestartSec=1 +StartLimitInterval=0 + +[Install] +WantedBy=multi-user.target" + + local -r aro_dbtoken_service_file="[Unit] +After=network-online.target +Wants=network-online.target + +[Service] +EnvironmentFile=/etc/sysconfig/aro-gateway +ExecStartPre=-/usr/bin/docker rm -f %N +ExecStartPre=/usr/bin/mkdir -p ${gateway_logdir} +ExecStart=/usr/bin/docker run \ + --hostname %H \ + --name %N \ + --rm \ + --cap-drop net_raw \ + -e ACR_RESOURCE_ID \ + -e DATABASE_ACCOUNT_NAME \ + -e AZURE_DBTOKEN_CLIENT_ID \ + -e DBTOKEN_URL \ + -e GATEWAY_DOMAINS \ + -e GATEWAY_FEATURES \ + -e MDM_ACCOUNT \ + -e MDM_NAMESPACE \ + -m 2g \ + -p 80:8080 \ + -p 8081:8081 \ + -p 443:8443 \ + -v /run/systemd/journal:/run/systemd/journal \ + -v /var/etw:/var/etw:z \ + -v ${gateway_logdir}:/ctr.log:z \ + \$RPIMAGE \ + gateway +ExecStop=/usr/bin/docker stop -t 3600 %N +TimeoutStopSec=3600 +Restart=always +RestartSec=1 +StartLimitInterval=0 + +[Install] +WantedBy=multi-user.target" + + write_file aro_dbtoken_service_filename aro_dbtoken_service_file true +} + +# configure_service_mdsd +configure_service_mdsd() { + local -n monitor_config_version="$1" + log "starting" + + local -r mdsd_service_dir="/etc/systemd/system/mdsd.service.d" + mkdir -p "$mdsd_service_dir" + + local -r mdsd_override_conf_filename="$mdsd_service_dir/override.conf" + local -r mdsd_override_conf_file="[Unit] +After=network-online.target" + + write_file mdsd_override_conf_filename mdsd_override_conf_file true + + local -r default_mdsd_filename="/etc/default/mdsd" + local -r default_mdsd_file="MDSD_ROLE_PREFIX=/var/run/mdsd/default +MDSD_OPTIONS=\"-A -d -r \$MDSD_ROLE_PREFIX\" + +export MONITORING_GCS_ENVIRONMENT='$MDSDENVIRONMENT' +export MONITORING_GCS_ACCOUNT='$RPMDSDACCOUNT' +export MONITORING_GCS_REGION='$LOCATION' +export MONITORING_GCS_AUTH_ID_TYPE=AuthKeyVault +export MONITORING_GCS_AUTH_ID='$MDSDCERTIFICATESAN' +export MONITORING_GCS_NAMESPACE='$RPMDSDNAMESPACE' +export MONITORING_CONFIG_VERSION='$monitor_config_version' +export MONITORING_USE_GENEVA_CONFIG_SERVICE=true + +export MONITORING_TENANT='$LOCATION' +export MONITORING_ROLE=rp +export MONITORING_ROLE_INSTANCE=\"$(hostname)\" + +export MDSD_MSGPACK_SORT_COLUMNS=1\"" + + write_file default_mdsd_filename default_mdsd_file true +} + +# run_azsecd_config_scan +run_azsecd_config_scan() { + log "starting" + + local -ar configs=( + "baseline" + "clamav" + "software" + ) + + log "Scanning configuration files ${configs[*]}" + # shellcheck disable=SC2068 + for scan in ${configs[@]}; do + log "Scanning config file $scan now" + /usr/local/bin/azsecd config -s "$scan" -d P1D + done +} diff --git a/pkg/deploy/generator/scripts/gatewayVMSS.sh b/pkg/deploy/generator/scripts/gatewayVMSS.sh index 83089fa3efe..064bf18bd49 100644 --- a/pkg/deploy/generator/scripts/gatewayVMSS.sh +++ b/pkg/deploy/generator/scripts/gatewayVMSS.sh @@ -8,124 +8,14 @@ if [ "${DEBUG:-false}" == true ]; then fi main() { - local -r gateway_logdir='/var/log/aro-gateway' - parse_run_options "$@" gateway_logdir - - configure_sshd - configure_and_install_dnf_pkgs_repos - configure_disk_partitions - configure_logrotate gateway_logdir - configure_selinux - - mkdir -p /var/log/journal - mkdir -p /var/lib/waagent/Microsoft.Azure.KeyVault.Store - - configure_firewalld_rules - pull_container_images - configure_system_services gateway_logdir - reboot_vm -} - -usage() { - local -n options="$1" - log "$(basename "$0") [$options] - -d Configure Disk Partitions - -p Configure rpm repositories, import required rpm keys, update & install packages with dnf - -l Configure logrotate.conf - -s Make selinux modifications required for ARO RP - -r Configure sshd - Allow password authenticaiton - -f Configure firewalld default zone rules - -u Configure systemd unit files for ARO RP - -i Pull container images - - Note: steps will be executed in the order that flags are provided - " -} - -# parse_run_options takes all arguements passed to main and parses them -# allowing individual step(s) to be ran, rather than all steps -# -# This is useful for local testing, or possibly modifying the bootstrap execution via environment variables in the deployment pipeline -parse_run_options() { - # shellcheck disable=SC2206 - local -a options=(${1:-}) - if [ "${#options[@]}" -eq 0 ]; then - log "Running all steps" - return 0 - fi - - local OPTIND - local -r allowed_options="dplsrfui" - while getopts ${allowed_options} options; do - case "${options}" in - d) - log "Running step configure_disk_partitions" - configure_disk_partitions - ;; - p) - log "Running step configure_and_install_dnf_pkgs_repos" - configure_and_install_dnf_pkgs_repos - ;; - l) - log "Running configure_logrotate" - configure_logrotate "$2" - ;; - s) - log "Running configure_selinux" - configure_selinux - ;; - r) - log "Running configure_sshd" - configure_sshd - ;; - f) - log "Running configure_firewalld_rules" - configure_firewalld_rules - ;; - u) - log "Running pull_container_images & configure_system_services" - configure_system_services "$2" - ;; - i) - log "Running pull_container_images" - pull_container_images - ;; - *) - usage allowed_options - abort "Unkown option provided" - ;; - esac - done - - exit 0 -} - -# We need to configure PasswordAuthentication to yes in order for the VMSS Access JIT to work -configure_sshd() { - log "starting" - log "setting ssh password authentication" - sed -i 's/PasswordAuthentication no/PasswordAuthentication yes/g' /etc/ssh/sshd_config - - systemctl reload sshd.service - systemctl is-active --quiet sshd || abort "sshd failed to reload" -} - -# configure_and_install_dnf_pkgs_repos -configure_and_install_dnf_pkgs_repos() { - log "starting" - - # transaction attempt retry time in seconds - local -ri retry_wait_time=60 - configure_rhui_repo retry_wait_time - create_azure_rpm_repos retry_wait_time local -ar exclude_pkgs=( "-x WALinuxAgent" "-x WALinuxAgent-udev" ) - dnf_update_pkgs exclude_pkgs retry_wait_time + dnf_update_pkgs pkgs_to_exclude retry_wait_time local -ra rpm_keys=( https://dl.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-8 @@ -138,6 +28,8 @@ configure_and_install_dnf_pkgs_repos() { https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm ) + dnf_install_pkgs repo_rpm_pkgs retry_wait_time + local -ra install_pkgs=( clamav azsec-clamav @@ -152,166 +44,15 @@ configure_and_install_dnf_pkgs_repos() { python3 ) - dnf_install_pkgs repo_rpm_pkgs retry_wait_time dnf_install_pkgs install_pkgs retry_wait_time -} - -# configure_rhui_repo -configure_rhui_repo() { - log "starting" - - local -ra cmd=( - dnf - update - -y - --disablerepo='*' - --enablerepo='rhui-microsoft-azure*' - ) - - log "running RHUI package updates" - retry cmd "$1" -} - -# retry Adding retry logic to yum commands in order to avoid stalling out on resource locks -retry() { - local -n cmd_retry="$1" - local -n wait_time="$2" - - for attempt in {1..5}; do - log "attempt #${attempt} - ${FUNCNAME[2]}" - ${cmd_retry[@]} & - - wait $! && break - if [[ ${attempt} -lt 5 ]]; then - sleep "$wait_time" - else - abort "attempt #${attempt} - Failed to update packages" - fi - done -} - -# dnf_update_pkgs -dnf_update_pkgs() { - local -n excludes="$1" - log "starting" - - local -ra cmd=( - dnf - -y - ${excludes[@]} - update - --allowerasing - ) - - log "Updating all packages" - retry cmd "$2" -} - -# dnf_install_pkgs -dnf_install_pkgs() { - local -n pkgs="$1" - log "starting" - - local -ra cmd=( - dnf - -y - install - ${pkgs[@]} - ) - - log "Attempting to install packages: ${pkgs[*]}" - retry cmd "$2" -} - -# rpm_import_keys -rpm_import_keys() { - local -n keys="$1" - log "starting" - - - # shellcheck disable=SC2068 - for key in ${keys[@]}; do - if [ ${#keys[@]} -eq 0 ]; then - break - fi - local -a cmd=( - rpm - --import - -v - "$key" - ) - - log "attempt #$attempt - importing rpm repository key $key" - retry cmd "$2" && unset key - done -} - -# configure_disk_partitions -configure_disk_partitions() { - log "starting" - log "extending partition table" - - # Linux block devices are inconsistently named - # it's difficult to tie the lvm pv to the physical disk using /dev/disk files, which is why lvs is used here - physical_disk="$(lvs -o devices -a | head -n2 | tail -n1 | cut -d ' ' -f 3 | cut -d \( -f 1 | tr -d '[:digit:]')" - growpart "$physical_disk" 2 - - log "extending filesystems" - log "extending root lvm" - lvextend -l +20%FREE /dev/rootvg/rootlv - log "growing root filesystem" - xfs_growfs / - - log "extending var lvm" - lvextend -l +100%FREE /dev/rootvg/varlv - log "growing var filesystem" - xfs_growfs /var -} - -# configure_logrotate clobbers /etc/logrotate.conf -configure_logrotate() { - local -n log_dir="$1" - log "starting" - - local -r logrotate_conf_filename='/etc/logrotate.conf' - local -r logrotate_conf_file="# see 'man logrotate' for details -# rotate log files weekly -weekly - -# keep 2 weeks worth of backlogs -rotate 2 - -# create new (empty) log files after rotating old ones -create - -# use date as a suffix of the rotated file -dateext - -# uncomment this if you want your log files compressed -compress - -# RPM packages drop log rotation information into this directory -include /etc/logrotate.d - -# no packages own wtmp and btmp -- we will rotate them here -/var/log/wtmp { - monthly - create 0664 root utmp - minsize 1M - rotate 1 -} -/var/log/btmp { - missingok - monthly - create 0600 root utmp - rotate 1 -} + configure_disk_partitions -# Maximum log directory size is 100G with this configuration + local -r gateway_logdir='/var/log/aro-gateway' + local -r gateway_log_file="# Maximum log directory size is 100G with this configuration # Setting limit to 100G to allow space for other logging services # copytruncate is a critical option used to prevent logs from being shipped twice -${log_dir} { +${gateway_logdir} { size 20G rotate 5 create 0600 root root @@ -320,131 +61,35 @@ ${log_dir} { compress }" - write_file logrotate_conf_filename logrotate_conf_file true -} - -# create_azure_rpm_repos creates /etc/yum.repos.d/azure.repo repository file -create_azure_rpm_repos() { - log "starting" - - local -r azure_repo_filename='/etc/yum.repos.d/azure.repo' - local -r azure_repo_file='[azure-cli] -name=azure-cli -baseurl=https://packages.microsoft.com/yumrepos/azure-cli -enabled=yes -gpgcheck=yes - -[azurecore] -name=azurecore -baseurl=https://packages.microsoft.com/yumrepos/azurecore -enabled=yes -gpgcheck=no' - - write_file azure_repo_filename azure_repo_file true -} - -# configure_selinux -configure_selinux() { - log "starting" - - local -r relabel="${1:-false}" - - already_defined_ignore_error="File context for /var/log/journal(/.*)? already defined" - semanage fcontext -a -t var_log_t "/var/log/journal(/.*)?" || log "$already_defined_ignore_error" - chcon -R system_u:object_r:var_log_t:s0 /var/opt/microsoft/linuxmonagent - - if "$relabel"; then - restorecon -RF /var/log/* || log "$already_defined_ignore_error" - fi -} - -# configure_firewalld_rules -configure_firewalld_rules() { - log "starting" - - # https://access.redhat.com/security/cve/cve-2020-13401 - local -r prefix="/etc/sysctl.d" - local -r disable_accept_ra_conf_filename="$prefix/02-disable-accept-ra.conf" - local -r disable_accept_ra_conf_file="net.ipv6.conf.all.accept_ra=0" - - write_file disable_accept_ra_conf_filename disable_accept_ra_conf_file true + local -rA logrotate_dropins=( + ["gateway_log_config"]="$gateway_log_file" + ) - local -r disable_core_filename="$prefix/01-disable-core.conf" - local -r disable_core_file="kernel.core_pattern = |/bin/true - " - write_file disable_core_filename disable_core_file true + configure_logrotate logrotate_dropins + configure_selinux - sysctl --system + mkdir -p /var/log/journal + mkdir -p /var/lib/waagent/Microsoft.Azure.KeyVault.Store local -ra enable_ports=( "80/tcp" "8081/tcp" "443/tcp" ) + configure_firewalld_rules enable_ports + + local -r mdmimage="${RPIMAGE%%/*}/${MDMIMAGE##*/}" + local -r rpimage="$RPIMAGE" + local -r fluentbit_image="$FLUENTBITIMAGE" + local -ra images=( + "$mdmimage" + "$rpimage" + "$fluentbit_image" + ) - log "Enabling ports ${enable_ports[*]} on default firewalld zone" - # shellcheck disable=SC2068 - for port in ${enable_ports[@]}; do - log "Enabling port $port now" - firewall-cmd "--add-port=$port" - done - - firewall-cmd --runtime-to-permanent -} - -# pull_container_images -pull_container_images() { - log "starting" - - # The managed identity that the VM runs as only has a single roleassignment. - # This role assignment is ACRPull which is not necessarily present in the - # subscription we're deploying into. If the identity does not have any - # role assignments scoped on the subscription we're deploying into, it will - # not show on az login -i, which is why the below line is commented. - # az account set -s "$SUBSCRIPTIONID" - az login -i --allow-no-subscriptions - - # Suppress emulation output for podman instead of docker for az acr compatability - mkdir -p /etc/containers/ - mkdir -p /root/.docker - touch /etc/containers/nodocker - - # This name is used in the case that az acr login searches for this in it's environment - local -r REGISTRY_AUTH_FILE="/root/.docker/config.json" - - log "logging into prod acr" - az acr login --name "$(sed -e 's|.*/||' <<<"$ACRRESOURCEID")" - - MDMIMAGE="${RPIMAGE%%/*}/${MDMIMAGE##*/}" - docker pull "$MDMIMAGE" - docker pull "$RPIMAGE" - docker pull "$FLUENTBITIMAGE" - - az logout -} - -# configure_system_services creates, configures, and enables the following systemd services and timers -# services -# fluentbit -# mdm -# mdsd -# arp-rp -# aro-dbtoken -# aro-monitor -# aro-portal -configure_system_services() { - configure_service_fluentbit - configure_service_mdm - configure_timers_mdm_mdsd - configure_service_aro_gateway "$1" - configure_service_mdsd -} - -# enable_aro_services enables all services required for aro rp -enable_aro_services() { - log "starting" + pull_container_images images - local -ra aro_services=( + local -ra gateway_services=( aro-gateway auoms azsecd @@ -454,23 +99,7 @@ enable_aro_services() { chronyd fluentbit ) - log "enabling gateway services ${aro_services[*]}" - # shellcheck disable=SC2068 - for service in ${aro_services[@]}; do - log "Enabling $service now" - systemctl enable "$service.service" - done -} -# configure_service_fluentbit -configure_service_fluentbit() { - log "starting" - log "configuring fluentbit service" - - mkdir -p /etc/fluentbit/ - mkdir -p /var/lib/fluent - - local -r fluentbit_conf_filename='/etc/fluentbit/fluentbit.conf' local -r fluentbit_conf_file="[INPUT] Name systemd Tag journald @@ -488,277 +117,28 @@ DB /var/lib/fluent/journaldb Match * Port 29230" - write_file fluentbit_conf_filename fluentbit_conf_file true - - local -r sysconfig_fluentbit_filename='/etc/sysconfig/fluentbit' - local -r sysconfig_fluentbit_file="FLUENTBITIMAGE=$FLUENTBITIMAGE" - - write_file sysconfig_fluentbit_filename sysconfig_fluentbit_file true - - local -r fluentbit_service_filename='/etc/systemd/system/fluentbit.service' - - local -r fluentbit_service_file="[Unit] -After=network-online.target -Wants=network-online.target -StartLimitIntervalSec=0 - -[Service] -RestartSec=1s -EnvironmentFile=/etc/sysconfig/fluentbit -ExecStartPre=-/usr/bin/docker rm -f %N -ExecStart=/usr/bin/docker run \ - --security-opt label=disable \ - --entrypoint /opt/td-agent-bit/bin/td-agent-bit \ - --net=host \ - --hostname %H \ - --name %N \ - --rm \ - --cap-drop net_raw \ - -v /etc/fluentbit/fluentbit.conf:/etc/fluentbit/fluentbit.conf \ - -v /var/lib/fluent:/var/lib/fluent:z \ - -v /var/log/journal:/var/log/journal:ro \ - -v /etc/machine-id:/etc/machine-id:ro \ - $FLUENTBITIMAGE \ - -c /etc/fluentbit/fluentbit.conf - -ExecStop=/usr/bin/docker stop %N -Restart=always -RestartSec=5 -StartLimitInterval=0 - -[Install] -WantedBy=multi-user.target" - - write_file fluentbit_conf_filename fluentbit_conf_file true -} - -# configure_certs -configure_certs() { - log "starting" - - mkdir /etc/aro-rp - base64 -d <<<"$ADMINAPICABUNDLE" >/etc/aro-rp/admin-ca-bundle.pem - if [[ -n "$ARMAPICABUNDLE" ]]; then - base64 -d <<<"$ARMAPICABUNDLE" >/etc/aro-rp/arm-ca-bundle.pem - fi - chown -R 1000:1000 /etc/aro-rp - - # setting MONITORING_GCS_AUTH_ID_TYPE=AuthKeyVault seems to have caused mdsd not - # to honour SSL_CERT_FILE any more, heaven only knows why. - mkdir -p /usr/lib/ssl/certs - csplit -f /usr/lib/ssl/certs/cert- -b %03d.pem /etc/pki/tls/certs/ca-bundle.crt /^$/1 "{*}" >/dev/null - c_rehash /usr/lib/ssl/certs - -# we leave clientId blank as long as only 1 managed identity assigned to vmss -# if we have more than 1, we will need to populate with clientId used for off-node scanning - local -r nodescan_agent_filename="/etc/default/vsa-nodescan-agent.config" - local -r nodescan_agent_file="{ - \"Nice\": 19, - \"Timeout\": 10800, - \"ClientId\": \"\", - \"TenantId\": $AZURESECPACKVSATENANTID, - \"QualysStoreBaseUrl\": $AZURESECPACKQUALYSURL, - \"ProcessTimeout\": 300, - \"CommandDelay\": 0 - }" - - write_file nodescan_agent_filename nodescan_agent_file true -} - -# configure_service_mdm -configure_service_mdm() { - log "starting" - log "configuring mdm service" - - local -r sysconfig_mdm_filename="/etc/sysconfig/mdm" - local -r sysconfig_mdm_file="MDMFRONTENDURL='$MDMFRONTENDURL' -MDMIMAGE='$MDMIMAGE' -MDMSOURCEENVIRONMENT='$LOCATION' -MDMSOURCEROLE=gateway -MDMSOURCEROLEINSTANCE=\"$(hostname)\"" - - write_file sysconfig_mdm_filename sysconfig_mdm_file true - - mkdir -p /var/etw - local -r mdm_service_filename="/etc/systemd/system/mdm.service" - local -r mdm_service_file="[Unit] -After=network-online.target -Wants=network-online.target - -[Service] -EnvironmentFile=/etc/sysconfig/mdm -ExecStartPre=-/usr/bin/docker rm -f %N -ExecStart=/usr/bin/docker run \ - --entrypoint /usr/sbin/MetricsExtension \ - --hostname %H \ - --name %N \ - --rm \ - --cap-drop net_raw \ - -m 2g \ - -v /etc/mdm.pem:/etc/mdm.pem \ - -v /var/etw:/var/etw:z \ - $MDMIMAGE \ - -CertFile /etc/mdm.pem \ - -FrontEndUrl $MDMFRONTENDURL \ - -Logger Console \ - -LogLevel Warning \ - -PrivateKeyFile /etc/mdm.pem \ - -SourceEnvironment $MDMSOURCEENVIRONMENT \ - -SourceRole $MDMSOURCEROLE \ - -SourceRoleInstance $MDMSOURCEROLEINSTANCE -ExecStop=/usr/bin/docker stop %N -Restart=always -RestartSec=1 -StartLimitInterval=0 - -[Install] -WantedBy=multi-user.target" - - write_file mdm_service_filename mdm_service_file true -} - -# configure_timers_mdm_mdsd -configure_timers_mdm_mdsd() { - log "starting" - - for var in "mdsd" "mdm"; do - local download_creds_service_filename="/etc/systemd/system/download-$var-credentials.service" - local download_creds_service_file="[Unit] -Description=Periodic $var credentials refresh - -[Service] -Type=oneshot -ExecStart=/usr/local/bin/download-credentials.sh $var" - - write_file download_creds_service_filename download_creds_service_file true - - local download_creds_timer_filename="/etc/systemd/system/download-$var-credentials.timer" - local download_creds_timer_file="[Unit] -Description=Periodic $var credentials refresh -After=network-online.target -Wants=network-online.target - -[Timer] -OnBootSec=0min -OnCalendar=0/12:00:00 -AccuracySec=5s - -[Install] -WantedBy=timers.target" - - write_file download_creds_timer_filename download_creds_timer_file true - done - - local -r download_creds_script_filename="/usr/local/bin/download-credentials.sh" - local -r download_creds_script_file="#!/bin/bash -set -eu - -COMPONENT=\$1 -echo \"Download \$COMPONENT credentials\" - -TEMP_DIR=\"\$(mktemp -d)\" -export AZURE_CONFIG_DIR=\"\$(mktemp -d)\" - -echo \"Logging into Azure...\" -RETRIES=3 -while [[ \$RETRIES -gt 0 ]]; do - if az login -i --allow-no-subscriptions - then - echo \"az login successful\" - break - else - echo \"az login failed. Retrying...\" - let RETRIES-=1 - sleep 5 - fi -done - -trap \"cleanup\" EXIT - -cleanup() { - az logout - [[ \$TEMP_DIR =~ /tmp/.+ ]] && rm -rf \$TEMP_DIR - [[ \$AZURE_CONFIG_DIR =~ /tmp/.+ ]] && rm -rf \$AZURE_CONFIG_DIR -} - -if [[ \$COMPONENT = \"mdm\" ]]; then - CURRENT_CERT_FILE=\"/etc/mdm.pem\" -elif [[ \$COMPONENT\ = \"mdsd\" ]]; then - CURRENT_CERT_FILE=\"/var/lib/waagent/Microsoft.Azure.KeyVault.Store/mdsd.pem\" -else - echo Invalid usage && exit 1 -fi - -SECRET_NAME=\"gwy-\${COMPONENT}\" -NEW_CERT_FILE=\"\$TEMP_DIR/\$COMPONENT.pem\" -for attempt in {1..5}; do - az keyvault \ - secret \ - download \ - --file \"\$NEW_CERT_FILE\" \ - --id \"https://$KEYVAULTPREFIX-gwy.$KEYVAULTDNSSUFFIX/secrets/\$SECRET_NAME\" \ - && break - if [[ \$attempt -lt 5 ]]; then sleep 10; else exit 1; fi -done - -if [ -f \$NEW_CERT_FILE ]; then - if [[ \$COMPONENT = \"mdsd\" ]]; then - chown syslog:syslog \$NEW_CERT_FILE - else - sed -i -ne '1,/END CERTIFICATE/ p' \$NEW_CERT_FILE - fi - - new_cert_sn=\"\$(openssl x509 -in \"\$NEW_CERT_FILE\" -noout -serial | awk -F= '{print \$2}')\" - current_cert_sn=\"\$(openssl x509 -in \"\$CURRENT_CERT_FILE\" -noout -serial | awk -F= '{print \$2}')\" - if [[ ! -z \$new_cert_sn ]] && [[ \$new_cert_sn != \"\$current_cert_sn\" ]]; then - echo updating certificate for \$COMPONENT - chmod 0600 \$NEW_CERT_FILE - mv \$NEW_CERT_FILE \$CURRENT_CERT_FILE - fi -else - echo Failed to refresh certificate for \$COMPONENT && exit 1 -fi" - - write_file download_creds_script_filename download_creds_script_file true - - chmod u+x /usr/local/bin/download-credentials.sh - - systemctl enable download-mdsd-credentials.timer - systemctl enable download-mdm-credentials.timer - - /usr/local/bin/download-credentials.sh mdsd - /usr/local/bin/download-credentials.sh mdm - - local -r MDSDCERTIFICATESAN="$(openssl x509 -in /var/lib/waagent/Microsoft.Azure.KeyVault.Store/mdsd.pem -noout -subject | sed -e 's/.*CN = //')" - local -r watch_mdm_creds_service_filename="/etc/systemd/system/watch-mdm-credentials.service" - local -r watch_mdm_creds_service_file="[Unit] -Description=Watch for changes in mdm.pem and restarts the mdm service - -[Service] -Type=oneshot -ExecStart=/usr/bin/systemctl restart mdm.service - -[Install] -WantedBy=multi-user.target" - - write_file watch_mdm_creds_service_filename watch_mdm_creds_service_file true - - local -r watch_mdm_creds_path_filename='/etc/systemd/system/watch-mdm-credentials.path' - local -r watch_mdm_creds_path_file='[Path] -PathModified=/etc/mdm.pem - -[Install] -WantedBy=multi-user.target' + local -r aro_dbtoken_service_conf_file="ACR_RESOURCE_ID='$ACRRESOURCEID' +DATABASE_ACCOUNT_NAME='$DATABASEACCOUNTNAME' +AZURE_DBTOKEN_CLIENT_ID='$DBTOKENCLIENTID' +DBTOKEN_URL='$DBTOKENURL' +MDM_ACCOUNT='$RPMDMACCOUNT' +MDM_NAMESPACE=Gateway +GATEWAY_DOMAINS='$GATEWAYDOMAINS' +GATEWAY_FEATURES='$GATEWAYFEATURES' +RPIMAGE='$RPIMAGE'" - write_file watch_mdm_creds_path_filename watch_mdm_creds_path_file true + local -n mdsd_gateway_version="$GATEWAYMDSDCONFIGVERSION" - local -r watch_mdm_creds='watch-mdm-credentials.path' - systemctl enable "$watch_mdm_creds" || abort "failed to enable $watch_mdm_creds" - systemctl start "$watch_mdm_creds" || abort "failed to start $watch_mdm_creds" + configure_service_fluentbit fluentbit_conf_file fluentbit_image + configure_service_mdm + configure_timers_mdm_mdsd + configure_service_gateway gateway_log_file + configure_service_mdsd + reboot_vm } -# configure_service_aro_gateway -configure_service_aro_gateway() { +# configure_service_aro_rp +configure_service_gateway() { local -n log_dir="$1" log "starting" @@ -827,7 +207,7 @@ ExecStart=/usr/bin/docker run \ -v /run/systemd/journal:/run/systemd/journal \ -v /var/etw:/var/etw:z \ -v ${log_dir}:/ctr.log:z \ - \$RPIMAGE \ + $RPIMAGE \ gateway ExecStop=/usr/bin/docker stop -t 3600 %N TimeoutStopSec=3600 @@ -842,66 +222,6 @@ WantedBy=multi-user.target write_file aro_gateway_service_filename aro_gateway_service_file true } -# configure_service_aro_dbtoken -configure_service_aro_dbtoken() { - log "starting" - - local -r aro_dbtoken_service_conf_filename='/etc/sysconfig/aro-dbtoken' - local -r aro_dbtoken_service_conf_file="ACR_RESOURCE_ID='$ACRRESOURCEID' -DATABASE_ACCOUNT_NAME='$DATABASEACCOUNTNAME' -AZURE_DBTOKEN_CLIENT_ID='$DBTOKENCLIENTID' -DBTOKEN_URL='$DBTOKENURL' -MDM_ACCOUNT='$RPMDMACCOUNT' -MDM_NAMESPACE=Gateway -GATEWAY_DOMAINS='$GATEWAYDOMAINS' -GATEWAY_FEATURES='$GATEWAYFEATURES' -RPIMAGE='$RPIMAGE'" - - write_file aro_dbtoken_service_conf_filename aro_dbtoken_service_conf_file true - - local -r aro_dbtoken_service_filename='/etc/systemd/system/aro-dbtoken.service' - local -r aro_dbtoken_service_file="[Unit] -After=network-online.target -Wants=network-online.target - -[Service] -EnvironmentFile=/etc/sysconfig/aro-gateway -ExecStartPre=-/usr/bin/docker rm -f %N -ExecStartPre=/usr/bin/mkdir -p ${gateway_logdir} -ExecStart=/usr/bin/docker run \ - --hostname %H \ - --name %N \ - --rm \ - --cap-drop net_raw \ - -e ACR_RESOURCE_ID \ - -e DATABASE_ACCOUNT_NAME \ - -e AZURE_DBTOKEN_CLIENT_ID \ - -e DBTOKEN_URL \ - -e GATEWAY_DOMAINS \ - -e GATEWAY_FEATURES \ - -e MDM_ACCOUNT \ - -e MDM_NAMESPACE \ - -m 2g \ - -p 80:8080 \ - -p 8081:8081 \ - -p 443:8443 \ - -v /run/systemd/journal:/run/systemd/journal \ - -v /var/etw:/var/etw:z \ - -v ${gateway_logdir}:/ctr.log:z \ - \$RPIMAGE \ - gateway -ExecStop=/usr/bin/docker stop -t 3600 %N -TimeoutStopSec=3600 -Restart=always -RestartSec=1 -StartLimitInterval=0 - -[Install] -WantedBy=multi-user.target" - - write_file aro_dbtoken_service_filename aro_dbtoken_service_file true -} - # configure_service_mdsd configure_service_mdsd() { log "starting" @@ -925,7 +245,7 @@ export MONITORING_GCS_REGION='$LOCATION' export MONITORING_GCS_AUTH_ID_TYPE=AuthKeyVault export MONITORING_GCS_AUTH_ID='$MDSDCERTIFICATESAN' export MONITORING_GCS_NAMESPACE='$RPMDSDNAMESPACE' -export MONITORING_CONFIG_VERSION='$GATEWAYMDSDCONFIGVERSION' +export MONITORING_CONFIG_VERSION='' export MONITORING_USE_GENEVA_CONFIG_SERVICE=true export MONITORING_TENANT='$LOCATION' @@ -938,66 +258,6 @@ export MDSD_MSGPACK_SORT_COLUMNS=1\"" } -# run_azsecd_config_scan -run_azsecd_config_scan() { - log "starting" - - local -ar configs=( - "baseline" - "clamav" - "software" - ) - - log "Scanning configuration files ${configs[*]}" - # shellcheck disable=SC2068 - for scan in ${configs[@]}; do - log "Scanning config file $scan now" - /usr/local/bin/azsecd config -s "$scan" -d P1D - done -} - -# write_file -# Args -# 1) filename - string -# 2) file_contents - string -# 3) clobber - boolean; optional - defaults to false -write_file() { - local -n filename="$1" - local -n file_contents="$2" - local -r clobber="${3:-false}" - - if $clobber; then - log "Overwriting file $filename" - echo "$file_contents" > "$filename" - else - log "Appending to $filename" - echo "$file_contents" >> "$filename" - fi -} - -# reboot_vm restores all selinux file contexts, waits 30 seconds then reboots -reboot_vm() { - log "starting" - - configure_selinux "true" - (sleep 30 && log "rebooting vm now"; reboot) & -} - -# log is a wrapper for echo that includes the function name -log() { - local -r msg="${1:-"log message is empty"}" - local -r stack_level="${2:-1}" - echo "${FUNCNAME[${stack_level}]}: ${msg}" -} - -# abort is a wrapper for log that exits with an error code -abort() { - local -ri origin_stacklevel=2 - log "${1}" "$origin_stacklevel" - log "Exiting" - exit 1 -} - export AZURE_CLOUD_NAME="${AZURECLOUDNAME:?"Failed to carry over variables"}" main "$@" diff --git a/pkg/deploy/generator/scripts/rpVMSS.sh b/pkg/deploy/generator/scripts/rpVMSS.sh index 424c40af8bf..c7fd67f2d30 100644 --- a/pkg/deploy/generator/scripts/rpVMSS.sh +++ b/pkg/deploy/generator/scripts/rpVMSS.sh @@ -70,116 +70,16 @@ main() { configure_firewalld_rules enable_ports - MDMIMAGE="${RPIMAGE%%/*}/${MDMIMAGE##*/}" + local -r mdmimage="${RPIMAGE%%/*}/${MDMIMAGE##*/}" + local -r rpimage="$RPIMAGE" + local -r fluentbit_image="$FLUENTBITIMAGE" local -ra images=( - "$MDMIMAGE" - "$RPIMAGE" - "$FLUENTBITIMAGE" + "$mdmimage" + "$rpimage" + "$fluentbit_image" ) - pull_container_images images - local -ra aro_services=( - "aro-dbtoken" - "aro-monitor" - "aro-portal" - "aro-rp" - "auoms" - "azsecd" - "azsecmond" - "mdsd" - "mdm" - "chronyd" - "fluentbit" - ) - - configure_aro_services - enable_services - - enable_services aro_services - - reboot_vm -} - -# configure_rpm_repos -configure_rpm_repos() { - log "starting" - - configure_rhui_repo "$1" - create_azure_rpm_repos "$1" -} - -# configure_disk_partitions -configure_disk_partitions() { - log "starting" - log "extending partition table" - - # Linux block devices are inconsistently named - # it's difficult to tie the lvm pv to the physical disk using /dev/disk files, which is why lvs is used here - physical_disk="$(lvs -o devices -a | head -n2 | tail -n1 | cut -d ' ' -f 3 | cut -d \( -f 1 | tr -d '[:digit:]')" - growpart "$physical_disk" 2 - - log "extending filesystems" - log "extending root lvm" - lvextend -l +20%FREE /dev/rootvg/rootlv - log "growing root filesystem" - xfs_growfs / - - log "extending var lvm" - lvextend -l +100%FREE /dev/rootvg/varlv - log "growing var filesystem" - xfs_growfs /var -} - -# create_azure_rpm_repos creates /etc/yum.repos.d/azure.repo repository file -create_azure_rpm_repos() { - log "starting" - - local -r azure_repo_filename='/etc/yum.repos.d/azure.repo' - local -r azure_repo_file='[azure-cli] -name=azure-cli -baseurl=https://packages.microsoft.com/yumrepos/azure-cli -enabled=yes -gpgcheck=yes - -[azurecore] -name=azurecore -baseurl=https://packages.microsoft.com/yumrepos/azurecore -enabled=yes -gpgcheck=no' - - write_file azure_repo_filename azure_repo_file true -} - -# configure_aro_services creates, configures, and enables the following systemd services and timers -# services -# fluentbit -# mdm -# mdsd -# arp-rp -# aro-dbtoken -# aro-monitor -# aro-portal -configure_aro_services() { - configure_service_fluentbit - configure_service_mdm - configure_timers_mdm_mdsd - configure_service_aro_rp - configure_service_aro_dbtoken - configure_service_aro_monitor - configure_service_aro_portal - configure_service_mdsd -} - -# configure_service_fluentbit -configure_service_fluentbit() { - log "starting" - log "configuring fluentbit service" - - mkdir -p /etc/fluentbit/ - mkdir -p /var/lib/fluent - - local -r fluentbit_conf_filename='/etc/fluentbit/fluentbit.conf' local -r fluentbit_conf_file="[INPUT] Name systemd Tag journald @@ -214,273 +114,70 @@ DB /var/lib/fluent/journaldb Match * Port 29230" - write_file fluentbit_conf_filename fluentbit_conf_file true - - local -r sysconfig_fluentbit_filename='/etc/sysconfig/fluentbit' - local -r sysconfig_fluentbit_file="FLUENTBITIMAGE=$FLUENTBITIMAGE" - - write_file sysconfig_fluentbit_filename sysconfig_fluentbit_file true - - local -r fluentbit_service_filename='/etc/systemd/system/fluentbit.service' - - local -r fluentbit_service_file="[Unit] -After=network-online.target -Wants=network-online.target -StartLimitIntervalSec=0 - -[Service] -RestartSec=1s -EnvironmentFile=/etc/sysconfig/fluentbit -ExecStartPre=-/usr/bin/docker rm -f %N -ExecStart=/usr/bin/docker run \ - --security-opt label=disable \ - --entrypoint /opt/td-agent-bit/bin/td-agent-bit \ - --net=host \ - --hostname %H \ - --name %N \ - --rm \ - --cap-drop net_raw \ - -v /etc/fluentbit/fluentbit.conf:/etc/fluentbit/fluentbit.conf \ - -v /var/lib/fluent:/var/lib/fluent:z \ - -v /var/log/journal:/var/log/journal:ro \ - -v /etc/machine-id:/etc/machine-id:ro \ - $FLUENTBITIMAGE \ - -c /etc/fluentbit/fluentbit.conf - -ExecStop=/usr/bin/docker stop %N -Restart=always -RestartSec=5 -StartLimitInterval=0 + local -r aro_dbtoken_service_conf_file="DATABASE_ACCOUNT_NAME='$DATABASEACCOUNTNAME' +AZURE_DBTOKEN_CLIENT_ID='$DBTOKENCLIENTID' +AZURE_GATEWAY_SERVICE_PRINCIPAL_ID='$GATEWAYSERVICEPRINCIPALID' +KEYVAULT_PREFIX='$KEYVAULTPREFIX' +MDM_ACCOUNT='$RPMDMACCOUNT' +MDM_NAMESPACE=DBToken +RPIMAGE='$RPIMAGE'" -[Install] -WantedBy=multi-user.target" + # TODO pass this to mdsd service call + configure_service_fluentbit fluentbit_conf_file fluentbit_image + configure_service_mdm + configure_timers_mdm_mdsd + configure_service_aro_rp + configure_service_aro_dbtoken + configure_service_aro_monitor + configure_service_aro_portal + local -r mdsd_rp_version="$RPMDSDCONFIGVERSION" + configure_service_mdsd mdsd_rp_version - write_file fluentbit_service_filename fluentbit_service_file true -} + local -ra aro_services=( + "aro-dbtoken" + "aro-monitor" + "aro-portal" + "aro-rp" + "auoms" + "azsecd" + "azsecmond" + "mdsd" + "mdm" + "chronyd" + "fluentbit" + ) -# configure_certs -configure_certs() { - log "starting" + enable_services aro_services - mkdir /etc/aro-rp - base64 -d <<<"$ADMINAPICABUNDLE" >/etc/aro-rp/admin-ca-bundle.pem - if [[ -n "$ARMAPICABUNDLE" ]]; then - base64 -d <<<"$ARMAPICABUNDLE" >/etc/aro-rp/arm-ca-bundle.pem - fi - chown -R 1000:1000 /etc/aro-rp - - # setting MONITORING_GCS_AUTH_ID_TYPE=AuthKeyVault seems to have caused mdsd not - # to honour SSL_CERT_FILE any more, heaven only knows why. - mkdir -p /usr/lib/ssl/certs - csplit -f /usr/lib/ssl/certs/cert- -b %03d.pem /etc/pki/tls/certs/ca-bundle.crt /^$/1 "{*}" >/dev/null - c_rehash /usr/lib/ssl/certs - -# we leave clientId blank as long as only 1 managed identity assigned to vmss -# if we have more than 1, we will need to populate with clientId used for off-node scanning - local -r nodescan_agent_filename="/etc/default/vsa-nodescan-agent.config" - local -r nodescan_agent_file="{ - \"Nice\": 19, - \"Timeout\": 10800, - \"ClientId\": \"\", - \"TenantId\": $AZURESECPACKVSATENANTID, - \"QualysStoreBaseUrl\": $AZURESECPACKQUALYSURL, - \"ProcessTimeout\": 300, - \"CommandDelay\": 0 - }" - - write_file nodescan_agent_filename nodescan_agent_file true + reboot_vm } -# configure_service_mdm -configure_service_mdm() { +# configure_rpm_repos +configure_rpm_repos() { log "starting" - log "configuring mdm service" - - local -r sysconfig_mdm_filename="/etc/sysconfig/mdm" - local -r sysconfig_mdm_file="MDMFRONTENDURL='$MDMFRONTENDURL' -MDMIMAGE='$MDMIMAGE' -MDMSOURCEENVIRONMENT='$LOCATION' -MDMSOURCEROLE=rp -MDMSOURCEROLEINSTANCE=\"$(hostname)\"" - - write_file sysconfig_mdm_filename sysconfig_mdm_file true - mkdir -p /var/etw - local -r mdm_service_filename="/etc/systemd/system/mdm.service" - local -r mdm_service_file="[Unit] -After=network-online.target -Wants=network-online.target - -[Service] -EnvironmentFile=/etc/sysconfig/mdm -ExecStartPre=-/usr/bin/docker rm -f %N -ExecStart=/usr/bin/docker run \ - --entrypoint /usr/sbin/MetricsExtension \ - --hostname %H \ - --name %N \ - --rm \ - --cap-drop net_raw \ - -m 2g \ - -v /etc/mdm.pem:/etc/mdm.pem \ - -v /var/etw:/var/etw:z \ - $MDMIMAGE \ - -CertFile /etc/mdm.pem \ - -FrontEndUrl $MDMFRONTENDURL \ - -Logger Console \ - -LogLevel Warning \ - -PrivateKeyFile /etc/mdm.pem \ - -SourceEnvironment $MDMSOURCEENVIRONMENT \ - -SourceRole $MDMSOURCEROLE \ - -SourceRoleInstance $MDMSOURCEROLEINSTANCE -ExecStop=/usr/bin/docker stop %N -Restart=always -RestartSec=1 -StartLimitInterval=0 - -[Install] -WantedBy=multi-user.target" - - write_file mdm_service_filename mdm_service_file true + configure_rhui_repo "$1" + create_azure_rpm_repos } -# configure_timers_mdm_mdsd -configure_timers_mdm_mdsd() { +# create_azure_rpm_repos creates /etc/yum.repos.d/azure.repo repository file +create_azure_rpm_repos() { log "starting" - for var in "mdsd" "mdm"; do - local download_creds_service_filename="/etc/systemd/system/download-$var-credentials.service" - local download_creds_service_file="[Unit] -Description=Periodic $var credentials refresh - -[Service] -Type=oneshot -ExecStart=/usr/local/bin/download-credentials.sh $var" - - write_file download_creds_service_filename download_creds_service_file true - - local download_creds_timer_filename="/etc/systemd/system/download-$var-credentials.timer" - local download_creds_timer_file="[Unit] -Description=Periodic $var credentials refresh -After=network-online.target -Wants=network-online.target - -[Timer] -OnBootSec=0min -OnCalendar=0/12:00:00 -AccuracySec=5s - -[Install] -WantedBy=timers.target" - - write_file download_creds_timer_filename download_creds_timer_file true - done - - local -r download_creds_script_filename="/usr/local/bin/download-credentials.sh" - local -r download_creds_script_file="#!/bin/bash -set -eu - -COMPONENT=\$1 -echo \"Download \$COMPONENT credentials\" - -TEMP_DIR=\"\$(mktemp -d)\" -export AZURE_CONFIG_DIR=\"\$(mktemp -d)\" - -echo \"Logging into Azure...\" -RETRIES=3 -while [[ \$RETRIES -gt 0 ]]; do - if az login -i --allow-no-subscriptions - then - echo \"az login successful\" - break - else - echo \"az login failed. Retrying...\" - let RETRIES-=1 - sleep 5 - fi -done - -trap \"cleanup\" EXIT - -cleanup() { - az logout - [[ \$TEMP_DIR =~ /tmp/.+ ]] && rm -rf \$TEMP_DIR - [[ \$AZURE_CONFIG_DIR =~ /tmp/.+ ]] && rm -rf \$AZURE_CONFIG_DIR -} - -if [[ \$COMPONENT = \"mdm\" ]]; then - CURRENT_CERT_FILE=\"/etc/mdm.pem\" -elif [[ \$COMPONENT\ = \"mdsd\" ]]; then - CURRENT_CERT_FILE=\"/var/lib/waagent/Microsoft.Azure.KeyVault.Store/mdsd.pem\" -else - echo Invalid usage && exit 1 -fi - -SECRET_NAME=\"rp-\${COMPONENT}\" -NEW_CERT_FILE=\"\$TEMP_DIR/\$COMPONENT.pem\" -for attempt in {1..5}; do - az keyvault \ - secret \ - download \ - --file \"\$NEW_CERT_FILE\" \ - --id \"https://$KEYVAULTPREFIX-svc.$KEYVAULTDNSSUFFIX/secrets/\$SECRET_NAME\" \ - && break - if [[ \$attempt -lt 5 ]]; then sleep 10; else exit 1; fi -done - -if [ -f \$NEW_CERT_FILE ]; then - if [[ \$COMPONENT = \"mdsd\" ]]; then - chown syslog:syslog \$NEW_CERT_FILE - else - sed -i -ne '1,/END CERTIFICATE/ p' \$NEW_CERT_FILE - fi - - new_cert_sn=\"\$(openssl x509 -in \"\$NEW_CERT_FILE\" -noout -serial | awk -F= '{print \$2}')\" - current_cert_sn=\"\$(openssl x509 -in \"\$CURRENT_CERT_FILE\" -noout -serial | awk -F= '{print \$2}')\" - if [[ ! -z \$new_cert_sn ]] && [[ \$new_cert_sn != \"\$current_cert_sn\" ]]; then - echo updating certificate for \$COMPONENT - chmod 0600 \$NEW_CERT_FILE - mv \$NEW_CERT_FILE \$CURRENT_CERT_FILE - fi -else - echo Failed to refresh certificate for \$COMPONENT && exit 1 -fi" - - write_file download_creds_script_filename download_creds_script_file true - - chmod u+x /usr/local/bin/download-credentials.sh - - systemctl enable download-mdsd-credentials.timer - systemctl enable download-mdm-credentials.timer - - /usr/local/bin/download-credentials.sh mdsd - /usr/local/bin/download-credentials.sh mdm - - local -r MDSDCERTIFICATESAN="$(openssl x509 -in /var/lib/waagent/Microsoft.Azure.KeyVault.Store/mdsd.pem -noout -subject | sed -e 's/.*CN = //')" - local -r watch_mdm_creds_service_filename="/etc/systemd/system/watch-mdm-credentials.service" - local -r watch_mdm_creds_service_file="[Unit] -Description=Watch for changes in mdm.pem and restarts the mdm service - -[Service] -Type=oneshot -ExecStart=/usr/bin/systemctl restart mdm.service - -[Install] -WantedBy=multi-user.target" - - write_file watch_mdm_creds_service_filename watch_mdm_creds_service_file true - - local -r watch_mdm_creds_path_filename='/etc/systemd/system/watch-mdm-credentials.path' - local -r watch_mdm_creds_path_file='[Path] -PathModified=/etc/mdm.pem - -[Install] -WantedBy=multi-user.target' + local -r azure_repo_filename='/etc/yum.repos.d/azure.repo' + local -r azure_repo_file='[azure-cli] +name=azure-cli +baseurl=https://packages.microsoft.com/yumrepos/azure-cli +enabled=yes +gpgcheck=yes - write_file watch_mdm_creds_path_filename watch_mdm_creds_path_file true +[azurecore] +name=azurecore +baseurl=https://packages.microsoft.com/yumrepos/azurecore +enabled=yes +gpgcheck=no' - local -r watch_mdm_creds='watch-mdm-credentials.path' - systemctl enable "$watch_mdm_creds" || abort "failed to enable $watch_mdm_creds" - systemctl start "$watch_mdm_creds" || abort "failed to start $watch_mdm_creds" + write_file azure_repo_filename azure_repo_file true } # configure_service_aro_rp @@ -573,58 +270,6 @@ WantedBy=multi-user.target" write_file aro_rp_service_filename aro_rp_service_file true } -# configure_service_aro_dbtoken -configure_service_aro_dbtoken() { - log "starting" - - local -r aro_dbtoken_service_conf_filename='/etc/sysconfig/aro-dbtoken' - local -r aro_dbtoken_service_conf_file="DATABASE_ACCOUNT_NAME='$DATABASEACCOUNTNAME' -AZURE_DBTOKEN_CLIENT_ID='$DBTOKENCLIENTID' -AZURE_GATEWAY_SERVICE_PRINCIPAL_ID='$GATEWAYSERVICEPRINCIPALID' -KEYVAULT_PREFIX='$KEYVAULTPREFIX' -MDM_ACCOUNT='$RPMDMACCOUNT' -MDM_NAMESPACE=DBToken -RPIMAGE='$RPIMAGE'" - - write_file aro_dbtoken_service_conf_filename aro_dbtoken_service_conf_file true - - local -r aro_dbtoken_service_filename='/etc/systemd/system/aro-dbtoken.service' - local -r aro_dbtoken_service_file="[Unit] -After=network-online.target -Wants=network-online.target - -[Service] -EnvironmentFile=/etc/sysconfig/aro-dbtoken -ExecStartPre=-/usr/bin/docker rm -f %N -ExecStart=/usr/bin/docker run \ - --hostname %H \ - --name %N \ - --rm \ - --cap-drop net_raw \ - -e AZURE_GATEWAY_SERVICE_PRINCIPAL_ID \ - -e DATABASE_ACCOUNT_NAME \ - -e AZURE_DBTOKEN_CLIENT_ID \ - -e KEYVAULT_PREFIX \ - -e MDM_ACCOUNT \ - -e MDM_NAMESPACE \ - -m 2g \ - -p 445:8445 \ - -v /run/systemd/journal:/run/systemd/journal \ - -v /var/etw:/var/etw:z \ - $RPIMAGE \ - dbtoken -ExecStop=/usr/bin/docker stop -t 3600 %N -TimeoutStopSec=3600 -Restart=always -RestartSec=1 -StartLimitInterval=0 - -[Install] -WantedBy=multi-user.target" - - write_file aro_dbtoken_service_filename aro_dbtoken_service_file true -} - # configure_service_aro_monitor configure_service_aro_monitor() { log "starting" @@ -748,61 +393,6 @@ WantedBy=multi-user.target" write_file aro_portal_service_filename aro_portal_service_file true } -# configure_service_mdsd -configure_service_mdsd() { - local -n mdsd - log "starting" - - local -r mdsd_service_dir="/etc/systemd/system/mdsd.service.d" - mkdir -p "$mdsd_service_dir" - - local -r mdsd_override_conf_filename="$mdsd_service_dir/override.conf" - local -r mdsd_override_conf_file="[Unit] -After=network-online.target" - - write_file mdsd_override_conf_filename mdsd_override_conf_file true - - local -r default_mdsd_filename="/etc/default/mdsd" - local -r default_mdsd_file="MDSD_ROLE_PREFIX=/var/run/mdsd/default -MDSD_OPTIONS=\"-A -d -r \$MDSD_ROLE_PREFIX\" - -export MONITORING_GCS_ENVIRONMENT='$MDSDENVIRONMENT' -export MONITORING_GCS_ACCOUNT='$RPMDSDACCOUNT' -export MONITORING_GCS_REGION='$LOCATION' -export MONITORING_GCS_AUTH_ID_TYPE=AuthKeyVault -export MONITORING_GCS_AUTH_ID='$MDSDCERTIFICATESAN' -export MONITORING_GCS_NAMESPACE='$RPMDSDNAMESPACE' -export MONITORING_CONFIG_VERSION='$RPMDSDCONFIGVERSION' -export MONITORING_USE_GENEVA_CONFIG_SERVICE=true - -export MONITORING_TENANT='$LOCATION' -export MONITORING_ROLE=rp -export MONITORING_ROLE_INSTANCE=\"$(hostname)\" - -export MDSD_MSGPACK_SORT_COLUMNS=1\"" - - write_file default_mdsd_filename default_mdsd_file true - -} - -# run_azsecd_config_scan -run_azsecd_config_scan() { - log "starting" - - local -ar configs=( - "baseline" - "clamav" - "software" - ) - - log "Scanning configuration files ${configs[*]}" - # shellcheck disable=SC2068 - for scan in ${configs[@]}; do - log "Scanning config file $scan now" - /usr/local/bin/azsecd config -s "$scan" -d P1D - done -} - export AZURE_CLOUD_NAME="${AZURECLOUDNAME:?"Failed to carry over variables"}" main "$@" From d914aef195e8970e18adcd1baba0df900c420875 Mon Sep 17 00:00:00 2001 From: Steven Fairchild Date: Fri, 19 Apr 2024 16:39:09 -0400 Subject: [PATCH 33/38] WIP Functional rpVMSS.sh and common.sh files --- pkg/deploy/generator/scripts/common.sh | 157 ++++++------------------- pkg/deploy/generator/scripts/rpVMSS.sh | 104 ++++++++++++---- 2 files changed, 117 insertions(+), 144 deletions(-) diff --git a/pkg/deploy/generator/scripts/common.sh b/pkg/deploy/generator/scripts/common.sh index f69e30dbf2c..c1db1d0c2f6 100644 --- a/pkg/deploy/generator/scripts/common.sh +++ b/pkg/deploy/generator/scripts/common.sh @@ -131,7 +131,9 @@ configure_firewalld_rules() { } # configure_logrotate clobbers /etc/logrotate.conf -# TODO add writing of dropin files +# args: +# 1) dropin_files - associative array. Key name dictates filenames written to /etc/logrotate.d. +# If an empty array is provided, no files will be written configure_logrotate() { local -n dropin_files="$1" log "starting" @@ -228,7 +230,7 @@ enable_services() { # shellcheck disable=SC2068 for service in ${services[@]}; do log "Enabling $service now" - systemctl enable "$service.service" + systemctl enable "$service" done } @@ -377,14 +379,16 @@ configure_certs() { # configure_service_mdm configure_service_mdm() { + local -n role="$1" + local -n image="$2" log "starting" log "configuring mdm service" local -r sysconfig_mdm_filename="/etc/sysconfig/mdm" local -r sysconfig_mdm_file="MDMFRONTENDURL='$MDMFRONTENDURL' -MDMIMAGE='$MDMIMAGE' +MDMIMAGE='$image' MDMSOURCEENVIRONMENT='$LOCATION' -MDMSOURCEROLE=gateway +MDMSOURCEROLE='$role' MDMSOURCEROLEINSTANCE=\"$(hostname)\"" write_file sysconfig_mdm_filename sysconfig_mdm_file true @@ -407,7 +411,7 @@ ExecStart=/usr/bin/docker run \ -m 2g \ -v /etc/mdm.pem:/etc/mdm.pem \ -v /var/etw:/var/etw:z \ - $MDMIMAGE \ + $image \ -CertFile /etc/mdm.pem \ -FrontEndUrl $MDMFRONTENDURL \ -Logger Console \ @@ -429,6 +433,7 @@ WantedBy=multi-user.target" # configure_timers_mdm_mdsd configure_timers_mdm_mdsd() { + local -n component="$1" log "starting" for var in "mdsd" "mdm"; do @@ -493,20 +498,20 @@ cleanup() { if [[ \$COMPONENT = \"mdm\" ]]; then CURRENT_CERT_FILE=\"/etc/mdm.pem\" -elif [[ \$COMPONENT\ = \"mdsd\" ]]; then +elif [[ \$COMPONENT = \"mdsd\" ]]; then CURRENT_CERT_FILE=\"/var/lib/waagent/Microsoft.Azure.KeyVault.Store/mdsd.pem\" else echo Invalid usage && exit 1 fi -SECRET_NAME=\"gwy-\${COMPONENT}\" +SECRET_NAME=\"$component-\${COMPONENT}\" NEW_CERT_FILE=\"\$TEMP_DIR/\$COMPONENT.pem\" for attempt in {1..5}; do az keyvault \ secret \ download \ --file \"\$NEW_CERT_FILE\" \ - --id \"https://$KEYVAULTPREFIX-gwy.$KEYVAULTDNSSUFFIX/secrets/\$SECRET_NAME\" \ + --id \"https://$KEYVAULTPREFIX-$component.$KEYVAULTDNSSUFFIX/secrets/\$SECRET_NAME\" \ && break if [[ \$attempt -lt 5 ]]; then sleep 10; else exit 1; fi done @@ -533,12 +538,8 @@ fi" chmod u+x /usr/local/bin/download-credentials.sh - # TODO place this in enable services section - systemctl enable download-mdsd-credentials.timer - systemctl enable download-mdm-credentials.timer - - /usr/local/bin/download-credentials.sh mdsd - /usr/local/bin/download-credentials.sh mdm + $download_creds_script_filename mdsd + $download_creds_script_filename mdm local -r MDSDCERTIFICATESAN="$(openssl x509 -in /var/lib/waagent/Microsoft.Azure.KeyVault.Store/mdsd.pem -noout -subject | sed -e 's/.*CN = //')" local -r watch_mdm_creds_service_filename="/etc/systemd/system/watch-mdm-credentials.service" @@ -570,31 +571,30 @@ WantedBy=multi-user.target' # configure_service_fluentbit configure_service_fluentbit() { - local -n fluentbit_conf_file="$1" - local -n fluentbit_image="$2" + local -n conf_file="$1" + local -n image="$2" log "starting" log "configuring fluentbit service" - if [[ -n $fluentbit_conf_file ]]; then - abort "$1 fluentbit config file cannot be empty" - elif [[ -n $fluentbit_image ]]; then - abort "$2 fluentbit image cannot be empty" + if [ -z "$conf_file" ]; then + abort "$1 config file cannot be empty" + elif [ -z "$image" ]; then + abort "$2 image cannot be empty" fi mkdir -p /etc/fluentbit/ mkdir -p /var/lib/fluent - local -r fluentbit_conf_filename='/etc/fluentbit/fluentbit.conf' - write_file fluentbit_conf_filename fluentbit_conf_file true - - local -r sysconfig_fluentbit_filename='/etc/sysconfig/fluentbit' - local -r sysconfig_fluentbit_file="FLUENTBITIMAGE=$fluentbit_image" + local -r conf_filename='/etc/fluentbit/fluentbit.conf' + write_file conf_filename conf_file true - write_file sysconfig_fluentbit_filename sysconfig_fluentbit_file true + local -r sysconfig_filename='/etc/sysconfig/fluentbit' + local -r sysconfig_file="FLUENTBITIMAGE=$fluentbit_image" - local -r fluentbit_service_filename='/etc/systemd/system/fluentbit.service' + write_file sysconfig_filename sysconfig_file true - local -r fluentbit_service_file="[Unit] + local -r service_filename='/etc/systemd/system/fluentbit.service' + local -r service_file="[Unit] After=network-online.target Wants=network-online.target StartLimitIntervalSec=0 @@ -615,7 +615,7 @@ ExecStart=/usr/bin/docker run \ -v /var/lib/fluent:/var/lib/fluent:z \ -v /var/log/journal:/var/log/journal:ro \ -v /etc/machine-id:/etc/machine-id:ro \ - $fluentbit_image \ + $image \ -c /etc/fluentbit/fluentbit.conf ExecStop=/usr/bin/docker stop %N @@ -626,99 +626,13 @@ StartLimitInterval=0 [Install] WantedBy=multi-user.target" - write_file fluentbit_service_filename fluentbit_service_file true -} - -# configure_service_aro_dbtoken -configure_service_aro_dbtoken() { - local -n dbtoken_conf="$1" - local -n log_dir="${2:-}" - log "starting" - - local -r aro_dbtoken_service_conf_filename='/etc/sysconfig/aro-dbtoken' - - write_file aro_dbtoken_service_conf_filename aro_dbtoken_service_conf_file true - - local -r aro_dbtoken_service_filename='/etc/systemd/system/aro-dbtoken.service' - # TODO add test if log_dir is empty, else - local -r aro_dbtoken_service_file="[Unit] -After=network-online.target -Wants=network-online.target - -[Service] -EnvironmentFile=/etc/sysconfig/aro-dbtoken -ExecStartPre=-/usr/bin/docker rm -f %N -ExecStart=/usr/bin/docker run \ - --hostname %H \ - --name %N \ - --rm \ - --cap-drop net_raw \ - -e AZURE_GATEWAY_SERVICE_PRINCIPAL_ID \ - -e DATABASE_ACCOUNT_NAME \ - -e AZURE_DBTOKEN_CLIENT_ID \ - -e KEYVAULT_PREFIX \ - -e MDM_ACCOUNT \ - -e MDM_NAMESPACE \ - -m 2g \ - -p 445:8445 \ - -v /run/systemd/journal:/run/systemd/journal \ - -v /var/etw:/var/etw:z \ - $RPIMAGE \ - dbtoken -ExecStop=/usr/bin/docker stop -t 3600 %N -TimeoutStopSec=3600 -Restart=always -RestartSec=1 -StartLimitInterval=0 - -[Install] -WantedBy=multi-user.target" - - local -r aro_dbtoken_service_file="[Unit] -After=network-online.target -Wants=network-online.target - -[Service] -EnvironmentFile=/etc/sysconfig/aro-gateway -ExecStartPre=-/usr/bin/docker rm -f %N -ExecStartPre=/usr/bin/mkdir -p ${gateway_logdir} -ExecStart=/usr/bin/docker run \ - --hostname %H \ - --name %N \ - --rm \ - --cap-drop net_raw \ - -e ACR_RESOURCE_ID \ - -e DATABASE_ACCOUNT_NAME \ - -e AZURE_DBTOKEN_CLIENT_ID \ - -e DBTOKEN_URL \ - -e GATEWAY_DOMAINS \ - -e GATEWAY_FEATURES \ - -e MDM_ACCOUNT \ - -e MDM_NAMESPACE \ - -m 2g \ - -p 80:8080 \ - -p 8081:8081 \ - -p 443:8443 \ - -v /run/systemd/journal:/run/systemd/journal \ - -v /var/etw:/var/etw:z \ - -v ${gateway_logdir}:/ctr.log:z \ - \$RPIMAGE \ - gateway -ExecStop=/usr/bin/docker stop -t 3600 %N -TimeoutStopSec=3600 -Restart=always -RestartSec=1 -StartLimitInterval=0 - -[Install] -WantedBy=multi-user.target" - - write_file aro_dbtoken_service_filename aro_dbtoken_service_file true + write_file service_filename service_file true } # configure_service_mdsd configure_service_mdsd() { - local -n monitor_config_version="$1" + local -n monitoring_role="$1" + local -n monitor_config_version="$2" log "starting" local -r mdsd_service_dir="/etc/systemd/system/mdsd.service.d" @@ -744,7 +658,7 @@ export MONITORING_CONFIG_VERSION='$monitor_config_version' export MONITORING_USE_GENEVA_CONFIG_SERVICE=true export MONITORING_TENANT='$LOCATION' -export MONITORING_ROLE=rp +export MONITORING_ROLE='$monitoring_role' export MONITORING_ROLE_INSTANCE=\"$(hostname)\" export MDSD_MSGPACK_SORT_COLUMNS=1\"" @@ -769,3 +683,8 @@ run_azsecd_config_scan() { /usr/local/bin/azsecd config -s "$scan" -d P1D done } + +create_required_dirs() { + mkdir -p /var/log/journal + mkdir -p /var/lib/waagent/Microsoft.Azure.KeyVault.Store +} diff --git a/pkg/deploy/generator/scripts/rpVMSS.sh b/pkg/deploy/generator/scripts/rpVMSS.sh index c7fd67f2d30..730964d5ab7 100644 --- a/pkg/deploy/generator/scripts/rpVMSS.sh +++ b/pkg/deploy/generator/scripts/rpVMSS.sh @@ -53,13 +53,14 @@ main() { dnf_install_pkgs install_pkgs retry_wait_time configure_dnf_cron_job - configure_disk_partitions - configure_logrotate - configure_selinux - mkdir -p /var/log/journal - mkdir -p /var/lib/waagent/Microsoft.Azure.KeyVault.Store + # Key dictates the filename written in /etc/logrotate.d + # Present for future dropin files, also is required for configure_logrotate + local -rA logrotate_dropins=() + configure_logrotate logrotate_dropins + configure_selinux + create_required_dirs local -ra enable_ports=( "443/tcp" @@ -78,7 +79,8 @@ main() { "$rpimage" "$fluentbit_image" ) - pull_container_images images + local -r registry_config_file="" + pull_container_images images registry_config_file local -r fluentbit_conf_file="[INPUT] Name systemd @@ -114,24 +116,17 @@ DB /var/lib/fluent/journaldb Match * Port 29230" - local -r aro_dbtoken_service_conf_file="DATABASE_ACCOUNT_NAME='$DATABASEACCOUNTNAME' -AZURE_DBTOKEN_CLIENT_ID='$DBTOKENCLIENTID' -AZURE_GATEWAY_SERVICE_PRINCIPAL_ID='$GATEWAYSERVICEPRINCIPALID' -KEYVAULT_PREFIX='$KEYVAULTPREFIX' -MDM_ACCOUNT='$RPMDMACCOUNT' -MDM_NAMESPACE=DBToken -RPIMAGE='$RPIMAGE'" - - # TODO pass this to mdsd service call configure_service_fluentbit fluentbit_conf_file fluentbit_image - configure_service_mdm - configure_timers_mdm_mdsd + local -r monitor_role="rp" + configure_service_mdm monitor_role mdmimage + configure_timers_mdm_mdsd monitor_role configure_service_aro_rp - configure_service_aro_dbtoken - configure_service_aro_monitor - configure_service_aro_portal + + configure_service_dbtoken rpimage + configure_service_aro_monitor rpimage + configure_service_aro_portal rpimage local -r mdsd_rp_version="$RPMDSDCONFIGVERSION" - configure_service_mdsd mdsd_rp_version + configure_service_mdsd monitor_role mdsd_rp_version local -ra aro_services=( "aro-dbtoken" @@ -145,6 +140,8 @@ RPIMAGE='$RPIMAGE'" "mdm" "chronyd" "fluentbit" + "download-mdsd-credentials.timer" + "download-mdm-credentials.timer" ) enable_services aro_services @@ -272,6 +269,7 @@ WantedBy=multi-user.target" # configure_service_aro_monitor configure_service_aro_monitor() { + local -n image="$1" log "starting" log "configuring aro-monitor service" @@ -292,7 +290,7 @@ DATABASE_ACCOUNT_NAME='$DATABASEACCOUNTNAME' KEYVAULT_PREFIX='$KEYVAULTPREFIX' MDM_ACCOUNT='$RPMDMACCOUNT' MDM_NAMESPACE=BBM -RPIMAGE='$RPIMAGE'" +RPIMAGE='$image'" write_file aro_monitor_service_conf_filename aro_monitor_service_conf_file true @@ -326,7 +324,7 @@ ExecStart=/usr/bin/docker run \ -m 2.5g \ -v /run/systemd/journal:/run/systemd/journal \ -v /var/etw:/var/etw:z \ - $RPIMAGE \ + $image \ monitor Restart=always RestartSec=1 @@ -340,6 +338,7 @@ WantedBy=multi-user.target" # configure_service_aro_portal configure_service_aro_portal() { + local -n image="$1" log "starting" local -r aro_portal_service_conf_filename='/etc/sysconfig/aro-portal' @@ -351,7 +350,7 @@ KEYVAULT_PREFIX='$KEYVAULTPREFIX' MDM_ACCOUNT='$RPMDMACCOUNT' MDM_NAMESPACE=Portal PORTAL_HOSTNAME='$LOCATION.admin.$RPPARENTDOMAINNAME' -RPIMAGE='$RPIMAGE'" +RPIMAGE='$image'" write_file aro_portal_service_conf_filename aro_portal_service_conf_file true @@ -382,7 +381,7 @@ ExecStart=/usr/bin/docker run \ -p 2222:2222 \ -v /run/systemd/journal:/run/systemd/journal \ -v /var/etw:/var/etw:z \ - $RPIMAGE \ + $image \ portal Restart=always RestartSec=1 @@ -393,6 +392,61 @@ WantedBy=multi-user.target" write_file aro_portal_service_filename aro_portal_service_file true } +# configure_service_aro_dbtoken +configure_service_dbtoken() { + local -n image="$1" + log "starting" + + local -r conf_file="DATABASE_ACCOUNT_NAME='$DATABASEACCOUNTNAME' +AZURE_DBTOKEN_CLIENT_ID='$DBTOKENCLIENTID' +AZURE_GATEWAY_SERVICE_PRINCIPAL_ID='$GATEWAYSERVICEPRINCIPALID' +KEYVAULT_PREFIX='$KEYVAULTPREFIX' +MDM_ACCOUNT='$RPMDMACCOUNT' +MDM_NAMESPACE=DBToken +RPIMAGE='$image'" + + local -r conf_filename='/etc/sysconfig/aro-dbtoken' + + write_file conf_filename conf_file true + + local -r service_file="[Unit] +After=network-online.target +Wants=network-online.target + +[Service] +EnvironmentFile=/etc/sysconfig/aro-dbtoken +ExecStartPre=-/usr/bin/docker rm -f %N +ExecStart=/usr/bin/docker run \ + --hostname %H \ + --name %N \ + --rm \ + --cap-drop net_raw \ + -e AZURE_GATEWAY_SERVICE_PRINCIPAL_ID \ + -e DATABASE_ACCOUNT_NAME \ + -e AZURE_DBTOKEN_CLIENT_ID \ + -e KEYVAULT_PREFIX \ + -e MDM_ACCOUNT \ + -e MDM_NAMESPACE \ + -m 2g \ + -p 445:8445 \ + -v /run/systemd/journal:/run/systemd/journal \ + -v /var/etw:/var/etw:z \ + $image \ + dbtoken +ExecStop=/usr/bin/docker stop -t 3600 %N +TimeoutStopSec=3600 +Restart=always +RestartSec=1 +StartLimitInterval=0 + +[Install] +WantedBy=multi-user.target" + + local -r service_filename='/etc/systemd/system/aro-dbtoken.service' + write_file service_filename service_file true +} + + export AZURE_CLOUD_NAME="${AZURECLOUDNAME:?"Failed to carry over variables"}" main "$@" From 429c281ee140247f342dce477126923a5d5ffd17 Mon Sep 17 00:00:00 2001 From: Steven Fairchild Date: Tue, 23 Apr 2024 16:08:27 -0400 Subject: [PATCH 34/38] WIP Functional gatewayVMSS.sh, moved repo functions into common.sh --- pkg/deploy/generator/scripts/common.sh | 72 ++++++++++++--------- pkg/deploy/generator/scripts/gatewayVMSS.sh | 60 ++++++++++------- pkg/deploy/generator/scripts/rpVMSS.sh | 28 -------- 3 files changed, 78 insertions(+), 82 deletions(-) diff --git a/pkg/deploy/generator/scripts/common.sh b/pkg/deploy/generator/scripts/common.sh index c1db1d0c2f6..fbae20b34d3 100644 --- a/pkg/deploy/generator/scripts/common.sh +++ b/pkg/deploy/generator/scripts/common.sh @@ -178,8 +178,9 @@ include /etc/logrotate.d local -r logrotate_d="/etc/logrotate.d" log "Writing logrotate files to $logrotate_d" for dropin_name in "${!dropin_files[@]}"; do - local -r dropin_file="$logrotate_d/$dropin_name" - write_file "$dropin_file" "${dropin_files["$dropin_name"]}" + local -r dropin_filename="$logrotate_d/$dropin_name" + local -r dropin_file="${dropin_files["$dropin_name"]}" + write_file dropin_filename dropin_file true done } @@ -226,6 +227,8 @@ enable_services() { local -n services="$1" log "starting" + systemctl daemon-reload + log "enabling services ${services[*]}" # shellcheck disable=SC2068 for service in ${services[@]}; do @@ -276,7 +279,40 @@ abort() { exit 1 } -# configure_rhui_repo +# configure_rpm_repos +# New repositories should be added in their own functions, and called here +# args: +# 1) retry_wait_time - nameref +configure_rpm_repos() { + log "starting" + + configure_rhui_repo "$1" + create_azure_rpm_repos +} + +# create_azure_rpm_repos creates /etc/yum.repos.d/azure.repo repository file +create_azure_rpm_repos() { + log "starting" + + local -r azure_repo_filename='/etc/yum.repos.d/azure.repo' + local -r azure_repo_file='[azure-cli] +name=azure-cli +baseurl=https://packages.microsoft.com/yumrepos/azure-cli +enabled=yes +gpgcheck=yes + +[azurecore] +name=azurecore +baseurl=https://packages.microsoft.com/yumrepos/azurecore +enabled=yes +gpgcheck=no' + + write_file azure_repo_filename azure_repo_file true +} + +# configure_rhui_repo enables all rhui-microsoft-azure* repos +# args: +# 1) retry_wait_time - nameref configure_rhui_repo() { log "starting" @@ -302,26 +338,6 @@ dnf update -y" chmod +x "$cron_weekly_dnf_update_filename" } -# create_azure_rpm_repos creates /etc/yum.repos.d/azure.repo repository file -create_azure_rpm_repos() { - log "starting" - - local -r azure_repo_filename='/etc/yum.repos.d/azure.repo' - local -r azure_repo_file='[azure-cli] -name=azure-cli -baseurl=https://packages.microsoft.com/yumrepos/azure-cli -enabled=yes -gpgcheck=yes - -[azurecore] -name=azurecore -baseurl=https://packages.microsoft.com/yumrepos/azurecore -enabled=yes -gpgcheck=no' - - write_file azure_repo_filename azure_repo_file true -} - # configure_disk_partitions configure_disk_partitions() { log "starting" @@ -361,8 +377,8 @@ configure_certs() { csplit -f /usr/lib/ssl/certs/cert- -b %03d.pem /etc/pki/tls/certs/ca-bundle.crt /^$/1 "{*}" >/dev/null c_rehash /usr/lib/ssl/certs -# we leave clientId blank as long as only 1 managed identity assigned to vmss -# if we have more than 1, we will need to populate with clientId used for off-node scanning + # we leave clientId blank as long as only 1 managed identity assigned to vmss + # if we have more than 1, we will need to populate with clientId used for off-node scanning local -r nodescan_agent_filename="/etc/default/vsa-nodescan-agent.config" local -r nodescan_agent_file="{ \"Nice\": 19, @@ -576,12 +592,6 @@ configure_service_fluentbit() { log "starting" log "configuring fluentbit service" - if [ -z "$conf_file" ]; then - abort "$1 config file cannot be empty" - elif [ -z "$image" ]; then - abort "$2 image cannot be empty" - fi - mkdir -p /etc/fluentbit/ mkdir -p /var/lib/fluent diff --git a/pkg/deploy/generator/scripts/gatewayVMSS.sh b/pkg/deploy/generator/scripts/gatewayVMSS.sh index 064bf18bd49..edc219928cd 100644 --- a/pkg/deploy/generator/scripts/gatewayVMSS.sh +++ b/pkg/deploy/generator/scripts/gatewayVMSS.sh @@ -8,7 +8,14 @@ if [ "${DEBUG:-false}" == true ]; then fi main() { + # transaction attempt retry time in seconds + local -ri retry_wait_time=60 + + # shellcheck source=common.sh + source common.sh + configure_sshd + configure_rpm_repos retry_wait_time local -ar exclude_pkgs=( "-x WALinuxAgent" @@ -29,6 +36,7 @@ main() { ) dnf_install_pkgs repo_rpm_pkgs retry_wait_time + configure_dnf_cron_job local -ra install_pkgs=( clamav @@ -61,15 +69,14 @@ ${gateway_logdir} { compress }" + # Key dictates the filename written in /etc/logrotate.d local -rA logrotate_dropins=( - ["gateway_log_config"]="$gateway_log_file" + ["gateway"]="$gateway_log_file" ) configure_logrotate logrotate_dropins configure_selinux - - mkdir -p /var/log/journal - mkdir -p /var/lib/waagent/Microsoft.Azure.KeyVault.Store + create_required_dirs local -ra enable_ports=( "80/tcp" @@ -87,18 +94,7 @@ ${gateway_logdir} { "$fluentbit_image" ) - pull_container_images images - - local -ra gateway_services=( - aro-gateway - auoms - azsecd - azsecmond - mdsd - mdm - chronyd - fluentbit - ) + pull_container_images images registry_config_file local -r fluentbit_conf_file="[INPUT] Name systemd @@ -117,7 +113,11 @@ DB /var/lib/fluent/journaldb Match * Port 29230" - local -r aro_dbtoken_service_conf_file="ACR_RESOURCE_ID='$ACRRESOURCEID' + configure_service_fluentbit fluentbit_conf_file fluentbit_image + local -r mdm_role="gateway" + configure_service_mdm mdm_role mdmimage + + local -r gwy_dbtoken_service_conf_file="ACR_RESOURCE_ID='$ACRRESOURCEID' DATABASE_ACCOUNT_NAME='$DATABASEACCOUNTNAME' AZURE_DBTOKEN_CLIENT_ID='$DBTOKENCLIENTID' DBTOKEN_URL='$DBTOKENURL' @@ -126,14 +126,28 @@ MDM_NAMESPACE=Gateway GATEWAY_DOMAINS='$GATEWAYDOMAINS' GATEWAY_FEATURES='$GATEWAYFEATURES' RPIMAGE='$RPIMAGE'" + configure_service_gateway gateway_logdir - local -n mdsd_gateway_version="$GATEWAYMDSDCONFIGVERSION" + local -r mdsd_config_version="$GATEWAYMDSDCONFIGVERSION" + configure_service_mdsd mdm_role mdsd_config_version + local -r mdsd_role="gwy" + configure_timers_mdm_mdsd mdsd_role + + local -ra gateway_services=( + "aro-gateway" + "auoms" + "azsecd" + "azsecmond" + "mdsd" + "mdm" + "chronyd" + "fluentbit" + "download-mdsd-credentials.timer" + "download-mdm-credentials.timer" + ) + + enable_services gateway_services - configure_service_fluentbit fluentbit_conf_file fluentbit_image - configure_service_mdm - configure_timers_mdm_mdsd - configure_service_gateway gateway_log_file - configure_service_mdsd reboot_vm } diff --git a/pkg/deploy/generator/scripts/rpVMSS.sh b/pkg/deploy/generator/scripts/rpVMSS.sh index 730964d5ab7..406e8273042 100644 --- a/pkg/deploy/generator/scripts/rpVMSS.sh +++ b/pkg/deploy/generator/scripts/rpVMSS.sh @@ -149,34 +149,6 @@ DB /var/lib/fluent/journaldb reboot_vm } -# configure_rpm_repos -configure_rpm_repos() { - log "starting" - - configure_rhui_repo "$1" - create_azure_rpm_repos -} - -# create_azure_rpm_repos creates /etc/yum.repos.d/azure.repo repository file -create_azure_rpm_repos() { - log "starting" - - local -r azure_repo_filename='/etc/yum.repos.d/azure.repo' - local -r azure_repo_file='[azure-cli] -name=azure-cli -baseurl=https://packages.microsoft.com/yumrepos/azure-cli -enabled=yes -gpgcheck=yes - -[azurecore] -name=azurecore -baseurl=https://packages.microsoft.com/yumrepos/azurecore -enabled=yes -gpgcheck=no' - - write_file azure_repo_filename azure_repo_file true -} - # configure_service_aro_rp configure_service_aro_rp() { log "starting" From 5a3ab70f1ad95069bfbc0008c79f6fa255da13d1 Mon Sep 17 00:00:00 2001 From: Steven Fairchild Date: Tue, 23 Apr 2024 17:12:36 -0400 Subject: [PATCH 35/38] Consolidate configure_certs by adding arguement determining certs to configure --- pkg/deploy/generator/scripts/common.sh | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/pkg/deploy/generator/scripts/common.sh b/pkg/deploy/generator/scripts/common.sh index fbae20b34d3..1de8b773786 100644 --- a/pkg/deploy/generator/scripts/common.sh +++ b/pkg/deploy/generator/scripts/common.sh @@ -362,14 +362,27 @@ configure_disk_partitions() { # configure_certs configure_certs() { + local -n role="$1" log "starting" + log "Configuring certificates for $role" + + if [ "$role" == "devproxy" ]; then + base64 -d <<<"$PROXYCERT" >/etc/proxy/proxy.crt + base64 -d <<<"$PROXYKEY" >/etc/proxy/proxy.key + base64 -d <<<"$PROXYCLIENTCERT" >/etc/proxy/proxy-client.crt + chown -R 1000:1000 /etc/proxy + chmod 0600 /etc/proxy/proxy.key + return 0 + fi - mkdir /etc/aro-rp - base64 -d <<<"$ADMINAPICABUNDLE" >/etc/aro-rp/admin-ca-bundle.pem - if [[ -n "$ARMAPICABUNDLE" ]]; then - base64 -d <<<"$ARMAPICABUNDLE" >/etc/aro-rp/arm-ca-bundle.pem + if [ "$role" == "rp" ]; then + mkdir -p /etc/aro-rp + base64 -d <<<"$ADMINAPICABUNDLE" >/etc/aro-rp/admin-ca-bundle.pem + if [[ -n "$ARMAPICABUNDLE" ]]; then + base64 -d <<<"$ARMAPICABUNDLE" >/etc/aro-rp/arm-ca-bundle.pem + fi + chown -R 1000:1000 /etc/aro-rp fi - chown -R 1000:1000 /etc/aro-rp # setting MONITORING_GCS_AUTH_ID_TYPE=AuthKeyVault seems to have caused mdsd not # to honour SSL_CERT_FILE any more, heaven only knows why. From f289e16e4cca13ae0473d458ee1f4d4ff0700ba6 Mon Sep 17 00:00:00 2001 From: Steven Fairchild Date: Tue, 23 Apr 2024 17:12:58 -0400 Subject: [PATCH 36/38] WIP configure certificates on gateway, rp, devProxy VMSSes Move create_required_dirs to be the first step that runs, to ensure they exist when needed. This was mostly for the devProxyVMSS --- pkg/deploy/generator/scripts/common.sh | 43 +++++++++++++------- pkg/deploy/generator/scripts/devProxyVMSS.sh | 18 +++----- pkg/deploy/generator/scripts/gatewayVMSS.sh | 4 +- pkg/deploy/generator/scripts/rpVMSS.sh | 4 +- 4 files changed, 40 insertions(+), 29 deletions(-) diff --git a/pkg/deploy/generator/scripts/common.sh b/pkg/deploy/generator/scripts/common.sh index 1de8b773786..6f54ced7354 100644 --- a/pkg/deploy/generator/scripts/common.sh +++ b/pkg/deploy/generator/scripts/common.sh @@ -187,7 +187,8 @@ include /etc/logrotate.d # pull_container_images pull_container_images() { local -n pull_images="$1" - local -n registry_conf="${2:-}" + local -n registry_conf="${2:-empty}" + local -r az_login="${3:-true}" log "starting" # The managed identity that the VM runs as only has a single roleassignment. @@ -196,7 +197,9 @@ pull_container_images() { # role assignments scoped on the subscription we're deploying into, it will # not show on az login -i, which is why the below line is commented. # az account set -s "$SUBSCRIPTIONID" - az login -i --allow-no-subscriptions + if $az_login; then + az login -i --allow-no-subscriptions + fi # Suppress emulation output for podman instead of docker for az acr compatability mkdir -p /etc/containers/ @@ -211,7 +214,9 @@ pull_container_images() { fi log "logging into prod acr" - az acr login --name "$(sed -e 's|.*/||' <<<"$ACRRESOURCEID")" + if $az_login; then + az acr login --name "$(sed -e 's|.*/||' <<<"$ACRRESOURCEID")" + fi # shellcheck disable=SC2068 for i in ${pull_images[@]}; do @@ -219,7 +224,9 @@ pull_container_images() { podman pull "$i" done - az logout + if $az_login; then + az logout + fi } # enable_services enables all services required for aro rp @@ -367,28 +374,32 @@ configure_certs() { log "Configuring certificates for $role" if [ "$role" == "devproxy" ]; then - base64 -d <<<"$PROXYCERT" >/etc/proxy/proxy.crt - base64 -d <<<"$PROXYKEY" >/etc/proxy/proxy.key - base64 -d <<<"$PROXYCLIENTCERT" >/etc/proxy/proxy-client.crt + local -r proxy_certs_basedir="/etc/proxy" + mkdir -p "$proxy_certs_basedir" + base64 -d <<<"$PROXYCERT" > "$proxy_certs_basedir/proxy.crt" + base64 -d <<<"$PROXYKEY" > "$proxy_certs_basedir/proxy.key" + base64 -d <<<"$PROXYCLIENTCERT" > "$proxy_certs_basedir/proxy-client.crt" chown -R 1000:1000 /etc/proxy - chmod 0600 /etc/proxy/proxy.key + chmod 0600 "$proxy_certs_basedir/proxy.key" return 0 fi if [ "$role" == "rp" ]; then - mkdir -p /etc/aro-rp - base64 -d <<<"$ADMINAPICABUNDLE" >/etc/aro-rp/admin-ca-bundle.pem + local -r rp_certs_basedir="/etc/aro-rp" + mkdir -p + base64 -d <<<"$ADMINAPICABUNDLE" > "$rp_certs_basedir/admin-ca-bundle.pem" if [[ -n "$ARMAPICABUNDLE" ]]; then - base64 -d <<<"$ARMAPICABUNDLE" >/etc/aro-rp/arm-ca-bundle.pem + base64 -d <<<"$ARMAPICABUNDLE" > "$rp_certs_basedir/arm-ca-bundle.pem" fi - chown -R 1000:1000 /etc/aro-rp + chown -R 1000:1000 "$rp_certs_basedir" fi # setting MONITORING_GCS_AUTH_ID_TYPE=AuthKeyVault seems to have caused mdsd not # to honour SSL_CERT_FILE any more, heaven only knows why. - mkdir -p /usr/lib/ssl/certs - csplit -f /usr/lib/ssl/certs/cert- -b %03d.pem /etc/pki/tls/certs/ca-bundle.crt /^$/1 "{*}" >/dev/null - c_rehash /usr/lib/ssl/certs + local -r ssl_certs_basedir="/usr/lib/ssl/certs" + mkdir -p + csplit -f "$ssl_certs_basedir/cert-" -b %03d.pem /etc/pki/tls/certs/ca-bundle.crt /^$/1 "{*}" >/dev/null + c_rehash "$ssl_certs_basedir" # we leave clientId blank as long as only 1 managed identity assigned to vmss # if we have more than 1, we will need to populate with clientId used for off-node scanning @@ -710,4 +721,6 @@ run_azsecd_config_scan() { create_required_dirs() { mkdir -p /var/log/journal mkdir -p /var/lib/waagent/Microsoft.Azure.KeyVault.Store + # Does not exist on devProxyVMSS + mkdir -p /var/opt/microsoft/linuxmonagent } diff --git a/pkg/deploy/generator/scripts/devProxyVMSS.sh b/pkg/deploy/generator/scripts/devProxyVMSS.sh index 9866313e007..af727a11155 100644 --- a/pkg/deploy/generator/scripts/devProxyVMSS.sh +++ b/pkg/deploy/generator/scripts/devProxyVMSS.sh @@ -14,6 +14,8 @@ main() { # shellcheck source=common.sh source common.sh + create_required_dirs + local -ar exclude_pkgs=( "-x WALinuxAgent" "-x WALinuxAgent-udev" @@ -44,9 +46,12 @@ main() { } }" - pull_container_images proxy_image registry_config_file + pull_container_images proxy_image registry_config_file false configure_devproxy_services proxy_images + local -r vmss_role="devproxy" + configure_certs vmss_role + local -ra proxy_services=( proxy ) @@ -62,17 +67,6 @@ configure_devproxy_services() { configure_service_proxy "$1" } -# configure_certs -configure_certs() { - log "starting" - - base64 -d <<<"$PROXYCERT" >/etc/proxy/proxy.crt - base64 -d <<<"$PROXYKEY" >/etc/proxy/proxy.key - base64 -d <<<"$PROXYCLIENTCERT" >/etc/proxy/proxy-client.crt - chown -R 1000:1000 /etc/proxy - chmod 0600 /etc/proxy/proxy.key -} - configure_service_proxy() { local -n proxy_image="$1" local -r sysconfig_proxy_filename='/etc/sysconfig/proxy' diff --git a/pkg/deploy/generator/scripts/gatewayVMSS.sh b/pkg/deploy/generator/scripts/gatewayVMSS.sh index edc219928cd..bb0e12e7137 100644 --- a/pkg/deploy/generator/scripts/gatewayVMSS.sh +++ b/pkg/deploy/generator/scripts/gatewayVMSS.sh @@ -14,6 +14,7 @@ main() { # shellcheck source=common.sh source common.sh + create_required_dirs configure_sshd configure_rpm_repos retry_wait_time @@ -76,7 +77,6 @@ ${gateway_logdir} { configure_logrotate logrotate_dropins configure_selinux - create_required_dirs local -ra enable_ports=( "80/tcp" @@ -133,6 +133,8 @@ RPIMAGE='$RPIMAGE'" local -r mdsd_role="gwy" configure_timers_mdm_mdsd mdsd_role + configure_certs mdm_role + local -ra gateway_services=( "aro-gateway" "auoms" diff --git a/pkg/deploy/generator/scripts/rpVMSS.sh b/pkg/deploy/generator/scripts/rpVMSS.sh index 406e8273042..2d9f16b717d 100644 --- a/pkg/deploy/generator/scripts/rpVMSS.sh +++ b/pkg/deploy/generator/scripts/rpVMSS.sh @@ -14,6 +14,7 @@ main() { # shellcheck source=common.sh source common.sh + create_required_dirs configure_sshd configure_rpm_repos retry_wait_time @@ -60,7 +61,6 @@ main() { local -rA logrotate_dropins=() configure_logrotate logrotate_dropins configure_selinux - create_required_dirs local -ra enable_ports=( "443/tcp" @@ -128,6 +128,8 @@ DB /var/lib/fluent/journaldb local -r mdsd_rp_version="$RPMDSDCONFIGVERSION" configure_service_mdsd monitor_role mdsd_rp_version + configure_certs monitor_role + local -ra aro_services=( "aro-dbtoken" "aro-monitor" From 63867bb55e0b637c3eeaa154b65414c3de890c30 Mon Sep 17 00:00:00 2001 From: Steven Fairchild Date: Tue, 23 Apr 2024 18:02:52 -0400 Subject: [PATCH 37/38] rename common.sh to commonVMSS.sh to show it's common to \*VMSS.sh scripts --- pkg/deploy/generator/scripts/{common.sh => commonVMSS.sh} | 0 pkg/deploy/generator/scripts/devProxyVMSS.sh | 4 ++-- pkg/deploy/generator/scripts/gatewayVMSS.sh | 4 ++-- pkg/deploy/generator/scripts/rpVMSS.sh | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) rename pkg/deploy/generator/scripts/{common.sh => commonVMSS.sh} (100%) diff --git a/pkg/deploy/generator/scripts/common.sh b/pkg/deploy/generator/scripts/commonVMSS.sh similarity index 100% rename from pkg/deploy/generator/scripts/common.sh rename to pkg/deploy/generator/scripts/commonVMSS.sh diff --git a/pkg/deploy/generator/scripts/devProxyVMSS.sh b/pkg/deploy/generator/scripts/devProxyVMSS.sh index af727a11155..23aab382c85 100644 --- a/pkg/deploy/generator/scripts/devProxyVMSS.sh +++ b/pkg/deploy/generator/scripts/devProxyVMSS.sh @@ -11,8 +11,8 @@ main() { # transaction attempt retry time in seconds local -ri retry_wait_time=60 - # shellcheck source=common.sh - source common.sh + # shellcheck source=commonVMSS.sh + source commonVMSS.sh create_required_dirs diff --git a/pkg/deploy/generator/scripts/gatewayVMSS.sh b/pkg/deploy/generator/scripts/gatewayVMSS.sh index bb0e12e7137..8b382698977 100644 --- a/pkg/deploy/generator/scripts/gatewayVMSS.sh +++ b/pkg/deploy/generator/scripts/gatewayVMSS.sh @@ -11,8 +11,8 @@ main() { # transaction attempt retry time in seconds local -ri retry_wait_time=60 - # shellcheck source=common.sh - source common.sh + # shellcheck source=commonVMSS.sh + source commonVMSS.sh create_required_dirs configure_sshd diff --git a/pkg/deploy/generator/scripts/rpVMSS.sh b/pkg/deploy/generator/scripts/rpVMSS.sh index 2d9f16b717d..dfe02052521 100644 --- a/pkg/deploy/generator/scripts/rpVMSS.sh +++ b/pkg/deploy/generator/scripts/rpVMSS.sh @@ -11,8 +11,8 @@ main() { # transaction attempt retry time in seconds local -ri retry_wait_time=60 - # shellcheck source=common.sh - source common.sh + # shellcheck source=commonVMSS.sh + source commonVMSS.sh create_required_dirs configure_sshd From bdf8d12b053faa89f6bbae09f3205e986cbf03b1 Mon Sep 17 00:00:00 2001 From: Steven Fairchild Date: Wed, 10 Apr 2024 11:24:40 -0400 Subject: [PATCH 38/38] Move systemd service configurations into functions Move dnf package and repo operations into function, move all service configuration into a function Move repository configuration higher in sequence of events, make unchanging variables readonly Add write_file function to cleanup creation of new files, appending to existing files move packages to install and rpm keys to import into arrays, this will make adding new packages and keys easier Add retry loop for rpm repo key imports, remove erroneous package from install_pkgs array Pass dnf packages and rpm keys to function calls via nameref to allow reuse, This also allows for function reuse. Add wait for all rpm related transactions to avoid rpm database corruption Add starting log message for each function call rpm database corruption has been seen in testing, and Prod deployments due to concurrent rpm database operations between rpm and dnf. wait is needed due to this. remove ERR trap, we aren't attempting to trap any specific errors yet. Increase dnf & rpm retry time to 1 minute, 5 minutes total Pass wait time as a nameref variable to allow easier modification Add parse_run_options to run individual steps for testing Add az login -i comment found in gatewayVMSS.sh, change variable syntex to snake case for consistency Port changes made in rpVMSS.sh to gatewayVMSS.sh Make gateway log directory to be passed in to functions where it is needed, this allows the value to be set in one location. Move retry steps into a single retry function call This is to reduce code duplication Move configure_fiewall_rules file creation to use write_file Correct accept_ra_conf variable name spelling Pass usage options via nameref variable that is also used by getops Move docker file creation to more logical location --- pkg/deploy/assets/env-development.json | 2 +- pkg/deploy/assets/gateway-production.json | 2 +- pkg/deploy/assets/rp-production.json | 2 +- pkg/deploy/generator/scripts/devProxyVMSS.sh | 440 ++++++-- pkg/deploy/generator/scripts/gatewayVMSS.sh | 1031 ++++++++++++----- pkg/deploy/generator/scripts/rpVMSS.sh | 1058 +++++++++++++----- 6 files changed, 1892 insertions(+), 643 deletions(-) diff --git a/pkg/deploy/assets/env-development.json b/pkg/deploy/assets/env-development.json index 10057c04528..1da1cb9fb5b 100644 --- a/pkg/deploy/assets/env-development.json +++ b/pkg/deploy/assets/env-development.json @@ -296,7 +296,7 @@ "autoUpgradeMinorVersion": true, "settings": {}, "protectedSettings": { - "script": "[base64(concat(base64ToString('c2V0IC1leAoK'),'PROXYIMAGE=$(base64 -d \u003c\u003c\u003c''',base64(parameters('proxyImage')),''')\n','PROXYIMAGEAUTH=$(base64 -d \u003c\u003c\u003c''',base64(parameters('proxyImageAuth')),''')\n','PROXYCERT=''',parameters('proxyCert'),'''\n','PROXYCLIENTCERT=''',parameters('proxyClientCert'),'''\n','PROXYKEY=''',parameters('proxyKey'),'''\n','\n',base64ToString('I0FkZGluZyByZXRyeSBsb2dpYyB0byB5dW0gY29tbWFuZHMgaW4gb3JkZXIgdG8gYXZvaWQgc3RhbGxpbmcgb3V0IG9uIHJlc291cmNlIGxvY2tzCmVjaG8gInJ1bm5pbmcgUkhVSSBmaXgiCmZvciBhdHRlbXB0IGluIHsxLi41fTsgZG8KICB5dW0gdXBkYXRlIC15IC0tZGlzYWJsZXJlcG89JyonIC0tZW5hYmxlcmVwbz0ncmh1aS1taWNyb3NvZnQtYXp1cmUqJyAmJiBicmVhawogIGlmIFtbICR7YXR0ZW1wdH0gLWx0IDUgXV07IHRoZW4gc2xlZXAgMTA7IGVsc2UgZXhpdCAxOyBmaQpkb25lCgplY2hvICJydW5uaW5nIHl1bSB1cGRhdGUiCmZvciBhdHRlbXB0IGluIHsxLi41fTsgZG8KICB5dW0gLXkgLXggV0FMaW51eEFnZW50IC14IFdBTGludXhBZ2VudC11ZGV2IHVwZGF0ZSAtLWFsbG93ZXJhc2luZyAmJiBicmVhawogIGlmIFtbICR7YXR0ZW1wdH0gLWx0IDUgXV07IHRoZW4gc2xlZXAgMTA7IGVsc2UgZXhpdCAxOyBmaQpkb25lCgplY2hvICJpbnN0YWxsaW5nIHBvZG1hbi1kb2NrZXIiCmZvciBhdHRlbXB0IGluIHsxLi41fTsgZG8KICB5dW0gLXkgaW5zdGFsbCBwb2RtYW4tZG9ja2VyICYmIGJyZWFrCiAgaWYgW1sgJHthdHRlbXB0fSAtbHQgNSBdXTsgdGhlbiBzbGVlcCAxMDsgZWxzZSBleGl0IDE7IGZpCmRvbmUKCmZpcmV3YWxsLWNtZCAtLWFkZC1wb3J0PTQ0My90Y3AgLS1wZXJtYW5lbnQKCm1rZGlyIC9yb290Ly5kb2NrZXIKY2F0ID4vcm9vdC8uZG9ja2VyL2NvbmZpZy5qc29uIDw8RU9GCnsKCSJhdXRocyI6IHsKCQkiJHtQUk9YWUlNQUdFJSUvKn0iOiB7CgkJCSJhdXRoIjogIiRQUk9YWUlNQUdFQVVUSCIKCQl9Cgl9Cn0KRU9GCgpta2RpciAtcCAvZXRjL2NvbnRhaW5lcnMvCnRvdWNoIC9ldGMvY29udGFpbmVycy9ub2RvY2tlcgoKZG9ja2VyIHB1bGwgIiRQUk9YWUlNQUdFIgoKbWtkaXIgL2V0Yy9wcm94eQpiYXNlNjQgLWQgPDw8IiRQUk9YWUNFUlQiID4vZXRjL3Byb3h5L3Byb3h5LmNydApiYXNlNjQgLWQgPDw8IiRQUk9YWUtFWSIgPi9ldGMvcHJveHkvcHJveHkua2V5CmJhc2U2NCAtZCA8PDwiJFBST1hZQ0xJRU5UQ0VSVCIgPi9ldGMvcHJveHkvcHJveHktY2xpZW50LmNydApjaG93biAtUiAxMDAwOjEwMDAgL2V0Yy9wcm94eQpjaG1vZCAwNjAwIC9ldGMvcHJveHkvcHJveHkua2V5CgpjYXQgPi9ldGMvc3lzY29uZmlnL3Byb3h5IDw8RU9GClBST1hZX0lNQUdFPSckUFJPWFlJTUFHRScKRU9GCgpjYXQgPi9ldGMvc3lzdGVtZC9zeXN0ZW0vcHJveHkuc2VydmljZSA8PCdFT0YnCltVbml0XQpBZnRlcj1uZXR3b3JrLW9ubGluZS50YXJnZXQKV2FudHM9bmV0d29yay1vbmxpbmUudGFyZ2V0CgpbU2VydmljZV0KRW52aXJvbm1lbnRGaWxlPS9ldGMvc3lzY29uZmlnL3Byb3h5CkV4ZWNTdGFydFByZT0tL3Vzci9iaW4vZG9ja2VyIHJtIC1mICVuCkV4ZWNTdGFydD0vdXNyL2Jpbi9kb2NrZXIgcnVuIC0tcm0gLS1uYW1lICVuIC1wIDQ0Mzo4NDQzIC12IC9ldGMvcHJveHk6L3NlY3JldHMgJFBST1hZX0lNQUdFCkV4ZWNTdG9wPS91c3IvYmluL2RvY2tlciBzdG9wICVuClJlc3RhcnQ9YWx3YXlzClJlc3RhcnRTZWM9MQpTdGFydExpbWl0SW50ZXJ2YWw9MAoKW0luc3RhbGxdCldhbnRlZEJ5PW11bHRpLXVzZXIudGFyZ2V0CkVPRgoKc3lzdGVtY3RsIGVuYWJsZSBwcm94eS5zZXJ2aWNlCgpjYXQgPi9ldGMvY3Jvbi53ZWVrbHkvcHVsbC1pbWFnZSA8PCdFT0YnCiMhL2Jpbi9iYXNoCgpkb2NrZXIgcHVsbCAkUFJPWFlJTUFHRQpzeXN0ZW1jdGwgcmVzdGFydCBwcm94eS5zZXJ2aWNlCkVPRgpjaG1vZCAreCAvZXRjL2Nyb24ud2Vla2x5L3B1bGwtaW1hZ2UKCmNhdCA+L2V0Yy9jcm9uLndlZWtseS95dW11cGRhdGUgPDwnRU9GJwojIS9iaW4vYmFzaAoKeXVtIHVwZGF0ZSAteQpFT0YKY2htb2QgK3ggL2V0Yy9jcm9uLndlZWtseS95dW11cGRhdGUKCmNhdCA+L2V0Yy9jcm9uLmRhaWx5L3Jlc3RhcnQtcHJveHkgPDwnRU9GJwojIS9iaW4vYmFzaAoKc3lzdGVtY3RsIHJlc3RhcnQgcHJveHkuc2VydmljZQpFT0YKY2htb2QgK3ggL2V0Yy9jcm9uLmRhaWx5L3Jlc3RhcnQtcHJveHkKCigKCXNsZWVwIDMwCglyZWJvb3QKKSAmCg==')))]" + "script": "[base64(concat(base64ToString('c2V0IC1leAoK'),'PROXYIMAGE=$(base64 -d \u003c\u003c\u003c''',base64(parameters('proxyImage')),''')\n','PROXYIMAGEAUTH=$(base64 -d \u003c\u003c\u003c''',base64(parameters('proxyImageAuth')),''')\n','PROXYCERT=''',parameters('proxyCert'),'''\n','PROXYCLIENTCERT=''',parameters('proxyClientCert'),'''\n','PROXYKEY=''',parameters('proxyKey'),'''\n','\n',base64ToString('IyEvYmluL2Jhc2gKCnNldCAtbyBlcnJleGl0IFwKICAgIC1vIG5vdW5zZXQKCmlmIFsgIiR7REVCVUc6LWZhbHNlfSIgPT0gdHJ1ZSBdOyB0aGVuCiAgICBzZXQgLXgKZmkKCm1haW4oKSB7CiAgICBwYXJzZV9ydW5fb3B0aW9ucyAiJEAiCgogICAgY29uZmlndXJlX2FuZF9pbnN0YWxsX2RuZl9wa2dzX3JlcG9zCgogICAgY29uZmlndXJlX2ZpcmV3YWxsZF9ydWxlcwogICAgcHVsbF9jb250YWluZXJfaW1hZ2VzCiAgICBjb25maWd1cmVfc3lzdGVtX3NlcnZpY2VzCiAgICByZWJvb3Rfdm0KfQoKdXNhZ2UoKSB7CiAgICBsb2NhbCAtbiBvcHRpb25zPSIkMSIKICAgIGxvZyAiJChiYXNlbmFtZSAiJDAiKSBbJG9wdGlvbnNdCiAgICAgICAgLXAgQ29uZmlndXJlIHJwbSByZXBvc2l0b3JpZXMsIGltcG9ydCByZXF1aXJlZCBycG0ga2V5cywgdXBkYXRlICYgaW5zdGFsbCBwYWNrYWdlcyB3aXRoIGRuZgogICAgICAgIC1mIENvbmZpZ3VyZSBmaXJld2FsbGQgZGVmYXVsdCB6b25lIHJ1bGVzCiAgICAgICAgLXUgQ29uZmlndXJlIHN5c3RlbWQgdW5pdCBmaWxlcyBmb3IgQVJPIFJQCiAgICAgICAgLWkgUHVsbCBjb250YWluZXIgaW1hZ2VzCgogICAgICAgIE5vdGU6IHN0ZXBzIHdpbGwgYmUgZXhlY3V0ZWQgaW4gdGhlIG9yZGVyIHRoYXQgZmxhZ3MgYXJlIHByb3ZpZGVkCiAgICAiCn0KCiMgcGFyc2VfcnVuX29wdGlvbnMgdGFrZXMgYWxsIGFyZ3VlbWVudHMgcGFzc2VkIHRvIG1haW4gYW5kIHBhcnNlcyB0aGVtCiMgYWxsb3dpbmcgaW5kaXZpZHVhbCBzdGVwKHMpIHRvIGJlIHJhbiwgcmF0aGVyIHRoYW4gYWxsIHN0ZXBzCiMKIyBUaGlzIGlzIHVzZWZ1bCBmb3IgbG9jYWwgdGVzdGluZywgb3IgcG9zc2libHkgbW9kaWZ5aW5nIHRoZSBib290c3RyYXAgZXhlY3V0aW9uIHZpYSBlbnZpcm9ubWVudCB2YXJpYWJsZXMgaW4gdGhlIGRlcGxveW1lbnQgcGlwZWxpbmUKcGFyc2VfcnVuX29wdGlvbnMoKSB7CiAgICAjIHNoZWxsY2hlY2sgZGlzYWJsZT1TQzIyMDYKICAgIGxvY2FsIC1hIG9wdGlvbnM9KCR7MTotfSkKICAgIGlmIFsgIiR7I29wdGlvbnNbQF19IiAtZXEgMCBdOyB0aGVuCiAgICAgICAgbG9nICJSdW5uaW5nIGFsbCBzdGVwcyIKICAgICAgICByZXR1cm4gMAogICAgZmkKCiAgICBsb2NhbCBPUFRJTkQKCWxvY2FsIC1yIGFsbG93ZWRfb3B0aW9ucz0icGZ1aSIKICAgIHdoaWxlIGdldG9wdHMgJHthbGxvd2VkX29wdGlvbnN9IG9wdGlvbnM7IGRvCiAgICAgICAgY2FzZSAiJHtvcHRpb25zfSIgaW4KICAgICAgICAgICAgcCkKICAgICAgICAgICAgICAgIGxvZyAiUnVubmluZyBzdGVwIGNvbmZpZ3VyZV9hbmRfaW5zdGFsbF9kbmZfcGtnc19yZXBvcyIKICAgICAgICAgICAgICAgIGNvbmZpZ3VyZV9hbmRfaW5zdGFsbF9kbmZfcGtnc19yZXBvcwogICAgICAgICAgICAgICAgOzsKICAgICAgICAgICAgZikKICAgICAgICAgICAgICAgIGxvZyAiUnVubmluZyBjb25maWd1cmVfZmlyZXdhbGxkX3J1bGVzIgogICAgICAgICAgICAgICAgY29uZmlndXJlX2ZpcmV3YWxsZF9ydWxlcwogICAgICAgICAgICAgICAgOzsKICAgICAgICAgICAgdSkKICAgICAgICAgICAgICAgIGxvZyAiUnVubmluZyBwdWxsX2NvbnRhaW5lcl9pbWFnZXMgJiBjb25maWd1cmVfc3lzdGVtX3NlcnZpY2VzIgogICAgICAgICAgICAgICAgY29uZmlndXJlX3N5c3RlbV9zZXJ2aWNlcwogICAgICAgICAgICAgICAgOzsKICAgICAgICAgICAgaSkKICAgICAgICAgICAgICAgIGxvZyAiUnVubmluZyBwdWxsX2NvbnRhaW5lcl9pbWFnZXMiCiAgICAgICAgICAgICAgICBwdWxsX2NvbnRhaW5lcl9pbWFnZXMgCiAgICAgICAgICAgICAgICA7OwogICAgICAgICAgICAqKQogICAgICAgICAgICAgICAgdXNhZ2UgYWxsb3dlZF9vcHRpb25zCiAgICAgICAgICAgICAgICBhYm9ydCAiVW5rb3duIG9wdGlvbiBwcm92aWRlZCIKICAgICAgICAgICAgICAgIDs7CiAgICAgICAgZXNhYwogICAgZG9uZQogICAgCiAgICBleGl0IDAKfQoKIyBjb25maWd1cmVfYW5kX2luc3RhbGxfZG5mX3BrZ3NfcmVwb3MKY29uZmlndXJlX2FuZF9pbnN0YWxsX2RuZl9wa2dzX3JlcG9zKCkgewogICAgbG9nICJzdGFydGluZyIKCiAgICAjIHRyYW5zYWN0aW9uIGF0dGVtcHQgcmV0cnkgdGltZSBpbiBzZWNvbmRzCiAgICBsb2NhbCAtcmkgcmV0cnlfd2FpdF90aW1lPTYwCiAgICBjb25maWd1cmVfcmh1aV9yZXBvIHJldHJ5X3dhaXRfdGltZQoKICAgIGxvY2FsIC1hciBleGNsdWRlX3BrZ3M9KAogICAgICAgICIteCBXQUxpbnV4QWdlbnQiCiAgICAgICAgIi14IFdBTGludXhBZ2VudC11ZGV2IgogICAgKQoKICAgIGRuZl91cGRhdGVfcGtncyBleGNsdWRlX3BrZ3MgcmV0cnlfd2FpdF90aW1lCgogICAgbG9jYWwgLXJhIHJlcG9fcnBtX3BrZ3M9KAogICAgICAgIGh0dHBzOi8vZGwuZmVkb3JhcHJvamVjdC5vcmcvcHViL2VwZWwvZXBlbC1yZWxlYXNlLWxhdGVzdC04Lm5vYXJjaC5ycG0KICAgICkKCiAgICBsb2NhbCAtcmEgaW5zdGFsbF9wa2dzPSgKICAgICAgICBwb2RtYW4KICAgICAgICBwb2RtYW4tZG9ja2VyCiAgICApCgogICAgZG5mX2luc3RhbGxfcGtncyByZXBvX3JwbV9wa2dzIHJldHJ5X3dhaXRfdGltZQogICAgZG5mX2luc3RhbGxfcGtncyBpbnN0YWxsX3BrZ3MgcmV0cnlfd2FpdF90aW1lCgoJbG9jYWwgLXIgY3Jvbl93ZWVrbHlfZG5mX3VwZGF0ZV9maWxlbmFtZT0nL2V0Yy9jcm9uLndlZWtseS9kbmZ1cGRhdGUnCglsb2NhbCAtciBjcm9uX3dlZWtseV9kbmZfdXBkYXRlX2ZpbGU9IiMhL2Jpbi9iYXNoCmRuZiB1cGRhdGUgLXkiCgoJd3JpdGVfZmlsZSBjcm9uX3dlZWtseV9kbmZfdXBkYXRlX2ZpbGVuYW1lIGNyb25fd2Vla2x5X2RuZl91cGRhdGVfZmlsZSB0cnVlCgljaG1vZCAreCAiJGNyb25fd2Vla2x5X2RuZl91cGRhdGVfZmlsZW5hbWUiCn0KCiMgY29uZmlndXJlX3JodWlfcmVwbwpjb25maWd1cmVfcmh1aV9yZXBvKCkgewogICAgbG9nICJzdGFydGluZyIKCiAgICBsb2NhbCAtcmEgY21kPSgKICAgICAgICBkbmYKICAgICAgICB1cGRhdGUKICAgICAgICAteQogICAgICAgIC0tZGlzYWJsZXJlcG89JyonCiAgICAgICAgLS1lbmFibGVyZXBvPSdyaHVpLW1pY3Jvc29mdC1henVyZSonCiAgICApCgogICAgbG9nICJydW5uaW5nIFJIVUkgcGFja2FnZSB1cGRhdGVzIgogICAgcmV0cnkgY21kICIkMSIKfQoKIyByZXRyeSBBZGRpbmcgcmV0cnkgbG9naWMgdG8geXVtIGNvbW1hbmRzIGluIG9yZGVyIHRvIGF2b2lkIHN0YWxsaW5nIG91dCBvbiByZXNvdXJjZSBsb2NrcwpyZXRyeSgpIHsKICAgIGxvY2FsIC1uIGNtZF9yZXRyeT0iJDEiCiAgICBsb2NhbCAtbiB3YWl0X3RpbWU9IiQyIgoKICAgIGZvciBhdHRlbXB0IGluIHsxLi41fTsgZG8KICAgICAgICBsb2cgImF0dGVtcHQgIyR7YXR0ZW1wdH0gLSAke0ZVTkNOQU1FWzJdfSIKICAgICAgICAke2NtZF9yZXRyeVtAXX0gJgoKICAgICAgICB3YWl0ICQhICYmIGJyZWFrCiAgICAgICAgaWYgW1sgJHthdHRlbXB0fSAtbHQgNSBdXTsgdGhlbgogICAgICAgICAgICBzbGVlcCAiJHdhaXRfdGltZSIKICAgICAgICBlbHNlCiAgICAgICAgICAgIGFib3J0ICJhdHRlbXB0ICMke2F0dGVtcHR9IC0gRmFpbGVkIHRvIHVwZGF0ZSBwYWNrYWdlcyIKICAgICAgICBmaQogICAgZG9uZQp9CgojIGRuZl91cGRhdGVfcGtncwpkbmZfdXBkYXRlX3BrZ3MoKSB7CiAgICBsb2NhbCAtbiBleGNsdWRlcz0iJDEiCiAgICBsb2cgInN0YXJ0aW5nIgoKICAgIGxvY2FsIC1yYSBjbWQ9KAogICAgICAgIGRuZgogICAgICAgIC15CiAgICAgICAgJHtleGNsdWRlc1tAXX0KICAgICAgICB1cGRhdGUKICAgICAgICAtLWFsbG93ZXJhc2luZwogICAgKQoKICAgIGxvZyAiVXBkYXRpbmcgYWxsIHBhY2thZ2VzIgogICAgcmV0cnkgY21kICIkMiIKfQoKIyBkbmZfaW5zdGFsbF9wa2dzCmRuZl9pbnN0YWxsX3BrZ3MoKSB7CiAgICBsb2NhbCAtbiBwa2dzPSIkMSIKICAgIGxvZyAic3RhcnRpbmciCgogICAgbG9jYWwgLXJhIGNtZD0oCiAgICAgICAgZG5mCiAgICAgICAgLXkKICAgICAgICBpbnN0YWxsCiAgICAgICAgJHtwa2dzW0BdfQogICAgKQoKICAgIGxvZyAiQXR0ZW1wdGluZyB0byBpbnN0YWxsIHBhY2thZ2VzOiAke3BrZ3NbKl19IgogICAgcmV0cnkgY21kICIkMiIKfQoKIyBjb25maWd1cmVfbG9ncm90YXRlIGNsb2JiZXJzIC9ldGMvbG9ncm90YXRlLmNvbmYKY29uZmlndXJlX2xvZ3JvdGF0ZSgpIHsKICAgIGxvZyAic3RhcnRpbmciCgogICAgbG9jYWwgLXIgbG9ncm90YXRlX2NvbmZfZmlsZW5hbWU9Jy9ldGMvbG9ncm90YXRlLmNvbmYnCiAgICBsb2NhbCAtciBsb2dyb3RhdGVfY29uZl9maWxlPScjIHNlZSAibWFuIGxvZ3JvdGF0ZSIgZm9yIGRldGFpbHMKIyByb3RhdGUgbG9nIGZpbGVzIHdlZWtseQp3ZWVrbHkKCiMga2VlcCAyIHdlZWtzIHdvcnRoIG9mIGJhY2tsb2dzCnJvdGF0ZSAyCgojIGNyZWF0ZSBuZXcgKGVtcHR5KSBsb2cgZmlsZXMgYWZ0ZXIgcm90YXRpbmcgb2xkIG9uZXMKY3JlYXRlCgojIHVzZSBkYXRlIGFzIGEgc3VmZml4IG9mIHRoZSByb3RhdGVkIGZpbGUKZGF0ZWV4dAoKIyB1bmNvbW1lbnQgdGhpcyBpZiB5b3Ugd2FudCB5b3VyIGxvZyBmaWxlcyBjb21wcmVzc2VkCmNvbXByZXNzCgojIFJQTSBwYWNrYWdlcyBkcm9wIGxvZyByb3RhdGlvbiBpbmZvcm1hdGlvbiBpbnRvIHRoaXMgZGlyZWN0b3J5CmluY2x1ZGUgL2V0Yy9sb2dyb3RhdGUuZAoKIyBubyBwYWNrYWdlcyBvd24gd3RtcCBhbmQgYnRtcCAtLSB3ZSB3aWxsIHJvdGF0ZSB0aGVtIGhlcmUKL3Zhci9sb2cvd3RtcCB7CiAgICBtb250aGx5CiAgICBjcmVhdGUgMDY2NCByb290IHV0bXAKICAgICAgICBtaW5zaXplIDFNCiAgICByb3RhdGUgMQp9CgovdmFyL2xvZy9idG1wIHsKICAgIG1pc3NpbmdvawogICAgbW9udGhseQogICAgY3JlYXRlIDA2MDAgcm9vdCB1dG1wCiAgICByb3RhdGUgMQp9JwoKICAgIHdyaXRlX2ZpbGUgbG9ncm90YXRlX2NvbmZfZmlsZW5hbWUgbG9ncm90YXRlX2NvbmZfZmlsZSB0cnVlCn0KCiMgY29uZmlndXJlX2ZpcmV3YWxsZF9ydWxlcwpjb25maWd1cmVfZmlyZXdhbGxkX3J1bGVzKCkgewogICAgbG9nICJzdGFydGluZyIKCiAgICAjIGh0dHBzOi8vYWNjZXNzLnJlZGhhdC5jb20vc2VjdXJpdHkvY3ZlL2N2ZS0yMDIwLTEzNDAxCiAgICBsb2NhbCAtciBwcmVmaXg9Ii9ldGMvc3lzY3RsLmQiCiAgICBsb2NhbCAtciBkaXNhYmxlX2FjY2VwdF9yYV9jb25mX2ZpbGVuYW1lPSIkcHJlZml4LzAyLWRpc2FibGUtYWNjZXB0LXJhLmNvbmYiCiAgICBsb2NhbCAtciBkaXNhYmxlX2FjY2VwdF9yYV9jb25mX2ZpbGU9Im5ldC5pcHY2LmNvbmYuYWxsLmFjY2VwdF9yYT0wIgoKICAgIHdyaXRlX2ZpbGUgZGlzYWJsZV9hY2NlcHRfcmFfY29uZl9maWxlbmFtZSBkaXNhYmxlX2FjY2VwdF9yYV9jb25mX2ZpbGUgdHJ1ZQoKICAgIGxvY2FsIC1yIGRpc2FibGVfY29yZV9maWxlbmFtZT0iJHByZWZpeC8wMS1kaXNhYmxlLWNvcmUuY29uZiIKICAgIGxvY2FsIC1yIGRpc2FibGVfY29yZV9maWxlPSJrZXJuZWwuY29yZV9wYXR0ZXJuID0gfC9iaW4vdHJ1ZQogICAgIgogICAgd3JpdGVfZmlsZSBkaXNhYmxlX2NvcmVfZmlsZW5hbWUgZGlzYWJsZV9jb3JlX2ZpbGUgdHJ1ZQoKICAgIHN5c2N0bCAtLXN5c3RlbQoKICAgIGxvY2FsIC1yYSBlbmFibGVfcG9ydHM9KAogICAgICAgICI0NDMvdGNwIgogICAgKQoKICAgIGxvZyAiRW5hYmxpbmcgcG9ydHMgJHtlbmFibGVfcG9ydHNbKl19IG9uIGRlZmF1bHQgZmlyZXdhbGxkIHpvbmUiCiAgICAjIHNoZWxsY2hlY2sgZGlzYWJsZT1TQzIwNjgKICAgIGZvciBwb3J0IGluICR7ZW5hYmxlX3BvcnRzW0BdfTsgZG8KICAgICAgICBsb2cgIkVuYWJsaW5nIHBvcnQgJHBvcnQgbm93IgogICAgICAgIGZpcmV3YWxsLWNtZCAiLS1hZGQtcG9ydD0kcG9ydCIKICAgIGRvbmUKCiAgICBmaXJld2FsbC1jbWQgLS1ydW50aW1lLXRvLXBlcm1hbmVudAp9CgojIHB1bGxfY29udGFpbmVyX2ltYWdlcwpwdWxsX2NvbnRhaW5lcl9pbWFnZXMoKSB7CiAgICBsb2cgInN0YXJ0aW5nIgoKICAgICMgVGhlIG1hbmFnZWQgaWRlbnRpdHkgdGhhdCB0aGUgVk0gcnVucyBhcyBvbmx5IGhhcyBhIHNpbmdsZSByb2xlYXNzaWdubWVudC4KICAgICMgVGhpcyByb2xlIGFzc2lnbm1lbnQgaXMgQUNSUHVsbCB3aGljaCBpcyBub3QgbmVjZXNzYXJpbHkgcHJlc2VudCBpbiB0aGUKICAgICMgc3Vic2NyaXB0aW9uIHdlJ3JlIGRlcGxveWluZyBpbnRvLiAgSWYgdGhlIGlkZW50aXR5IGRvZXMgbm90IGhhdmUgYW55CiAgICAjIHJvbGUgYXNzaWdubWVudHMgc2NvcGVkIG9uIHRoZSBzdWJzY3JpcHRpb24gd2UncmUgZGVwbG95aW5nIGludG8sIGl0IHdpbGwKICAgICMgbm90IHNob3cgb24gYXogbG9naW4gLWksIHdoaWNoIGlzIHdoeSB0aGUgYmVsb3cgbGluZSBpcyBjb21tZW50ZWQuCiAgICAjIGF6IGFjY291bnQgc2V0IC1zICIkU1VCU0NSSVBUSU9OSUQiCiAgICBheiBsb2dpbiAtaSAtLWFsbG93LW5vLXN1YnNjcmlwdGlvbnMKCiAgICAjIFN1cHByZXNzIGVtdWxhdGlvbiBvdXRwdXQgZm9yIHBvZG1hbiBpbnN0ZWFkIG9mIGRvY2tlciBmb3IgYXogYWNyIGNvbXBhdGFiaWxpdHkKICAgIG1rZGlyIC1wIC9ldGMvY29udGFpbmVycy8KICAgIG1rZGlyIC1wIC9yb290Ly5kb2NrZXIKICAgIHRvdWNoIC9ldGMvY29udGFpbmVycy9ub2RvY2tlcgoKCSMgVGhpcyBuYW1lIGlzIHVzZWQgaW4gdGhlIGNhc2UgdGhhdCBheiBhY3IgbG9naW4gc2VhcmNoZXMgZm9yIHRoaXMgaW4gaXQncyBlbnZpcm9ubWVudAogICAgbG9jYWwgLXIgUkVHSVNUUllfQVVUSF9GSUxFPSIvcm9vdC8uZG9ja2VyL2NvbmZpZy5qc29uIgoJbG9jYWwgLXIgcmVnaXN0cnlfY29uZmlnX2ZpbGU9InsKCSJhdXRocyI6IHsKCQlcIiR7UFJPWFlJTUFHRSUlLyp9XCI6IHsKCQkJXCJhdXRoXCI6IFwiJFBST1hZSU1BR0VBVVRIXCIKCQl9Cgl9IgoKCXdyaXRlX2ZpbGUgUkVHSVNUUllfQVVUSF9GSUxFIHJlZ2lzdHJ5X2NvbmZpZ19maWxlIHRydWUKCiAgICBsb2cgImxvZ2dpbmcgaW50byBwcm9kIGFjciIKCiAgICBheiBhY3IgbG9naW4gLS1uYW1lICIkKHNlZCAtZSAnc3wuKi98fCcgPDw8IiRBQ1JSRVNPVVJDRUlEIikiCgogICAgZG9ja2VyIHB1bGwgIiRQUk9YWUlNQUdFIgoKICAgIGF6IGxvZ291dAp9CgojIGNvbmZpZ3VyZV9zeXN0ZW1fc2VydmljZXMgY3JlYXRlcywgY29uZmlndXJlcywgYW5kIGVuYWJsZXMgdGhlIGZvbGxvd2luZyBzeXN0ZW1kIHNlcnZpY2VzIGFuZCB0aW1lcnMKIyBzZXJ2aWNlcwojCXByb3h5CmNvbmZpZ3VyZV9zeXN0ZW1fc2VydmljZXMoKSB7Cgljb25maWd1cmVfc2VydmljZV9wcm94eQp9CgojIGVuYWJsZV9hcm9fc2VydmljZXMgZW5hYmxlcyBhbGwgc2VydmljZXMgcmVxdWlyZWQgZm9yIGFybyBycAplbmFibGVfYXJvX3NlcnZpY2VzKCkgewogICAgbG9nICJzdGFydGluZyIKCiAgICBsb2NhbCAtcmEgYXJvX3NlcnZpY2VzPSgKCQlwcm94eQogICAgKQogICAgbG9nICJlbmFibGluZyBhcm8gc2VydmljZXMgJHthcm9fc2VydmljZXNbKl19IgogICAgIyBzaGVsbGNoZWNrIGRpc2FibGU9U0MyMDY4CiAgICBmb3Igc2VydmljZSBpbiAke2Fyb19zZXJ2aWNlc1tAXX07IGRvCiAgICAgICAgbG9nICJFbmFibGluZyAkc2VydmljZSBub3ciCiAgICAgICAgc3lzdGVtY3RsIGVuYWJsZSAiJHNlcnZpY2Uuc2VydmljZSIKICAgIGRvbmUKfQoKIyBjb25maWd1cmVfY2VydHMKY29uZmlndXJlX2NlcnRzKCkgewogICAgbG9nICJzdGFydGluZyIKCgliYXNlNjQgLWQgPDw8IiRQUk9YWUNFUlQiID4vZXRjL3Byb3h5L3Byb3h5LmNydAoJYmFzZTY0IC1kIDw8PCIkUFJPWFlLRVkiID4vZXRjL3Byb3h5L3Byb3h5LmtleQoJYmFzZTY0IC1kIDw8PCIkUFJPWFlDTElFTlRDRVJUIiA+L2V0Yy9wcm94eS9wcm94eS1jbGllbnQuY3J0CgljaG93biAtUiAxMDAwOjEwMDAgL2V0Yy9wcm94eQoJY2htb2QgMDYwMCAvZXRjL3Byb3h5L3Byb3h5LmtleQp9Cgpjb25maWd1cmVfc2VydmljZV9wcm94eSgpIHsKCWxvY2FsIC1yIHN5c2NvbmZpZ19wcm94eV9maWxlbmFtZT0nL2V0Yy9zeXNjb25maWcvcHJveHknCglsb2NhbCAtciBzeXNjb25maWdfcHJveHlfZmlsZT0iUFJPWFlfSU1BR0U9JyRQUk9YWUlNQUdFJyIKCgl3cml0ZV9maWxlIHN5c2NvbmZpZ19wcm94eV9maWxlbmFtZSBzeXNjb25maWdfcHJveHlfZmlsZSB0cnVlCgoJbG9jYWwgLXIgcHJveHlfc2VydmljZV9maWxlbmFtZT0nL2V0Yy9zeXN0ZW1kL3N5c3RlbS9wcm94eS5zZXJ2aWNlJwoJbG9jYWwgLXIgcHJveHlfc2VydmljZV9maWxlPSJbVW5pdF0KQWZ0ZXI9bmV0d29yay1vbmxpbmUudGFyZ2V0CldhbnRzPW5ldHdvcmstb25saW5lLnRhcmdldAoKW1NlcnZpY2VdCkVudmlyb25tZW50RmlsZT0vZXRjL3N5c2NvbmZpZy9wcm94eQpFeGVjU3RhcnRQcmU9LS91c3IvYmluL2RvY2tlciBybSAtZiAlbgpFeGVjU3RhcnQ9L3Vzci9iaW4vZG9ja2VyIHJ1biAtLXJtIC0tbmFtZSAlbiAtcCA0NDM6ODQ0MyAtdiAvZXRjL3Byb3h5Oi9zZWNyZXRzICRQUk9YWV9JTUFHRQpFeGVjU3RvcD0vdXNyL2Jpbi9kb2NrZXIgc3RvcCAlbgpSZXN0YXJ0PWFsd2F5cwpSZXN0YXJ0U2VjPTEKU3RhcnRMaW1pdEludGVydmFsPTAKCltJbnN0YWxsXQpXYW50ZWRCeT1tdWx0aS11c2VyLnRhcmdldCIKCglsb2NhbCAtciBjcm9uX3dlZWtseV9wdWxsX2ltYWdlX2ZpbGVuYW1lPScvZXRjL2Nyb24ud2Vla2x5L3B1bGwtaW1hZ2UnCglsb2NhbCAtciBjcm9uX3dlZWtseV9wdWxsX2ltYWdlX2ZpbGU9IiMhL2Jpbi9iYXNoCmRvY2tlciBwdWxsICRQUk9YWUlNQUdFCnN5c3RlbWN0bCByZXN0YXJ0IHByb3h5LnNlcnZpY2UiCgkKCXdyaXRlX2ZpbGUgY3Jvbl93ZWVrbHlfcHVsbF9pbWFnZV9maWxlbmFtZSBjcm9uX3dlZWtseV9wdWxsX2ltYWdlX2ZpbGUgdHJ1ZQoJY2htb2QgK3ggIiRjcm9uX3dlZWtseV9wdWxsX2ltYWdlX2ZpbGVuYW1lIgoKCWxvY2FsIC1yIGNyb25fZGFpbHlfcmVzdGFydF9wcm94eV9maWxlbmFtZT0nL2V0Yy9jcm9uLmRhaWx5L3Jlc3RhcnQtcHJveHknCglsb2NhbCAtciBjcm9uX2RhaWx5X3Jlc3RhcnRfcHJveHlfZmlsZT0iIyEvYmluL2Jhc2gKc3lzdGVtY3RsIHJlc3RhcnQgcHJveHkuc2VydmljZSIKCQoJd3JpdGVfZmlsZSBjcm9uX2RhaWx5X3Jlc3RhcnRfcHJveHlfZmlsZW5hbWUgY3Jvbl9kYWlseV9yZXN0YXJ0X3Byb3h5X2ZpbGUKCWNobW9kICt4ICIkY3Jvbl9kYWlseV9yZXN0YXJ0X3Byb3h5X2ZpbGVuYW1lIgp9CgojIHdyaXRlX2ZpbGUKIyBBcmdzCiMgMSkgZmlsZW5hbWUgLSBzdHJpbmcKIyAyKSBmaWxlX2NvbnRlbnRzIC0gc3RyaW5nCiMgMykgY2xvYmJlciAtIGJvb2xlYW47IG9wdGlvbmFsIC0gZGVmYXVsdHMgdG8gZmFsc2UKd3JpdGVfZmlsZSgpIHsKICAgIGxvY2FsIC1uIGZpbGVuYW1lPSIkMSIKICAgIGxvY2FsIC1uIGZpbGVfY29udGVudHM9IiQyIgogICAgbG9jYWwgLXIgY2xvYmJlcj0iJHszOi1mYWxzZX0iCgogICAgaWYgJGNsb2JiZXI7IHRoZW4KICAgICAgICBsb2cgIk92ZXJ3cml0aW5nIGZpbGUgJGZpbGVuYW1lIgogICAgICAgIGVjaG8gIiRmaWxlX2NvbnRlbnRzIiA+ICIkZmlsZW5hbWUiCiAgICBlbHNlCiAgICAgICAgbG9nICJBcHBlbmRpbmcgdG8gJGZpbGVuYW1lIgogICAgICAgIGVjaG8gIiRmaWxlX2NvbnRlbnRzIiA+PiAiJGZpbGVuYW1lIgogICAgZmkKfQoKIyByZWJvb3Rfdm0gcmVzdG9yZXMgYWxsIHNlbGludXggZmlsZSBjb250ZXh0cywgd2FpdHMgMzAgc2Vjb25kcyB0aGVuIHJlYm9vdHMKcmVib290X3ZtKCkgewogICAgbG9nICJzdGFydGluZyIKCiAgICBjb25maWd1cmVfc2VsaW51eCAidHJ1ZSIKICAgIChzbGVlcCAzMCAmJiBsb2cgInJlYm9vdGluZyB2bSBub3ciOyByZWJvb3QpICYKfQoKIyBsb2cgaXMgYSB3cmFwcGVyIGZvciBlY2hvIHRoYXQgaW5jbHVkZXMgdGhlIGZ1bmN0aW9uIG5hbWUKbG9nKCkgewogICAgbG9jYWwgLXIgbXNnPSIkezE6LSJsb2cgbWVzc2FnZSBpcyBlbXB0eSJ9IgogICAgbG9jYWwgLXIgc3RhY2tfbGV2ZWw9IiR7MjotMX0iCiAgICBlY2hvICIke0ZVTkNOQU1FWyR7c3RhY2tfbGV2ZWx9XX06ICR7bXNnfSIKfQoKIyBhYm9ydCBpcyBhIHdyYXBwZXIgZm9yIGxvZyB0aGF0IGV4aXRzIHdpdGggYW4gZXJyb3IgY29kZQphYm9ydCgpIHsKICAgIGxvY2FsIC1yaSBvcmlnaW5fc3RhY2tsZXZlbD0yCiAgICBsb2cgIiR7MX0iICIkb3JpZ2luX3N0YWNrbGV2ZWwiCiAgICBsb2cgIkV4aXRpbmciCiAgICBleGl0IDEKfQoKZXhwb3J0IEFaVVJFX0NMT1VEX05BTUU9IiR7QVpVUkVDTE9VRE5BTUU6PyJGYWlsZWQgdG8gY2Fycnkgb3ZlciB2YXJpYWJsZXMifSIKCm1haW4gIiRAIgo=')))]" }, "provisionAfterExtensions": [ "Microsoft.Azure.Monitor.AzureMonitorLinuxAgent", diff --git a/pkg/deploy/assets/gateway-production.json b/pkg/deploy/assets/gateway-production.json index 1a3296cd889..ecbbe148c12 100644 --- a/pkg/deploy/assets/gateway-production.json +++ b/pkg/deploy/assets/gateway-production.json @@ -309,7 +309,7 @@ "autoUpgradeMinorVersion": true, "settings": {}, "protectedSettings": { - "script": "[base64(concat(base64ToString('c2V0IC1leAoK'),'ACRRESOURCEID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('acrResourceId')),''')\n','AZURECLOUDNAME=$(base64 -d \u003c\u003c\u003c''',base64(parameters('azureCloudName')),''')\n','AZURESECPACKQUALYSURL=$(base64 -d \u003c\u003c\u003c''',base64(parameters('azureSecPackQualysUrl')),''')\n','AZURESECPACKVSATENANTID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('azureSecPackVSATenantId')),''')\n','DATABASEACCOUNTNAME=$(base64 -d \u003c\u003c\u003c''',base64(parameters('databaseAccountName')),''')\n','DBTOKENCLIENTID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('dbtokenClientId')),''')\n','DBTOKENURL=$(base64 -d \u003c\u003c\u003c''',base64(parameters('dbtokenUrl')),''')\n','MDMFRONTENDURL=$(base64 -d \u003c\u003c\u003c''',base64(parameters('mdmFrontendUrl')),''')\n','MDSDENVIRONMENT=$(base64 -d \u003c\u003c\u003c''',base64(parameters('mdsdEnvironment')),''')\n','FLUENTBITIMAGE=$(base64 -d \u003c\u003c\u003c''',base64(parameters('fluentbitImage')),''')\n','GATEWAYMDSDCONFIGVERSION=$(base64 -d \u003c\u003c\u003c''',base64(parameters('gatewayMdsdConfigVersion')),''')\n','GATEWAYDOMAINS=$(base64 -d \u003c\u003c\u003c''',base64(parameters('gatewayDomains')),''')\n','GATEWAYFEATURES=$(base64 -d \u003c\u003c\u003c''',base64(parameters('gatewayFeatures')),''')\n','KEYVAULTDNSSUFFIX=$(base64 -d \u003c\u003c\u003c''',base64(parameters('keyvaultDNSSuffix')),''')\n','KEYVAULTPREFIX=$(base64 -d \u003c\u003c\u003c''',base64(parameters('keyvaultPrefix')),''')\n','RPIMAGE=$(base64 -d \u003c\u003c\u003c''',base64(parameters('rpImage')),''')\n','RPMDMACCOUNT=$(base64 -d \u003c\u003c\u003c''',base64(parameters('rpMdmAccount')),''')\n','RPMDSDACCOUNT=$(base64 -d \u003c\u003c\u003c''',base64(parameters('rpMdsdAccount')),''')\n','RPMDSDNAMESPACE=$(base64 -d \u003c\u003c\u003c''',base64(parameters('rpMdsdNamespace')),''')\n','MDMIMAGE=''/genevamdm:2.2024.328.1744-c5fb79-20240328t1935''\n','LOCATION=$(base64 -d \u003c\u003c\u003c''',base64(resourceGroup().location),''')\n','SUBSCRIPTIONID=$(base64 -d \u003c\u003c\u003c''',base64(subscription().subscriptionId),''')\n','RESOURCEGROUPNAME=$(base64 -d \u003c\u003c\u003c''',base64(resourceGroup().name),''')\n','\n',base64ToString('IyEvYmluL2Jhc2gKCmVjaG8gInNldHRpbmcgc3NoIHBhc3N3b3JkIGF1dGhlbnRpY2F0aW9uIgojIFdlIG5lZWQgdG8gbWFudWFsbHkgc2V0IFBhc3N3b3JkQXV0aGVudGljYXRpb24gdG8gdHJ1ZSBpbiBvcmRlciBmb3IgdGhlIFZNU1MgQWNjZXNzIEpJVCB0byB3b3JrCnNlZCAtaSAncy9QYXNzd29yZEF1dGhlbnRpY2F0aW9uIG5vL1Bhc3N3b3JkQXV0aGVudGljYXRpb24geWVzL2cnIC9ldGMvc3NoL3NzaGRfY29uZmlnCnN5c3RlbWN0bCByZWxvYWQgc3NoZC5zZXJ2aWNlCgojQWRkaW5nIHJldHJ5IGxvZ2ljIHRvIHl1bSBjb21tYW5kcyBpbiBvcmRlciB0byBhdm9pZCBzdGFsbGluZyBvdXQgb24gcmVzb3VyY2UgbG9ja3MKZWNobyAicnVubmluZyBSSFVJIGZpeCIKZm9yIGF0dGVtcHQgaW4gezEuLjV9OyBkbwogIHl1bSB1cGRhdGUgLXkgLS1kaXNhYmxlcmVwbz0nKicgLS1lbmFibGVyZXBvPSdyaHVpLW1pY3Jvc29mdC1henVyZSonICYmIGJyZWFrCiAgaWYgW1sgJHthdHRlbXB0fSAtbHQgNSBdXTsgdGhlbiBzbGVlcCAxMDsgZWxzZSBleGl0IDE7IGZpCmRvbmUKCmVjaG8gInJ1bm5pbmcgeXVtIHVwZGF0ZSIKZm9yIGF0dGVtcHQgaW4gezEuLjV9OyBkbwogIHl1bSAteSAteCBXQUxpbnV4QWdlbnQgLXggV0FMaW51eEFnZW50LXVkZXYgdXBkYXRlIC0tYWxsb3dlcmFzaW5nICYmIGJyZWFrCiAgaWYgW1sgJHthdHRlbXB0fSAtbHQgNSBdXTsgdGhlbiBzbGVlcCAxMDsgZWxzZSBleGl0IDE7IGZpCmRvbmUKCmVjaG8gImV4dGVuZGluZyBwYXJ0aXRpb24gdGFibGUiCiMgTGludXggYmxvY2sgZGV2aWNlcyBhcmUgaW5jb25zaXN0ZW50bHkgbmFtZWQKIyBpdCdzIGRpZmZpY3VsdCB0byB0aWUgdGhlIGx2bSBwdiB0byB0aGUgcGh5c2ljYWwgZGlzayB1c2luZyAvZGV2L2Rpc2sgZmlsZXMsIHdoaWNoIGlzIHdoeSBsdnMgaXMgdXNlZCBoZXJlCnBoeXNpY2FsX2Rpc2s9IiQobHZzIC1vIGRldmljZXMgLWEgfCBoZWFkIC1uMiB8IHRhaWwgLW4xIHwgY3V0IC1kICcgJyAtZiAzIHwgY3V0IC1kIFwoIC1mIDEgfCB0ciAtZCAnWzpkaWdpdDpdJykiCmdyb3dwYXJ0ICIkcGh5c2ljYWxfZGlzayIgMgoKZWNobyAiZXh0ZW5kaW5nIGZpbGVzeXN0ZW1zIgpsdmV4dGVuZCAtbCArMjAlRlJFRSAvZGV2L3Jvb3R2Zy9yb290bHYKeGZzX2dyb3dmcyAvCgpsdmV4dGVuZCAtbCArMTAwJUZSRUUgL2Rldi9yb290dmcvdmFybHYKeGZzX2dyb3dmcyAvdmFyCgpycG0gLS1pbXBvcnQgaHR0cHM6Ly9kbC5mZWRvcmFwcm9qZWN0Lm9yZy9wdWIvZXBlbC9SUE0tR1BHLUtFWS1FUEVMLTgKcnBtIC0taW1wb3J0IGh0dHBzOi8vcGFja2FnZXMubWljcm9zb2Z0LmNvbS9rZXlzL21pY3Jvc29mdC5hc2MKCmZvciBhdHRlbXB0IGluIHsxLi41fTsgZG8KICB5dW0gLXkgaW5zdGFsbCBodHRwczovL2RsLmZlZG9yYXByb2plY3Qub3JnL3B1Yi9lcGVsL2VwZWwtcmVsZWFzZS1sYXRlc3QtOC5ub2FyY2gucnBtICYmIGJyZWFrCiAgaWYgW1sgJHthdHRlbXB0fSAtbHQgNSBdXTsgdGhlbiBzbGVlcCAxMDsgZWxzZSBleGl0IDE7IGZpCmRvbmUKCmVjaG8gImNvbmZpZ3VyaW5nIGxvZ3JvdGF0ZSIKCiMgZ2F0ZXdheV9sb2dkaXIgaXMgYSByZWFkb25seSB2YXJpYWJsZSB0aGF0IHNwZWNpZmllcyB0aGUgaG9zdCBwYXRoIG1vdW50IHBvaW50IGZvciB0aGUgZ2F0ZXdheSBjb250YWluZXIgbG9nIGZpbGUKIyBmb3IgdGhlIHB1cnBvc2Ugb2Ygcm90YXRpbmcgdGhlIGdhdGV3YXkgbG9ncwpkZWNsYXJlIC1yIGdhdGV3YXlfbG9nZGlyPScvdmFyL2xvZy9hcm8tZ2F0ZXdheScKCmNhdCA+L2V0Yy9sb2dyb3RhdGUuY29uZiA8PEVPRgojIHNlZSAibWFuIGxvZ3JvdGF0ZSIgZm9yIGRldGFpbHMKIyByb3RhdGUgbG9nIGZpbGVzIHdlZWtseQp3ZWVrbHkKCiMga2VlcCAyIHdlZWtzIHdvcnRoIG9mIGJhY2tsb2dzCnJvdGF0ZSAyCgojIGNyZWF0ZSBuZXcgKGVtcHR5KSBsb2cgZmlsZXMgYWZ0ZXIgcm90YXRpbmcgb2xkIG9uZXMKY3JlYXRlCgojIHVzZSBkYXRlIGFzIGEgc3VmZml4IG9mIHRoZSByb3RhdGVkIGZpbGUKZGF0ZWV4dAoKIyB1bmNvbW1lbnQgdGhpcyBpZiB5b3Ugd2FudCB5b3VyIGxvZyBmaWxlcyBjb21wcmVzc2VkCmNvbXByZXNzCgojIFJQTSBwYWNrYWdlcyBkcm9wIGxvZyByb3RhdGlvbiBpbmZvcm1hdGlvbiBpbnRvIHRoaXMgZGlyZWN0b3J5CmluY2x1ZGUgL2V0Yy9sb2dyb3RhdGUuZAoKIyBubyBwYWNrYWdlcyBvd24gd3RtcCBhbmQgYnRtcCAtLSB3ZSdsbCByb3RhdGUgdGhlbSBoZXJlCi92YXIvbG9nL3d0bXAgewogICAgbW9udGhseQogICAgY3JlYXRlIDA2NjQgcm9vdCB1dG1wCiAgICAgICAgbWluc2l6ZSAxTQogICAgcm90YXRlIDEKfQoKL3Zhci9sb2cvYnRtcCB7CiAgICBtaXNzaW5nb2sKICAgIG1vbnRobHkKICAgIGNyZWF0ZSAwNjAwIHJvb3QgdXRtcAogICAgcm90YXRlIDEKfQoKIyBNYXhpbXVtIGxvZyBkaXJlY3Rvcnkgc2l6ZSBpcyAxMDBHIHdpdGggdGhpcyBjb25maWd1cmF0aW9uCiMgU2V0dGluZyBsaW1pdCB0byAxMDBHIHRvIGFsbG93IHNwYWNlIGZvciBvdGhlciBsb2dnaW5nIHNlcnZpY2VzCiMgY29weXRydW5jYXRlIGlzIGEgY3JpdGljYWwgb3B0aW9uIHVzZWQgdG8gcHJldmVudCBsb2dzIGZyb20gYmVpbmcgc2hpcHBlZCB0d2ljZQoke2dhdGV3YXlfbG9nZGlyfSB7CiAgICBzaXplIDIwRwogICAgcm90YXRlIDUKICAgIGNyZWF0ZSAwNjAwIHJvb3Qgcm9vdAogICAgY29weXRydW5jYXRlCiAgICBub29sZGRpcgogICAgY29tcHJlc3MKfQpFT0YKCmVjaG8gImNvbmZpZ3VyaW5nIHl1bSByZXBvc2l0b3J5IGFuZCBydW5uaW5nIHl1bSB1cGRhdGUiCmNhdCA+L2V0Yy95dW0ucmVwb3MuZC9henVyZS5yZXBvIDw8J0VPRicKW2F6dXJlLWNsaV0KbmFtZT1henVyZS1jbGkKYmFzZXVybD1odHRwczovL3BhY2thZ2VzLm1pY3Jvc29mdC5jb20veXVtcmVwb3MvYXp1cmUtY2xpCmVuYWJsZWQ9eWVzCmdwZ2NoZWNrPXllcwoKW2F6dXJlY29yZV0KbmFtZT1henVyZWNvcmUKYmFzZXVybD1odHRwczovL3BhY2thZ2VzLm1pY3Jvc29mdC5jb20veXVtcmVwb3MvYXp1cmVjb3JlCmVuYWJsZWQ9eWVzCmdwZ2NoZWNrPW5vCkVPRgoKc2VtYW5hZ2UgZmNvbnRleHQgLWEgLXQgdmFyX2xvZ190ICIvdmFyL2xvZy9qb3VybmFsKC8uKik/Igpta2RpciAtcCAvdmFyL2xvZy9qb3VybmFsCgpmb3IgYXR0ZW1wdCBpbiB7MS4uNX07IGRvCiAgeXVtIC15IGluc3RhbGwgY2xhbWF2IGF6c2VjLWNsYW1hdiBhenNlYy1tb25pdG9yIGF6dXJlLWNsaSBhenVyZS1tZHNkIGF6dXJlLXNlY3VyaXR5IHBvZG1hbi1kb2NrZXIgb3BlbnNzbC1wZXJsIHB5dGhvbjMgJiYgYnJlYWsKICAjIGhhY2sgLSB3ZSBhcmUgaW5zdGFsbGluZyBweXRob24zIG9uIGhvc3RzIGR1ZSB0byBhbiBpc3N1ZSB3aXRoIEF6dXJlIExpbnV4IEV4dGVuc2lvbnMgaHR0cHM6Ly9naXRodWIuY29tL0F6dXJlL2F6dXJlLWxpbnV4LWV4dGVuc2lvbnMvcHVsbC8xNTA1CiAgaWYgW1sgJHthdHRlbXB0fSAtbHQgNSBdXTsgdGhlbiBzbGVlcCAxMDsgZWxzZSBleGl0IDE7IGZpCmRvbmUKCmVjaG8gImFwcGx5aW5nIGZpcmV3YWxsIHJ1bGVzIgojIGh0dHBzOi8vYWNjZXNzLnJlZGhhdC5jb20vc2VjdXJpdHkvY3ZlL2N2ZS0yMDIwLTEzNDAxCmNhdCA+L2V0Yy9zeXNjdGwuZC8wMi1kaXNhYmxlLWFjY2VwdC1yYS5jb25mIDw8J0VPRicKbmV0LmlwdjYuY29uZi5hbGwuYWNjZXB0X3JhPTAKRU9GCgpjYXQgPi9ldGMvc3lzY3RsLmQvMDEtZGlzYWJsZS1jb3JlLmNvbmYgPDwnRU9GJwprZXJuZWwuY29yZV9wYXR0ZXJuID0gfC9iaW4vdHJ1ZQpFT0YKc3lzY3RsIC0tc3lzdGVtCgpmaXJld2FsbC1jbWQgLS1hZGQtcG9ydD04MC90Y3AgLS1wZXJtYW5lbnQKZmlyZXdhbGwtY21kIC0tYWRkLXBvcnQ9ODA4MS90Y3AgLS1wZXJtYW5lbnQKZmlyZXdhbGwtY21kIC0tYWRkLXBvcnQ9NDQzL3RjcCAtLXBlcm1hbmVudAoKZWNobyAibG9nZ2luZyBpbnRvIHByb2QgYWNyIgpleHBvcnQgQVpVUkVfQ0xPVURfTkFNRT0kQVpVUkVDTE9VRE5BTUUKYXogbG9naW4gLWkgLS1hbGxvdy1uby1zdWJzY3JpcHRpb25zCgojIFRoZSBtYW5hZ2VkIGlkZW50aXR5IHRoYXQgdGhlIFZNIHJ1bnMgYXMgb25seSBoYXMgYSBzaW5nbGUgcm9sZWFzc2lnbm1lbnQuCiMgVGhpcyByb2xlIGFzc2lnbm1lbnQgaXMgQUNSUHVsbCB3aGljaCBpcyBub3QgbmVjZXNzYXJpbHkgcHJlc2VudCBpbiB0aGUKIyBzdWJzY3JpcHRpb24gd2UncmUgZGVwbG95aW5nIGludG8uICBJZiB0aGUgaWRlbnRpdHkgZG9lcyBub3QgaGF2ZSBhbnkKIyByb2xlIGFzc2lnbm1lbnRzIHNjb3BlZCBvbiB0aGUgc3Vic2NyaXB0aW9uIHdlJ3JlIGRlcGxveWluZyBpbnRvLCBpdCB3aWxsCiMgbm90IHNob3cgb24gYXogbG9naW4gLWksIHdoaWNoIGlzIHdoeSB0aGUgYmVsb3cgbGluZSBpcyBjb21tZW50ZWQuCiMgYXogYWNjb3VudCBzZXQgLXMgIiRTVUJTQ1JJUFRJT05JRCIKCiMgU3VwcHJlc3MgZW11bGF0aW9uIG91dHB1dCBmb3IgcG9kbWFuIGluc3RlYWQgb2YgZG9ja2VyIGZvciBheiBhY3IgY29tcGF0YWJpbGl0eQpta2RpciAtcCAvZXRjL2NvbnRhaW5lcnMvCnRvdWNoIC9ldGMvY29udGFpbmVycy9ub2RvY2tlcgoKbWtkaXIgLXAgL3Jvb3QvLmRvY2tlcgpSRUdJU1RSWV9BVVRIX0ZJTEU9L3Jvb3QvLmRvY2tlci9jb25maWcuanNvbiBheiBhY3IgbG9naW4gLS1uYW1lICIkKHNlZCAtZSAnc3wuKi98fCcgPDw8IiRBQ1JSRVNPVVJDRUlEIikiCgpNRE1JTUFHRT0iJHtSUElNQUdFJSUvKn0vJHtNRE1JTUFHRSMjKi99Igpkb2NrZXIgcHVsbCAiJE1ETUlNQUdFIgpkb2NrZXIgcHVsbCAiJFJQSU1BR0UiCmRvY2tlciBwdWxsICIkRkxVRU5UQklUSU1BR0UiCgpheiBsb2dvdXQKCmVjaG8gImNvbmZpZ3VyaW5nIGZsdWVudGJpdCBzZXJ2aWNlIgpta2RpciAtcCAvZXRjL2ZsdWVudGJpdC8KbWtkaXIgLXAgL3Zhci9saWIvZmx1ZW50CgpjYXQgPi9ldGMvZmx1ZW50Yml0L2ZsdWVudGJpdC5jb25mIDw8J0VPRicKW0lOUFVUXQoJTmFtZSBzeXN0ZW1kCglUYWcgam91cm5hbGQKCVN5c3RlbWRfRmlsdGVyIF9DT01NPWFybwoJREIgL3Zhci9saWIvZmx1ZW50L2pvdXJuYWxkYgoKW0ZJTFRFUl0KCU5hbWUgbW9kaWZ5CglNYXRjaCBqb3VybmFsZAoJUmVtb3ZlX3dpbGRjYXJkIF8KCVJlbW92ZSBUSU1FU1RBTVAKCltPVVRQVVRdCglOYW1lIGZvcndhcmQKCU1hdGNoICoKCVBvcnQgMjkyMzAKRU9GCgplY2hvICJGTFVFTlRCSVRJTUFHRT0kRkxVRU5UQklUSU1BR0UiID4vZXRjL3N5c2NvbmZpZy9mbHVlbnRiaXQKCmNhdCA+L2V0Yy9zeXN0ZW1kL3N5c3RlbS9mbHVlbnRiaXQuc2VydmljZSA8PCdFT0YnCltVbml0XQpBZnRlcj1uZXR3b3JrLW9ubGluZS50YXJnZXQKV2FudHM9bmV0d29yay1vbmxpbmUudGFyZ2V0ClN0YXJ0TGltaXRJbnRlcnZhbFNlYz0wCgpbU2VydmljZV0KUmVzdGFydFNlYz0xcwpFbnZpcm9ubWVudEZpbGU9L2V0Yy9zeXNjb25maWcvZmx1ZW50Yml0CkV4ZWNTdGFydFByZT0tL3Vzci9iaW4vZG9ja2VyIHJtIC1mICVOCkV4ZWNTdGFydD0vdXNyL2Jpbi9kb2NrZXIgcnVuIFwKICAtLXNlY3VyaXR5LW9wdCBsYWJlbD1kaXNhYmxlIFwKICAtLWVudHJ5cG9pbnQgL29wdC90ZC1hZ2VudC1iaXQvYmluL3RkLWFnZW50LWJpdCBcCiAgLS1uZXQ9aG9zdCBcCiAgLS1ob3N0bmFtZSAlSCBcCiAgLS1uYW1lICVOIFwKICAtLXJtIFwKICAtLWNhcC1kcm9wIG5ldF9yYXcgXAogIC12IC9ldGMvZmx1ZW50Yml0L2ZsdWVudGJpdC5jb25mOi9ldGMvZmx1ZW50Yml0L2ZsdWVudGJpdC5jb25mIFwKICAtdiAvdmFyL2xpYi9mbHVlbnQ6L3Zhci9saWIvZmx1ZW50OnogXAogIC12IC92YXIvbG9nL2pvdXJuYWw6L3Zhci9sb2cvam91cm5hbDpybyBcCiAgLXYgL2V0Yy9tYWNoaW5lLWlkOi9ldGMvbWFjaGluZS1pZDpybyBcCiAgJEZMVUVOVEJJVElNQUdFIFwKICAtYyAvZXRjL2ZsdWVudGJpdC9mbHVlbnRiaXQuY29uZgoKRXhlY1N0b3A9L3Vzci9iaW4vZG9ja2VyIHN0b3AgJU4KUmVzdGFydD1hbHdheXMKUmVzdGFydFNlYz01ClN0YXJ0TGltaXRJbnRlcnZhbD0wCgpbSW5zdGFsbF0KV2FudGVkQnk9bXVsdGktdXNlci50YXJnZXQKRU9GCgplY2hvICJjb25maWd1cmluZyBtZG0gc2VydmljZSIKY2F0ID4vZXRjL3N5c2NvbmZpZy9tZG0gPDxFT0YKTURNRlJPTlRFTkRVUkw9JyRNRE1GUk9OVEVORFVSTCcKTURNSU1BR0U9JyRNRE1JTUFHRScKTURNU09VUkNFRU5WSVJPTk1FTlQ9JyRMT0NBVElPTicKTURNU09VUkNFUk9MRT1nYXRld2F5Ck1ETVNPVVJDRVJPTEVJTlNUQU5DRT0nJChob3N0bmFtZSknCkVPRgoKbWtkaXIgL3Zhci9ldHcKY2F0ID4vZXRjL3N5c3RlbWQvc3lzdGVtL21kbS5zZXJ2aWNlIDw8J0VPRicKW1VuaXRdCkFmdGVyPW5ldHdvcmstb25saW5lLnRhcmdldApXYW50cz1uZXR3b3JrLW9ubGluZS50YXJnZXQKCltTZXJ2aWNlXQpFbnZpcm9ubWVudEZpbGU9L2V0Yy9zeXNjb25maWcvbWRtCkV4ZWNTdGFydFByZT0tL3Vzci9iaW4vZG9ja2VyIHJtIC1mICVOCkV4ZWNTdGFydD0vdXNyL2Jpbi9kb2NrZXIgcnVuIFwKICAtLWVudHJ5cG9pbnQgL3Vzci9zYmluL01ldHJpY3NFeHRlbnNpb24gXAogIC0taG9zdG5hbWUgJUggXAogIC0tbmFtZSAlTiBcCiAgLS1ybSBcCiAgLS1jYXAtZHJvcCBuZXRfcmF3IFwKICAtbSAyZyBcCiAgLXYgL2V0Yy9tZG0ucGVtOi9ldGMvbWRtLnBlbSBcCiAgLXYgL3Zhci9ldHc6L3Zhci9ldHc6eiBcCiAgJE1ETUlNQUdFIFwKICAtQ2VydEZpbGUgL2V0Yy9tZG0ucGVtIFwKICAtRnJvbnRFbmRVcmwgJE1ETUZST05URU5EVVJMIFwKICAtTG9nZ2VyIENvbnNvbGUgXAogIC1Mb2dMZXZlbCBXYXJuaW5nIFwKICAtUHJpdmF0ZUtleUZpbGUgL2V0Yy9tZG0ucGVtIFwKICAtU291cmNlRW52aXJvbm1lbnQgJE1ETVNPVVJDRUVOVklST05NRU5UIFwKICAtU291cmNlUm9sZSAkTURNU09VUkNFUk9MRSBcCiAgLVNvdXJjZVJvbGVJbnN0YW5jZSAkTURNU09VUkNFUk9MRUlOU1RBTkNFCkV4ZWNTdG9wPS91c3IvYmluL2RvY2tlciBzdG9wICVOClJlc3RhcnQ9YWx3YXlzClJlc3RhcnRTZWM9MQpTdGFydExpbWl0SW50ZXJ2YWw9MAoKW0luc3RhbGxdCldhbnRlZEJ5PW11bHRpLXVzZXIudGFyZ2V0CkVPRgoKZWNobyAiY29uZmlndXJpbmcgYXJvLWdhdGV3YXkgc2VydmljZSIKY2F0ID4vZXRjL3N5c2NvbmZpZy9hcm8tZ2F0ZXdheSA8PEVPRgpBQ1JfUkVTT1VSQ0VfSUQ9JyRBQ1JSRVNPVVJDRUlEJwpEQVRBQkFTRV9BQ0NPVU5UX05BTUU9JyREQVRBQkFTRUFDQ09VTlROQU1FJwpBWlVSRV9EQlRPS0VOX0NMSUVOVF9JRD0nJERCVE9LRU5DTElFTlRJRCcKREJUT0tFTl9VUkw9JyREQlRPS0VOVVJMJwpNRE1fQUNDT1VOVD0iJFJQTURNQUNDT1VOVCIKTURNX05BTUVTUEFDRT1HYXRld2F5CkdBVEVXQVlfRE9NQUlOUz0nJEdBVEVXQVlET01BSU5TJwpHQVRFV0FZX0ZFQVRVUkVTPSckR0FURVdBWUZFQVRVUkVTJwpSUElNQUdFPSckUlBJTUFHRScKRU9GCgpjYXQgPi9ldGMvc3lzdGVtZC9zeXN0ZW0vYXJvLWdhdGV3YXkuc2VydmljZSA8PEVPRgpbVW5pdF0KQWZ0ZXI9bmV0d29yay1vbmxpbmUudGFyZ2V0CldhbnRzPW5ldHdvcmstb25saW5lLnRhcmdldAoKW1NlcnZpY2VdCkVudmlyb25tZW50RmlsZT0vZXRjL3N5c2NvbmZpZy9hcm8tZ2F0ZXdheQpFeGVjU3RhcnRQcmU9LS91c3IvYmluL2RvY2tlciBybSAtZiAlTgpFeGVjU3RhcnRQcmU9L3Vzci9iaW4vbWtkaXIgLXAgJHtnYXRld2F5X2xvZ2Rpcn0KRXhlY1N0YXJ0PS91c3IvYmluL2RvY2tlciBydW4gXAogIC0taG9zdG5hbWUgJUggXAogIC0tbmFtZSAlTiBcCiAgLS1ybSBcCiAgLS1jYXAtZHJvcCBuZXRfcmF3IFwKICAtZSBBQ1JfUkVTT1VSQ0VfSUQgXAogIC1lIERBVEFCQVNFX0FDQ09VTlRfTkFNRSBcCiAgLWUgQVpVUkVfREJUT0tFTl9DTElFTlRfSUQgXAogIC1lIERCVE9LRU5fVVJMIFwKICAtZSBHQVRFV0FZX0RPTUFJTlMgXAogIC1lIEdBVEVXQVlfRkVBVFVSRVMgXAogIC1lIE1ETV9BQ0NPVU5UIFwKICAtZSBNRE1fTkFNRVNQQUNFIFwKICAtbSAyZyBcCiAgLXAgODA6ODA4MCBcCiAgLXAgODA4MTo4MDgxIFwKICAtcCA0NDM6ODQ0MyBcCiAgLXYgL3J1bi9zeXN0ZW1kL2pvdXJuYWw6L3J1bi9zeXN0ZW1kL2pvdXJuYWwgXAogIC12IC92YXIvZXR3Oi92YXIvZXR3OnogXAogIC12ICR7Z2F0ZXdheV9sb2dkaXJ9Oi9jdHIubG9nOnogXAogIFwkUlBJTUFHRSBcCiAgZ2F0ZXdheQpFeGVjU3RvcD0vdXNyL2Jpbi9kb2NrZXIgc3RvcCAtdCAzNjAwICVOClRpbWVvdXRTdG9wU2VjPTM2MDAKUmVzdGFydD1hbHdheXMKUmVzdGFydFNlYz0xClN0YXJ0TGltaXRJbnRlcnZhbD0wCgpbSW5zdGFsbF0KV2FudGVkQnk9bXVsdGktdXNlci50YXJnZXQKRU9GCgpjaGNvbiAtUiBzeXN0ZW1fdTpvYmplY3Rfcjp2YXJfbG9nX3Q6czAgL3Zhci9vcHQvbWljcm9zb2Z0L2xpbnV4bW9uYWdlbnQKCm1rZGlyIC1wIC92YXIvbGliL3dhYWdlbnQvTWljcm9zb2Z0LkF6dXJlLktleVZhdWx0LlN0b3JlCgplY2hvICJjb25maWd1cmluZyBtZHNkIGFuZCBtZG0gc2VydmljZXMiCmZvciB2YXIgaW4gIm1kc2QiICJtZG0iOyBkbwpjYXQgPi9ldGMvc3lzdGVtZC9zeXN0ZW0vZG93bmxvYWQtJHZhci1jcmVkZW50aWFscy5zZXJ2aWNlIDw8RU9GCltVbml0XQpEZXNjcmlwdGlvbj1QZXJpb2RpYyAkdmFyIGNyZWRlbnRpYWxzIHJlZnJlc2gKCltTZXJ2aWNlXQpUeXBlPW9uZXNob3QKRXhlY1N0YXJ0PS91c3IvbG9jYWwvYmluL2Rvd25sb2FkLWNyZWRlbnRpYWxzLnNoICR2YXIKRU9GCgpjYXQgPi9ldGMvc3lzdGVtZC9zeXN0ZW0vZG93bmxvYWQtJHZhci1jcmVkZW50aWFscy50aW1lciA8PEVPRgpbVW5pdF0KRGVzY3JpcHRpb249UGVyaW9kaWMgJHZhciBjcmVkZW50aWFscyByZWZyZXNoCkFmdGVyPW5ldHdvcmstb25saW5lLnRhcmdldApXYW50cz1uZXR3b3JrLW9ubGluZS50YXJnZXQKCltUaW1lcl0KT25Cb290U2VjPTBtaW4KT25DYWxlbmRhcj0wLzEyOjAwOjAwCkFjY3VyYWN5U2VjPTVzCgpbSW5zdGFsbF0KV2FudGVkQnk9dGltZXJzLnRhcmdldApFT0YKZG9uZQoKY2F0ID4vdXNyL2xvY2FsL2Jpbi9kb3dubG9hZC1jcmVkZW50aWFscy5zaCA8PEVPRgojIS9iaW4vYmFzaApzZXQgLWV1CgpDT01QT05FTlQ9IlwkMSIKZWNobyAiRG93bmxvYWQgXCRDT01QT05FTlQgY3JlZGVudGlhbHMiCgpURU1QX0RJUj1cJChta3RlbXAgLWQpCmV4cG9ydCBBWlVSRV9DT05GSUdfRElSPVwkKG1rdGVtcCAtZCkKCmVjaG8gIkxvZ2dpbmcgaW50byBBenVyZS4uLiIKUkVUUklFUz0zCndoaWxlIFsgIlwkUkVUUklFUyIgLWd0IDAgXTsgZG8KICAgIGlmIGF6IGxvZ2luIC1pIC0tYWxsb3ctbm8tc3Vic2NyaXB0aW9ucwogICAgdGhlbgogICAgICAgIGVjaG8gImF6IGxvZ2luIHN1Y2Nlc3NmdWwiCiAgICAgICAgYnJlYWsKICAgIGVsc2UKICAgICAgICBlY2hvICJheiBsb2dpbiBmYWlsZWQuIFJldHJ5aW5nLi4uIgogICAgICAgIGxldCBSRVRSSUVTLT0xCiAgICAgICAgc2xlZXAgNQogICAgZmkKZG9uZQoKdHJhcCAiY2xlYW51cCIgRVhJVAoKY2xlYW51cCgpIHsKICBheiBsb2dvdXQKICBbWyAiXCRURU1QX0RJUiIgPX4gL3RtcC8uKyBdXSAmJiBybSAtcmYgXCRURU1QX0RJUgogIFtbICJcJEFaVVJFX0NPTkZJR19ESVIiID1+IC90bXAvLisgXV0gJiYgcm0gLXJmIFwkQVpVUkVfQ09ORklHX0RJUgp9CgppZiBbICJcJENPTVBPTkVOVCIgPSAibWRtIiBdOyB0aGVuCiAgQ1VSUkVOVF9DRVJUX0ZJTEU9Ii9ldGMvbWRtLnBlbSIKZWxpZiBbICJcJENPTVBPTkVOVCIgPSAibWRzZCIgXTsgdGhlbgogIENVUlJFTlRfQ0VSVF9GSUxFPSIvdmFyL2xpYi93YWFnZW50L01pY3Jvc29mdC5BenVyZS5LZXlWYXVsdC5TdG9yZS9tZHNkLnBlbSIKZWxzZQogIGVjaG8gSW52YWxpZCB1c2FnZSAmJiBleGl0IDEKZmkKClNFQ1JFVF9OQU1FPSJnd3ktXCR7Q09NUE9ORU5UfSIKTkVXX0NFUlRfRklMRT0iXCRURU1QX0RJUi9cJENPTVBPTkVOVC5wZW0iCmZvciBhdHRlbXB0IGluIHsxLi41fTsgZG8KICBheiBrZXl2YXVsdCBzZWNyZXQgZG93bmxvYWQgLS1maWxlIFwkTkVXX0NFUlRfRklMRSAtLWlkICJodHRwczovLyRLRVlWQVVMVFBSRUZJWC1nd3kuJEtFWVZBVUxURE5TU1VGRklYL3NlY3JldHMvXCRTRUNSRVRfTkFNRSIgJiYgYnJlYWsKICBpZiBbWyBcJGF0dGVtcHQgLWx0IDUgXV07IHRoZW4gc2xlZXAgMTA7IGVsc2UgZXhpdCAxOyBmaQpkb25lCgppZiBbIC1mIFwkTkVXX0NFUlRfRklMRSBdOyB0aGVuCiAgaWYgWyAiXCRDT01QT05FTlQiID0gIm1kc2QiIF07IHRoZW4KICAgIGNob3duIHN5c2xvZzpzeXNsb2cgXCRORVdfQ0VSVF9GSUxFCiAgZWxzZQogICAgc2VkIC1pIC1uZSAnMSwvRU5EIENFUlRJRklDQVRFLyBwJyBcJE5FV19DRVJUX0ZJTEUKICBmaQoKICBuZXdfY2VydF9zbj0iXCQob3BlbnNzbCB4NTA5IC1pbiAiXCRORVdfQ0VSVF9GSUxFIiAtbm9vdXQgLXNlcmlhbCB8IGF3ayAtRj0gJ3twcmludCBcJDJ9JykiCiAgY3VycmVudF9jZXJ0X3NuPSJcJChvcGVuc3NsIHg1MDkgLWluICJcJENVUlJFTlRfQ0VSVF9GSUxFIiAtbm9vdXQgLXNlcmlhbCB8IGF3ayAtRj0gJ3twcmludCBcJDJ9JykiCiAgaWYgW1sgISAteiBcJG5ld19jZXJ0X3NuIF1dICYmIFtbIFwkbmV3X2NlcnRfc24gIT0gIlwkY3VycmVudF9jZXJ0X3NuIiBdXTsgdGhlbgogICAgZWNobyB1cGRhdGluZyBjZXJ0aWZpY2F0ZSBmb3IgXCRDT01QT05FTlQKICAgIGNobW9kIDA2MDAgXCRORVdfQ0VSVF9GSUxFCiAgICBtdiBcJE5FV19DRVJUX0ZJTEUgXCRDVVJSRU5UX0NFUlRfRklMRQogIGZpCmVsc2UKICBlY2hvIEZhaWxlZCB0byByZWZyZXNoIGNlcnRpZmljYXRlIGZvciBcJENPTVBPTkVOVCAmJiBleGl0IDEKZmkKRU9GCgpjaG1vZCB1K3ggL3Vzci9sb2NhbC9iaW4vZG93bmxvYWQtY3JlZGVudGlhbHMuc2gKCnN5c3RlbWN0bCBlbmFibGUgZG93bmxvYWQtbWRzZC1jcmVkZW50aWFscy50aW1lcgpzeXN0ZW1jdGwgZW5hYmxlIGRvd25sb2FkLW1kbS1jcmVkZW50aWFscy50aW1lcgoKL3Vzci9sb2NhbC9iaW4vZG93bmxvYWQtY3JlZGVudGlhbHMuc2ggbWRzZAovdXNyL2xvY2FsL2Jpbi9kb3dubG9hZC1jcmVkZW50aWFscy5zaCBtZG0KTURTRENFUlRJRklDQVRFU0FOPSQob3BlbnNzbCB4NTA5IC1pbiAvdmFyL2xpYi93YWFnZW50L01pY3Jvc29mdC5BenVyZS5LZXlWYXVsdC5TdG9yZS9tZHNkLnBlbSAtbm9vdXQgLXN1YmplY3QgfCBzZWQgLWUgJ3MvLipDTiA9IC8vJykKCmNhdCA+L2V0Yy9zeXN0ZW1kL3N5c3RlbS93YXRjaC1tZG0tY3JlZGVudGlhbHMuc2VydmljZSA8PEVPRgpbVW5pdF0KRGVzY3JpcHRpb249V2F0Y2ggZm9yIGNoYW5nZXMgaW4gbWRtLnBlbSBhbmQgcmVzdGFydHMgdGhlIG1kbSBzZXJ2aWNlCgpbU2VydmljZV0KVHlwZT1vbmVzaG90CkV4ZWNTdGFydD0vdXNyL2Jpbi9zeXN0ZW1jdGwgcmVzdGFydCBtZG0uc2VydmljZQoKW0luc3RhbGxdCldhbnRlZEJ5PW11bHRpLXVzZXIudGFyZ2V0CkVPRgoKY2F0ID4vZXRjL3N5c3RlbWQvc3lzdGVtL3dhdGNoLW1kbS1jcmVkZW50aWFscy5wYXRoIDw8RU9GCltQYXRoXQpQYXRoTW9kaWZpZWQ9L2V0Yy9tZG0ucGVtCgpbSW5zdGFsbF0KV2FudGVkQnk9bXVsdGktdXNlci50YXJnZXQKRU9GCgpzeXN0ZW1jdGwgZW5hYmxlIHdhdGNoLW1kbS1jcmVkZW50aWFscy5wYXRoCnN5c3RlbWN0bCBzdGFydCB3YXRjaC1tZG0tY3JlZGVudGlhbHMucGF0aAoKbWtkaXIgL2V0Yy9zeXN0ZW1kL3N5c3RlbS9tZHNkLnNlcnZpY2UuZApjYXQgPi9ldGMvc3lzdGVtZC9zeXN0ZW0vbWRzZC5zZXJ2aWNlLmQvb3ZlcnJpZGUuY29uZiA8PCdFT0YnCltVbml0XQpBZnRlcj1uZXR3b3JrLW9ubGluZS50YXJnZXQKRU9GCgpjYXQgPi9ldGMvZGVmYXVsdC9tZHNkIDw8RU9GCk1EU0RfUk9MRV9QUkVGSVg9L3Zhci9ydW4vbWRzZC9kZWZhdWx0Ck1EU0RfT1BUSU9OUz0iLUEgLWQgLXIgXCRNRFNEX1JPTEVfUFJFRklYIgoKZXhwb3J0IE1PTklUT1JJTkdfR0NTX0VOVklST05NRU5UPSckTURTREVOVklST05NRU5UJwpleHBvcnQgTU9OSVRPUklOR19HQ1NfQUNDT1VOVD0nJFJQTURTREFDQ09VTlQnCmV4cG9ydCBNT05JVE9SSU5HX0dDU19SRUdJT049JyRMT0NBVElPTicKZXhwb3J0IE1PTklUT1JJTkdfR0NTX0FVVEhfSURfVFlQRT1BdXRoS2V5VmF1bHQKZXhwb3J0IE1PTklUT1JJTkdfR0NTX0FVVEhfSUQ9JyRNRFNEQ0VSVElGSUNBVEVTQU4nCmV4cG9ydCBNT05JVE9SSU5HX0dDU19OQU1FU1BBQ0U9JyRSUE1EU0ROQU1FU1BBQ0UnCmV4cG9ydCBNT05JVE9SSU5HX0NPTkZJR19WRVJTSU9OPSckR0FURVdBWU1EU0RDT05GSUdWRVJTSU9OJwpleHBvcnQgTU9OSVRPUklOR19VU0VfR0VORVZBX0NPTkZJR19TRVJWSUNFPXRydWUKCmV4cG9ydCBNT05JVE9SSU5HX1RFTkFOVD0nJExPQ0FUSU9OJwpleHBvcnQgTU9OSVRPUklOR19ST0xFPWdhdGV3YXkKZXhwb3J0IE1PTklUT1JJTkdfUk9MRV9JTlNUQU5DRT0nJChob3N0bmFtZSknCgpleHBvcnQgTURTRF9NU0dQQUNLX1NPUlRfQ09MVU1OUz0xCkVPRgoKIyBzZXR0aW5nIE1PTklUT1JJTkdfR0NTX0FVVEhfSURfVFlQRT1BdXRoS2V5VmF1bHQgc2VlbXMgdG8gaGF2ZSBjYXVzZWQgbWRzZCBub3QKIyB0byBob25vdXIgU1NMX0NFUlRfRklMRSBhbnkgbW9yZSwgaGVhdmVuIG9ubHkga25vd3Mgd2h5Lgpta2RpciAtcCAvdXNyL2xpYi9zc2wvY2VydHMKY3NwbGl0IC1mIC91c3IvbGliL3NzbC9jZXJ0cy9jZXJ0LSAtYiAlMDNkLnBlbSAvZXRjL3BraS90bHMvY2VydHMvY2EtYnVuZGxlLmNydCAvXiQvMSB7Kn0gPi9kZXYvbnVsbApjX3JlaGFzaCAvdXNyL2xpYi9zc2wvY2VydHMKCiMgd2UgbGVhdmUgY2xpZW50SWQgYmxhbmsgYXMgbG9uZyBhcyBvbmx5IDEgbWFuYWdlZCBpZGVudGl0eSBhc3NpZ25lZCB0byB2bXNzCiMgaWYgd2UgaGF2ZSBtb3JlIHRoYW4gMSwgd2Ugd2lsbCBuZWVkIHRvIHBvcHVsYXRlIHdpdGggY2xpZW50SWQgdXNlZCBmb3Igb2ZmLW5vZGUgc2Nhbm5pbmcKY2F0ID4vZXRjL2RlZmF1bHQvdnNhLW5vZGVzY2FuLWFnZW50LmNvbmZpZyA8PEVPRgp7CiAgICAiTmljZSI6IDE5LAogICAgIlRpbWVvdXQiOiAxMDgwMCwKICAgICJDbGllbnRJZCI6ICIiLAogICAgIlRlbmFudElkIjogIiRBWlVSRVNFQ1BBQ0tWU0FURU5BTlRJRCIsCiAgICAiUXVhbHlzU3RvcmVCYXNlVXJsIjogIiRBWlVSRVNFQ1BBQ0tRVUFMWVNVUkwiLAogICAgIlByb2Nlc3NUaW1lb3V0IjogMzAwLAogICAgIkNvbW1hbmREZWxheSI6IDAKICB9CkVPRgoKZWNobyAiZW5hYmxpbmcgYXJvIHNlcnZpY2VzIgpmb3Igc2VydmljZSBpbiBhcm8tZ2F0ZXdheSBhdW9tcyBhenNlY2QgYXpzZWNtb25kIG1kc2QgbWRtIGNocm9ueWQgZmx1ZW50Yml0OyBkbwogIHN5c3RlbWN0bCBlbmFibGUgJHNlcnZpY2Uuc2VydmljZQpkb25lCgpmb3Igc2NhbiBpbiBiYXNlbGluZSBjbGFtYXYgc29mdHdhcmU7IGRvCiAgL3Vzci9sb2NhbC9iaW4vYXpzZWNkIGNvbmZpZyAtcyAkc2NhbiAtZCBQMUQKZG9uZQoKZWNobyAicmVib290aW5nIgpyZXN0b3JlY29uIC1SRiAvdmFyL2xvZy8qCihzbGVlcCAzMDsgcmVib290KSAmCg==')))]" + "script": "[base64(concat(base64ToString('c2V0IC1leAoK'),'ACRRESOURCEID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('acrResourceId')),''')\n','AZURECLOUDNAME=$(base64 -d \u003c\u003c\u003c''',base64(parameters('azureCloudName')),''')\n','AZURESECPACKQUALYSURL=$(base64 -d \u003c\u003c\u003c''',base64(parameters('azureSecPackQualysUrl')),''')\n','AZURESECPACKVSATENANTID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('azureSecPackVSATenantId')),''')\n','DATABASEACCOUNTNAME=$(base64 -d \u003c\u003c\u003c''',base64(parameters('databaseAccountName')),''')\n','DBTOKENCLIENTID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('dbtokenClientId')),''')\n','DBTOKENURL=$(base64 -d \u003c\u003c\u003c''',base64(parameters('dbtokenUrl')),''')\n','MDMFRONTENDURL=$(base64 -d \u003c\u003c\u003c''',base64(parameters('mdmFrontendUrl')),''')\n','MDSDENVIRONMENT=$(base64 -d \u003c\u003c\u003c''',base64(parameters('mdsdEnvironment')),''')\n','FLUENTBITIMAGE=$(base64 -d \u003c\u003c\u003c''',base64(parameters('fluentbitImage')),''')\n','GATEWAYMDSDCONFIGVERSION=$(base64 -d \u003c\u003c\u003c''',base64(parameters('gatewayMdsdConfigVersion')),''')\n','GATEWAYDOMAINS=$(base64 -d \u003c\u003c\u003c''',base64(parameters('gatewayDomains')),''')\n','GATEWAYFEATURES=$(base64 -d \u003c\u003c\u003c''',base64(parameters('gatewayFeatures')),''')\n','KEYVAULTDNSSUFFIX=$(base64 -d \u003c\u003c\u003c''',base64(parameters('keyvaultDNSSuffix')),''')\n','KEYVAULTPREFIX=$(base64 -d \u003c\u003c\u003c''',base64(parameters('keyvaultPrefix')),''')\n','RPIMAGE=$(base64 -d \u003c\u003c\u003c''',base64(parameters('rpImage')),''')\n','RPMDMACCOUNT=$(base64 -d \u003c\u003c\u003c''',base64(parameters('rpMdmAccount')),''')\n','RPMDSDACCOUNT=$(base64 -d \u003c\u003c\u003c''',base64(parameters('rpMdsdAccount')),''')\n','RPMDSDNAMESPACE=$(base64 -d \u003c\u003c\u003c''',base64(parameters('rpMdsdNamespace')),''')\n','MDMIMAGE=''/genevamdm:2.2024.328.1744-c5fb79-20240328t1935''\n','LOCATION=$(base64 -d \u003c\u003c\u003c''',base64(resourceGroup().location),''')\n','SUBSCRIPTIONID=$(base64 -d \u003c\u003c\u003c''',base64(subscription().subscriptionId),''')\n','RESOURCEGROUPNAME=$(base64 -d \u003c\u003c\u003c''',base64(resourceGroup().name),''')\n','\n',base64ToString('IyEvYmluL2Jhc2gKCnNldCAtbyBlcnJleGl0IFwKICAgIC1vIG5vdW5zZXQKCmlmIFsgIiR7REVCVUc6LWZhbHNlfSIgPT0gdHJ1ZSBdOyB0aGVuCiAgICBzZXQgLXgKZmkKCm1haW4oKSB7CiAgICBsb2NhbCAtciBnYXRld2F5X2xvZ2Rpcj0nL3Zhci9sb2cvYXJvLWdhdGV3YXknCiAgICBwYXJzZV9ydW5fb3B0aW9ucyAiJEAiIGdhdGV3YXlfbG9nZGlyCgoKICAgIGNvbmZpZ3VyZV9zc2hkCiAgICBjb25maWd1cmVfYW5kX2luc3RhbGxfZG5mX3BrZ3NfcmVwb3MKICAgIGNvbmZpZ3VyZV9kaXNrX3BhcnRpdGlvbnMKICAgIGNvbmZpZ3VyZV9sb2dyb3RhdGUgZ2F0ZXdheV9sb2dkaXIKICAgIGNvbmZpZ3VyZV9zZWxpbnV4CgogICAgbWtkaXIgLXAgL3Zhci9sb2cvam91cm5hbAogICAgbWtkaXIgLXAgL3Zhci9saWIvd2FhZ2VudC9NaWNyb3NvZnQuQXp1cmUuS2V5VmF1bHQuU3RvcmUKCiAgICBjb25maWd1cmVfZmlyZXdhbGxkX3J1bGVzCiAgICBwdWxsX2NvbnRhaW5lcl9pbWFnZXMKICAgIGNvbmZpZ3VyZV9zeXN0ZW1fc2VydmljZXMgZ2F0ZXdheV9sb2dkaXIKICAgIHJlYm9vdF92bQp9Cgp1c2FnZSgpIHsKICAgIGxvY2FsIC1uIG9wdGlvbnM9IiQxIgogICAgbG9nICIkKGJhc2VuYW1lICIkMCIpIFskb3B0aW9uc10KICAgICAgICAtZCBDb25maWd1cmUgRGlzayBQYXJ0aXRpb25zCiAgICAgICAgLXAgQ29uZmlndXJlIHJwbSByZXBvc2l0b3JpZXMsIGltcG9ydCByZXF1aXJlZCBycG0ga2V5cywgdXBkYXRlICYgaW5zdGFsbCBwYWNrYWdlcyB3aXRoIGRuZgogICAgICAgIC1sIENvbmZpZ3VyZSBsb2dyb3RhdGUuY29uZgogICAgICAgIC1zIE1ha2Ugc2VsaW51eCBtb2RpZmljYXRpb25zIHJlcXVpcmVkIGZvciBBUk8gUlAKICAgICAgICAtciBDb25maWd1cmUgc3NoZCAtIEFsbG93IHBhc3N3b3JkIGF1dGhlbnRpY2FpdG9uCiAgICAgICAgLWYgQ29uZmlndXJlIGZpcmV3YWxsZCBkZWZhdWx0IHpvbmUgcnVsZXMKICAgICAgICAtdSBDb25maWd1cmUgc3lzdGVtZCB1bml0IGZpbGVzIGZvciBBUk8gUlAKICAgICAgICAtaSBQdWxsIGNvbnRhaW5lciBpbWFnZXMKCiAgICAgICAgTm90ZTogc3RlcHMgd2lsbCBiZSBleGVjdXRlZCBpbiB0aGUgb3JkZXIgdGhhdCBmbGFncyBhcmUgcHJvdmlkZWQKICAgICIKfQoKIyBwYXJzZV9ydW5fb3B0aW9ucyB0YWtlcyBhbGwgYXJndWVtZW50cyBwYXNzZWQgdG8gbWFpbiBhbmQgcGFyc2VzIHRoZW0KIyBhbGxvd2luZyBpbmRpdmlkdWFsIHN0ZXAocykgdG8gYmUgcmFuLCByYXRoZXIgdGhhbiBhbGwgc3RlcHMKIwojIFRoaXMgaXMgdXNlZnVsIGZvciBsb2NhbCB0ZXN0aW5nLCBvciBwb3NzaWJseSBtb2RpZnlpbmcgdGhlIGJvb3RzdHJhcCBleGVjdXRpb24gdmlhIGVudmlyb25tZW50IHZhcmlhYmxlcyBpbiB0aGUgZGVwbG95bWVudCBwaXBlbGluZQpwYXJzZV9ydW5fb3B0aW9ucygpIHsKICAgICMgc2hlbGxjaGVjayBkaXNhYmxlPVNDMjIwNgogICAgbG9jYWwgLWEgb3B0aW9ucz0oJHsxOi19KQogICAgaWYgWyAiJHsjb3B0aW9uc1tAXX0iIC1lcSAwIF07IHRoZW4KICAgICAgICBsb2cgIlJ1bm5pbmcgYWxsIHN0ZXBzIgogICAgICAgIHJldHVybiAwCiAgICBmaQoKICAgIGxvY2FsIE9QVElORAogICAgbG9jYWwgLXIgYWxsb3dlZF9vcHRpb25zPSJkcGxzcmZ1aSIKICAgIHdoaWxlIGdldG9wdHMgJHthbGxvd2VkX29wdGlvbnN9IG9wdGlvbnM7IGRvCiAgICAgICAgY2FzZSAiJHtvcHRpb25zfSIgaW4KICAgICAgICAgICAgZCkKICAgICAgICAgICAgICAgIGxvZyAiUnVubmluZyBzdGVwIGNvbmZpZ3VyZV9kaXNrX3BhcnRpdGlvbnMiCiAgICAgICAgICAgICAgICBjb25maWd1cmVfZGlza19wYXJ0aXRpb25zCiAgICAgICAgICAgICAgICA7OwogICAgICAgICAgICBwKQogICAgICAgICAgICAgICAgbG9nICJSdW5uaW5nIHN0ZXAgY29uZmlndXJlX2FuZF9pbnN0YWxsX2RuZl9wa2dzX3JlcG9zIgogICAgICAgICAgICAgICAgY29uZmlndXJlX2FuZF9pbnN0YWxsX2RuZl9wa2dzX3JlcG9zCiAgICAgICAgICAgICAgICA7OwogICAgICAgICAgICBsKQogICAgICAgICAgICAgICAgbG9nICJSdW5uaW5nIGNvbmZpZ3VyZV9sb2dyb3RhdGUiCiAgICAgICAgICAgICAgICBjb25maWd1cmVfbG9ncm90YXRlICIkMiIKICAgICAgICAgICAgICAgIDs7CiAgICAgICAgICAgIHMpCiAgICAgICAgICAgICAgICBsb2cgIlJ1bm5pbmcgY29uZmlndXJlX3NlbGludXgiCiAgICAgICAgICAgICAgICBjb25maWd1cmVfc2VsaW51eAogICAgICAgICAgICAgICAgOzsKICAgICAgICAgICAgcikKICAgICAgICAgICAgICAgIGxvZyAiUnVubmluZyBjb25maWd1cmVfc3NoZCIKICAgICAgICAgICAgICAgIGNvbmZpZ3VyZV9zc2hkCiAgICAgICAgICAgICAgICA7OwogICAgICAgICAgICBmKQogICAgICAgICAgICAgICAgbG9nICJSdW5uaW5nIGNvbmZpZ3VyZV9maXJld2FsbGRfcnVsZXMiCiAgICAgICAgICAgICAgICBjb25maWd1cmVfZmlyZXdhbGxkX3J1bGVzCiAgICAgICAgICAgICAgICA7OwogICAgICAgICAgICB1KQogICAgICAgICAgICAgICAgbG9nICJSdW5uaW5nIHB1bGxfY29udGFpbmVyX2ltYWdlcyAmIGNvbmZpZ3VyZV9zeXN0ZW1fc2VydmljZXMiCiAgICAgICAgICAgICAgICBjb25maWd1cmVfc3lzdGVtX3NlcnZpY2VzICIkMiIKICAgICAgICAgICAgICAgIDs7CiAgICAgICAgICAgIGkpCiAgICAgICAgICAgICAgICBsb2cgIlJ1bm5pbmcgcHVsbF9jb250YWluZXJfaW1hZ2VzIgogICAgICAgICAgICAgICAgcHVsbF9jb250YWluZXJfaW1hZ2VzIAogICAgICAgICAgICAgICAgOzsKICAgICAgICAgICAgKikKICAgICAgICAgICAgICAgIHVzYWdlIGFsbG93ZWRfb3B0aW9ucwogICAgICAgICAgICAgICAgYWJvcnQgIlVua293biBvcHRpb24gcHJvdmlkZWQiCiAgICAgICAgICAgICAgICA7OwogICAgICAgIGVzYWMKICAgIGRvbmUKICAgIAogICAgZXhpdCAwCn0KCiMgV2UgbmVlZCB0byBjb25maWd1cmUgUGFzc3dvcmRBdXRoZW50aWNhdGlvbiB0byB5ZXMgaW4gb3JkZXIgZm9yIHRoZSBWTVNTIEFjY2VzcyBKSVQgdG8gd29yawpjb25maWd1cmVfc3NoZCgpIHsKICAgIGxvZyAic3RhcnRpbmciCiAgICBsb2cgInNldHRpbmcgc3NoIHBhc3N3b3JkIGF1dGhlbnRpY2F0aW9uIgogICAgc2VkIC1pICdzL1Bhc3N3b3JkQXV0aGVudGljYXRpb24gbm8vUGFzc3dvcmRBdXRoZW50aWNhdGlvbiB5ZXMvZycgL2V0Yy9zc2gvc3NoZF9jb25maWcKCiAgICBzeXN0ZW1jdGwgcmVsb2FkIHNzaGQuc2VydmljZQogICAgc3lzdGVtY3RsIGlzLWFjdGl2ZSAtLXF1aWV0IHNzaGQgfHwgYWJvcnQgInNzaGQgZmFpbGVkIHRvIHJlbG9hZCIKfQoKIyBjb25maWd1cmVfYW5kX2luc3RhbGxfZG5mX3BrZ3NfcmVwb3MKY29uZmlndXJlX2FuZF9pbnN0YWxsX2RuZl9wa2dzX3JlcG9zKCkgewogICAgbG9nICJzdGFydGluZyIKCiAgICAjIHRyYW5zYWN0aW9uIGF0dGVtcHQgcmV0cnkgdGltZSBpbiBzZWNvbmRzCiAgICBsb2NhbCAtcmkgcmV0cnlfd2FpdF90aW1lPTYwCiAgICBjb25maWd1cmVfcmh1aV9yZXBvIHJldHJ5X3dhaXRfdGltZQogICAgY3JlYXRlX2F6dXJlX3JwbV9yZXBvcyByZXRyeV93YWl0X3RpbWUKCiAgICBsb2NhbCAtYXIgZXhjbHVkZV9wa2dzPSgKICAgICAgICAiLXggV0FMaW51eEFnZW50IgogICAgICAgICIteCBXQUxpbnV4QWdlbnQtdWRldiIKICAgICkKCiAgICBkbmZfdXBkYXRlX3BrZ3MgZXhjbHVkZV9wa2dzIHJldHJ5X3dhaXRfdGltZQoKICAgIGxvY2FsIC1yYSBycG1fa2V5cz0oCiAgICAgICAgaHR0cHM6Ly9kbC5mZWRvcmFwcm9qZWN0Lm9yZy9wdWIvZXBlbC9SUE0tR1BHLUtFWS1FUEVMLTgKICAgICAgICBodHRwczovL3BhY2thZ2VzLm1pY3Jvc29mdC5jb20va2V5cy9taWNyb3NvZnQuYXNjCiAgICApCgogICAgcnBtX2ltcG9ydF9rZXlzIHJwbV9rZXlzIHJldHJ5X3dhaXRfdGltZQoKICAgIGxvY2FsIC1yYSByZXBvX3JwbV9wa2dzPSgKICAgICAgICBodHRwczovL2RsLmZlZG9yYXByb2plY3Qub3JnL3B1Yi9lcGVsL2VwZWwtcmVsZWFzZS1sYXRlc3QtOC5ub2FyY2gucnBtCiAgICApCgogICAgbG9jYWwgLXJhIGluc3RhbGxfcGtncz0oCiAgICAgICAgY2xhbWF2CiAgICAgICAgYXpzZWMtY2xhbWF2CiAgICAgICAgYXpzZWMtbW9uaXRvcgogICAgICAgIGF6dXJlLWNsaQogICAgICAgIGF6dXJlLW1kc2QKICAgICAgICBhenVyZS1zZWN1cml0eQogICAgICAgIHBvZG1hbgogICAgICAgIHBvZG1hbi1kb2NrZXIKICAgICAgICBvcGVuc3NsLXBlcmwKICAgICAgICAjIGhhY2sgLSB3ZSBhcmUgaW5zdGFsbGluZyBweXRob24zIG9uIGhvc3RzIGR1ZSB0byBhbiBpc3N1ZSB3aXRoIEF6dXJlIExpbnV4IEV4dGVuc2lvbnMgaHR0cHM6Ly9naXRodWIuY29tL0F6dXJlL2F6dXJlLWxpbnV4LWV4dGVuc2lvbnMvcHVsbC8xNTA1CiAgICAgICAgcHl0aG9uMwogICAgKQoKICAgIGRuZl9pbnN0YWxsX3BrZ3MgcmVwb19ycG1fcGtncyByZXRyeV93YWl0X3RpbWUKICAgIGRuZl9pbnN0YWxsX3BrZ3MgaW5zdGFsbF9wa2dzIHJldHJ5X3dhaXRfdGltZQp9CgojIGNvbmZpZ3VyZV9yaHVpX3JlcG8KY29uZmlndXJlX3JodWlfcmVwbygpIHsKICAgIGxvZyAic3RhcnRpbmciCgogICAgbG9jYWwgLXJhIGNtZD0oCiAgICAgICAgZG5mCiAgICAgICAgdXBkYXRlCiAgICAgICAgLXkKICAgICAgICAtLWRpc2FibGVyZXBvPScqJwogICAgICAgIC0tZW5hYmxlcmVwbz0ncmh1aS1taWNyb3NvZnQtYXp1cmUqJwogICAgKQoKICAgIGxvZyAicnVubmluZyBSSFVJIHBhY2thZ2UgdXBkYXRlcyIKICAgIHJldHJ5IGNtZCAiJDEiCn0KCiMgcmV0cnkgQWRkaW5nIHJldHJ5IGxvZ2ljIHRvIHl1bSBjb21tYW5kcyBpbiBvcmRlciB0byBhdm9pZCBzdGFsbGluZyBvdXQgb24gcmVzb3VyY2UgbG9ja3MKcmV0cnkoKSB7CiAgICBsb2NhbCAtbiBjbWRfcmV0cnk9IiQxIgogICAgbG9jYWwgLW4gd2FpdF90aW1lPSIkMiIKCiAgICBmb3IgYXR0ZW1wdCBpbiB7MS4uNX07IGRvCiAgICAgICAgbG9nICJhdHRlbXB0ICMke2F0dGVtcHR9IC0gJHtGVU5DTkFNRVsyXX0iCiAgICAgICAgJHtjbWRfcmV0cnlbQF19ICYKCiAgICAgICAgd2FpdCAkISAmJiBicmVhawogICAgICAgIGlmIFtbICR7YXR0ZW1wdH0gLWx0IDUgXV07IHRoZW4KICAgICAgICAgICAgc2xlZXAgIiR3YWl0X3RpbWUiCiAgICAgICAgZWxzZQogICAgICAgICAgICBhYm9ydCAiYXR0ZW1wdCAjJHthdHRlbXB0fSAtIEZhaWxlZCB0byB1cGRhdGUgcGFja2FnZXMiCiAgICAgICAgZmkKICAgIGRvbmUKfQoKIyBkbmZfdXBkYXRlX3BrZ3MKZG5mX3VwZGF0ZV9wa2dzKCkgewogICAgbG9jYWwgLW4gZXhjbHVkZXM9IiQxIgogICAgbG9nICJzdGFydGluZyIKCiAgICBsb2NhbCAtcmEgY21kPSgKICAgICAgICBkbmYKICAgICAgICAteQogICAgICAgICR7ZXhjbHVkZXNbQF19CiAgICAgICAgdXBkYXRlCiAgICAgICAgLS1hbGxvd2VyYXNpbmcKICAgICkKCiAgICBsb2cgIlVwZGF0aW5nIGFsbCBwYWNrYWdlcyIKICAgIHJldHJ5IGNtZCAiJDIiCn0KCiMgZG5mX2luc3RhbGxfcGtncwpkbmZfaW5zdGFsbF9wa2dzKCkgewogICAgbG9jYWwgLW4gcGtncz0iJDEiCiAgICBsb2cgInN0YXJ0aW5nIgoKICAgIGxvY2FsIC1yYSBjbWQ9KAogICAgICAgIGRuZgogICAgICAgIC15CiAgICAgICAgaW5zdGFsbAogICAgICAgICR7cGtnc1tAXX0KICAgICkKCiAgICBsb2cgIkF0dGVtcHRpbmcgdG8gaW5zdGFsbCBwYWNrYWdlczogJHtwa2dzWypdfSIKICAgIHJldHJ5IGNtZCAiJDIiCn0KCiMgcnBtX2ltcG9ydF9rZXlzCnJwbV9pbXBvcnRfa2V5cygpIHsKICAgIGxvY2FsIC1uIGtleXM9IiQxIgogICAgbG9nICJzdGFydGluZyIKCgogICAgIyBzaGVsbGNoZWNrIGRpc2FibGU9U0MyMDY4CiAgICBmb3Iga2V5IGluICR7a2V5c1tAXX07IGRvCiAgICAgICAgaWYgWyAkeyNrZXlzW0BdfSAtZXEgMCBdOyB0aGVuCiAgICAgICAgICAgIGJyZWFrCiAgICAgICAgZmkKICAgICAgICAgICAgbG9jYWwgLWEgY21kPSgKICAgICAgICAgICAgICAgIHJwbQogICAgICAgICAgICAgICAgLS1pbXBvcnQKICAgICAgICAgICAgICAgIC12CiAgICAgICAgICAgICAgICAiJGtleSIKICAgICAgICAgICAgKQoKICAgICAgICAgICAgbG9nICJhdHRlbXB0ICMkYXR0ZW1wdCAtIGltcG9ydGluZyBycG0gcmVwb3NpdG9yeSBrZXkgJGtleSIKICAgICAgICAgICAgcmV0cnkgY21kICIkMiIgJiYgdW5zZXQga2V5CiAgICBkb25lCn0KCiMgY29uZmlndXJlX2Rpc2tfcGFydGl0aW9ucwpjb25maWd1cmVfZGlza19wYXJ0aXRpb25zKCkgewogICAgbG9nICJzdGFydGluZyIKICAgIGxvZyAiZXh0ZW5kaW5nIHBhcnRpdGlvbiB0YWJsZSIKCiAgICAjIExpbnV4IGJsb2NrIGRldmljZXMgYXJlIGluY29uc2lzdGVudGx5IG5hbWVkCiAgICAjIGl0J3MgZGlmZmljdWx0IHRvIHRpZSB0aGUgbHZtIHB2IHRvIHRoZSBwaHlzaWNhbCBkaXNrIHVzaW5nIC9kZXYvZGlzayBmaWxlcywgd2hpY2ggaXMgd2h5IGx2cyBpcyB1c2VkIGhlcmUKICAgIHBoeXNpY2FsX2Rpc2s9IiQobHZzIC1vIGRldmljZXMgLWEgfCBoZWFkIC1uMiB8IHRhaWwgLW4xIHwgY3V0IC1kICcgJyAtZiAzIHwgY3V0IC1kIFwoIC1mIDEgfCB0ciAtZCAnWzpkaWdpdDpdJykiCiAgICBncm93cGFydCAiJHBoeXNpY2FsX2Rpc2siIDIKCiAgICBsb2cgImV4dGVuZGluZyBmaWxlc3lzdGVtcyIKICAgIGxvZyAiZXh0ZW5kaW5nIHJvb3QgbHZtIgogICAgbHZleHRlbmQgLWwgKzIwJUZSRUUgL2Rldi9yb290dmcvcm9vdGx2CiAgICBsb2cgImdyb3dpbmcgcm9vdCBmaWxlc3lzdGVtIgogICAgeGZzX2dyb3dmcyAvCgogICAgbG9nICJleHRlbmRpbmcgdmFyIGx2bSIKICAgIGx2ZXh0ZW5kIC1sICsxMDAlRlJFRSAvZGV2L3Jvb3R2Zy92YXJsdgogICAgbG9nICJncm93aW5nIHZhciBmaWxlc3lzdGVtIgogICAgeGZzX2dyb3dmcyAvdmFyCn0KCiMgY29uZmlndXJlX2xvZ3JvdGF0ZSBjbG9iYmVycyAvZXRjL2xvZ3JvdGF0ZS5jb25mCmNvbmZpZ3VyZV9sb2dyb3RhdGUoKSB7CiAgICBsb2NhbCAtbiBsb2dfZGlyPSIkMSIKICAgIGxvZyAic3RhcnRpbmciCgogICAgbG9jYWwgLXIgbG9ncm90YXRlX2NvbmZfZmlsZW5hbWU9Jy9ldGMvbG9ncm90YXRlLmNvbmYnCiAgICBsb2NhbCAtciBsb2dyb3RhdGVfY29uZl9maWxlPSIjIHNlZSAnbWFuIGxvZ3JvdGF0ZScgZm9yIGRldGFpbHMKIyByb3RhdGUgbG9nIGZpbGVzIHdlZWtseQp3ZWVrbHkKCiMga2VlcCAyIHdlZWtzIHdvcnRoIG9mIGJhY2tsb2dzCnJvdGF0ZSAyCgojIGNyZWF0ZSBuZXcgKGVtcHR5KSBsb2cgZmlsZXMgYWZ0ZXIgcm90YXRpbmcgb2xkIG9uZXMKY3JlYXRlCgojIHVzZSBkYXRlIGFzIGEgc3VmZml4IG9mIHRoZSByb3RhdGVkIGZpbGUKZGF0ZWV4dAoKIyB1bmNvbW1lbnQgdGhpcyBpZiB5b3Ugd2FudCB5b3VyIGxvZyBmaWxlcyBjb21wcmVzc2VkCmNvbXByZXNzCgojIFJQTSBwYWNrYWdlcyBkcm9wIGxvZyByb3RhdGlvbiBpbmZvcm1hdGlvbiBpbnRvIHRoaXMgZGlyZWN0b3J5CmluY2x1ZGUgL2V0Yy9sb2dyb3RhdGUuZAoKIyBubyBwYWNrYWdlcyBvd24gd3RtcCBhbmQgYnRtcCAtLSB3ZSB3aWxsIHJvdGF0ZSB0aGVtIGhlcmUKL3Zhci9sb2cvd3RtcCB7CiAgICBtb250aGx5CiAgICBjcmVhdGUgMDY2NCByb290IHV0bXAKICAgICAgICBtaW5zaXplIDFNCiAgICByb3RhdGUgMQp9CgovdmFyL2xvZy9idG1wIHsKICAgIG1pc3NpbmdvawogICAgbW9udGhseQogICAgY3JlYXRlIDA2MDAgcm9vdCB1dG1wCiAgICByb3RhdGUgMQp9CgojIE1heGltdW0gbG9nIGRpcmVjdG9yeSBzaXplIGlzIDEwMEcgd2l0aCB0aGlzIGNvbmZpZ3VyYXRpb24KIyBTZXR0aW5nIGxpbWl0IHRvIDEwMEcgdG8gYWxsb3cgc3BhY2UgZm9yIG90aGVyIGxvZ2dpbmcgc2VydmljZXMKIyBjb3B5dHJ1bmNhdGUgaXMgYSBjcml0aWNhbCBvcHRpb24gdXNlZCB0byBwcmV2ZW50IGxvZ3MgZnJvbSBiZWluZyBzaGlwcGVkIHR3aWNlCiR7bG9nX2Rpcn0gewogICAgc2l6ZSAyMEcKICAgIHJvdGF0ZSA1CiAgICBjcmVhdGUgMDYwMCByb290IHJvb3QKICAgIGNvcHl0cnVuY2F0ZQogICAgbm9vbGRkaXIKICAgIGNvbXByZXNzCn0iCgogICAgd3JpdGVfZmlsZSBsb2dyb3RhdGVfY29uZl9maWxlbmFtZSBsb2dyb3RhdGVfY29uZl9maWxlIHRydWUKfQoKIyBjcmVhdGVfYXp1cmVfcnBtX3JlcG9zIGNyZWF0ZXMgL2V0Yy95dW0ucmVwb3MuZC9henVyZS5yZXBvIHJlcG9zaXRvcnkgZmlsZQpjcmVhdGVfYXp1cmVfcnBtX3JlcG9zKCkgewogICAgbG9nICJzdGFydGluZyIKCiAgICBsb2NhbCAtciBhenVyZV9yZXBvX2ZpbGVuYW1lPScvZXRjL3l1bS5yZXBvcy5kL2F6dXJlLnJlcG8nCiAgICBsb2NhbCAtciBhenVyZV9yZXBvX2ZpbGU9J1thenVyZS1jbGldCm5hbWU9YXp1cmUtY2xpCmJhc2V1cmw9aHR0cHM6Ly9wYWNrYWdlcy5taWNyb3NvZnQuY29tL3l1bXJlcG9zL2F6dXJlLWNsaQplbmFibGVkPXllcwpncGdjaGVjaz15ZXMKClthenVyZWNvcmVdCm5hbWU9YXp1cmVjb3JlCmJhc2V1cmw9aHR0cHM6Ly9wYWNrYWdlcy5taWNyb3NvZnQuY29tL3l1bXJlcG9zL2F6dXJlY29yZQplbmFibGVkPXllcwpncGdjaGVjaz1ubycKCiAgICB3cml0ZV9maWxlIGF6dXJlX3JlcG9fZmlsZW5hbWUgYXp1cmVfcmVwb19maWxlIHRydWUKfQoKIyBjb25maWd1cmVfc2VsaW51eApjb25maWd1cmVfc2VsaW51eCgpIHsKICAgIGxvZyAic3RhcnRpbmciCgogICAgbG9jYWwgLXIgcmVsYWJlbD0iJHsxOi1mYWxzZX0iCgogICAgYWxyZWFkeV9kZWZpbmVkX2lnbm9yZV9lcnJvcj0iRmlsZSBjb250ZXh0IGZvciAvdmFyL2xvZy9qb3VybmFsKC8uKik/IGFscmVhZHkgZGVmaW5lZCIKICAgIHNlbWFuYWdlIGZjb250ZXh0IC1hIC10IHZhcl9sb2dfdCAiL3Zhci9sb2cvam91cm5hbCgvLiopPyIgfHwgbG9nICIkYWxyZWFkeV9kZWZpbmVkX2lnbm9yZV9lcnJvciIKICAgIGNoY29uIC1SIHN5c3RlbV91Om9iamVjdF9yOnZhcl9sb2dfdDpzMCAvdmFyL29wdC9taWNyb3NvZnQvbGludXhtb25hZ2VudAoKICAgIGlmICIkcmVsYWJlbCI7IHRoZW4KICAgICAgICByZXN0b3JlY29uIC1SRiAvdmFyL2xvZy8qIHx8IGxvZyAiJGFscmVhZHlfZGVmaW5lZF9pZ25vcmVfZXJyb3IiCiAgICBmaQp9CgojIGNvbmZpZ3VyZV9maXJld2FsbGRfcnVsZXMKY29uZmlndXJlX2ZpcmV3YWxsZF9ydWxlcygpIHsKICAgIGxvZyAic3RhcnRpbmciCgogICAgIyBodHRwczovL2FjY2Vzcy5yZWRoYXQuY29tL3NlY3VyaXR5L2N2ZS9jdmUtMjAyMC0xMzQwMQogICAgbG9jYWwgLXIgcHJlZml4PSIvZXRjL3N5c2N0bC5kIgogICAgbG9jYWwgLXIgZGlzYWJsZV9hY2NlcHRfcmFfY29uZl9maWxlbmFtZT0iJHByZWZpeC8wMi1kaXNhYmxlLWFjY2VwdC1yYS5jb25mIgogICAgbG9jYWwgLXIgZGlzYWJsZV9hY2NlcHRfcmFfY29uZl9maWxlPSJuZXQuaXB2Ni5jb25mLmFsbC5hY2NlcHRfcmE9MCIKCiAgICB3cml0ZV9maWxlIGRpc2FibGVfYWNjZXB0X3JhX2NvbmZfZmlsZW5hbWUgZGlzYWJsZV9hY2NlcHRfcmFfY29uZl9maWxlIHRydWUKCiAgICBsb2NhbCAtciBkaXNhYmxlX2NvcmVfZmlsZW5hbWU9IiRwcmVmaXgvMDEtZGlzYWJsZS1jb3JlLmNvbmYiCiAgICBsb2NhbCAtciBkaXNhYmxlX2NvcmVfZmlsZT0ia2VybmVsLmNvcmVfcGF0dGVybiA9IHwvYmluL3RydWUKICAgICIKICAgIHdyaXRlX2ZpbGUgZGlzYWJsZV9jb3JlX2ZpbGVuYW1lIGRpc2FibGVfY29yZV9maWxlIHRydWUKCiAgICBzeXNjdGwgLS1zeXN0ZW0KCiAgICBsb2NhbCAtcmEgZW5hYmxlX3BvcnRzPSgKICAgICAgICAiODAvdGNwIgogICAgICAgICI4MDgxL3RjcCIKICAgICAgICAiNDQzL3RjcCIKICAgICkKCiAgICBsb2cgIkVuYWJsaW5nIHBvcnRzICR7ZW5hYmxlX3BvcnRzWypdfSBvbiBkZWZhdWx0IGZpcmV3YWxsZCB6b25lIgogICAgIyBzaGVsbGNoZWNrIGRpc2FibGU9U0MyMDY4CiAgICBmb3IgcG9ydCBpbiAke2VuYWJsZV9wb3J0c1tAXX07IGRvCiAgICAgICAgbG9nICJFbmFibGluZyBwb3J0ICRwb3J0IG5vdyIKICAgICAgICBmaXJld2FsbC1jbWQgIi0tYWRkLXBvcnQ9JHBvcnQiCiAgICBkb25lCgogICAgZmlyZXdhbGwtY21kIC0tcnVudGltZS10by1wZXJtYW5lbnQKfQoKIyBwdWxsX2NvbnRhaW5lcl9pbWFnZXMKcHVsbF9jb250YWluZXJfaW1hZ2VzKCkgewogICAgbG9nICJzdGFydGluZyIKCiAgICAjIFRoZSBtYW5hZ2VkIGlkZW50aXR5IHRoYXQgdGhlIFZNIHJ1bnMgYXMgb25seSBoYXMgYSBzaW5nbGUgcm9sZWFzc2lnbm1lbnQuCiAgICAjIFRoaXMgcm9sZSBhc3NpZ25tZW50IGlzIEFDUlB1bGwgd2hpY2ggaXMgbm90IG5lY2Vzc2FyaWx5IHByZXNlbnQgaW4gdGhlCiAgICAjIHN1YnNjcmlwdGlvbiB3ZSdyZSBkZXBsb3lpbmcgaW50by4gIElmIHRoZSBpZGVudGl0eSBkb2VzIG5vdCBoYXZlIGFueQogICAgIyByb2xlIGFzc2lnbm1lbnRzIHNjb3BlZCBvbiB0aGUgc3Vic2NyaXB0aW9uIHdlJ3JlIGRlcGxveWluZyBpbnRvLCBpdCB3aWxsCiAgICAjIG5vdCBzaG93IG9uIGF6IGxvZ2luIC1pLCB3aGljaCBpcyB3aHkgdGhlIGJlbG93IGxpbmUgaXMgY29tbWVudGVkLgogICAgIyBheiBhY2NvdW50IHNldCAtcyAiJFNVQlNDUklQVElPTklEIgogICAgYXogbG9naW4gLWkgLS1hbGxvdy1uby1zdWJzY3JpcHRpb25zCgogICAgIyBTdXBwcmVzcyBlbXVsYXRpb24gb3V0cHV0IGZvciBwb2RtYW4gaW5zdGVhZCBvZiBkb2NrZXIgZm9yIGF6IGFjciBjb21wYXRhYmlsaXR5CiAgICBta2RpciAtcCAvZXRjL2NvbnRhaW5lcnMvCiAgICBta2RpciAtcCAvcm9vdC8uZG9ja2VyCiAgICB0b3VjaCAvZXRjL2NvbnRhaW5lcnMvbm9kb2NrZXIKCgkjIFRoaXMgbmFtZSBpcyB1c2VkIGluIHRoZSBjYXNlIHRoYXQgYXogYWNyIGxvZ2luIHNlYXJjaGVzIGZvciB0aGlzIGluIGl0J3MgZW52aXJvbm1lbnQKICAgIGxvY2FsIC1yIFJFR0lTVFJZX0FVVEhfRklMRT0iL3Jvb3QvLmRvY2tlci9jb25maWcuanNvbiIKICAgIAogICAgbG9nICJsb2dnaW5nIGludG8gcHJvZCBhY3IiCiAgICBheiBhY3IgbG9naW4gLS1uYW1lICIkKHNlZCAtZSAnc3wuKi98fCcgPDw8IiRBQ1JSRVNPVVJDRUlEIikiCgogICAgTURNSU1BR0U9IiR7UlBJTUFHRSUlLyp9LyR7TURNSU1BR0UjIyovfSIKICAgIGRvY2tlciBwdWxsICIkTURNSU1BR0UiCiAgICBkb2NrZXIgcHVsbCAiJFJQSU1BR0UiCiAgICBkb2NrZXIgcHVsbCAiJEZMVUVOVEJJVElNQUdFIgoKICAgIGF6IGxvZ291dAp9CgojIGNvbmZpZ3VyZV9zeXN0ZW1fc2VydmljZXMgY3JlYXRlcywgY29uZmlndXJlcywgYW5kIGVuYWJsZXMgdGhlIGZvbGxvd2luZyBzeXN0ZW1kIHNlcnZpY2VzIGFuZCB0aW1lcnMKIyBzZXJ2aWNlcwojICAgZmx1ZW50Yml0CiMgICBtZG0KIyAgIG1kc2QKIyAgIGFycC1ycAojICAgYXJvLWRidG9rZW4KIyAgIGFyby1tb25pdG9yCiMgICBhcm8tcG9ydGFsCmNvbmZpZ3VyZV9zeXN0ZW1fc2VydmljZXMoKSB7CiAgICBjb25maWd1cmVfc2VydmljZV9mbHVlbnRiaXQKICAgIGNvbmZpZ3VyZV9zZXJ2aWNlX21kbQogICAgY29uZmlndXJlX3RpbWVyc19tZG1fbWRzZAogICAgY29uZmlndXJlX3NlcnZpY2VfYXJvX2dhdGV3YXkgIiQxIgogICAgY29uZmlndXJlX3NlcnZpY2VfbWRzZAp9CgojIGVuYWJsZV9hcm9fc2VydmljZXMgZW5hYmxlcyBhbGwgc2VydmljZXMgcmVxdWlyZWQgZm9yIGFybyBycAplbmFibGVfYXJvX3NlcnZpY2VzKCkgewogICAgbG9nICJzdGFydGluZyIKCiAgICBsb2NhbCAtcmEgYXJvX3NlcnZpY2VzPSgKICAgICAgYXJvLWdhdGV3YXkKICAgICAgYXVvbXMKICAgICAgYXpzZWNkCiAgICAgIGF6c2VjbW9uZAogICAgICBtZHNkCiAgICAgIG1kbQogICAgICBjaHJvbnlkCiAgICAgIGZsdWVudGJpdAogICAgKQogICAgbG9nICJlbmFibGluZyBnYXRld2F5IHNlcnZpY2VzICR7YXJvX3NlcnZpY2VzWypdfSIKICAgICMgc2hlbGxjaGVjayBkaXNhYmxlPVNDMjA2OAogICAgZm9yIHNlcnZpY2UgaW4gJHthcm9fc2VydmljZXNbQF19OyBkbwogICAgICAgIGxvZyAiRW5hYmxpbmcgJHNlcnZpY2Ugbm93IgogICAgICAgIHN5c3RlbWN0bCBlbmFibGUgIiRzZXJ2aWNlLnNlcnZpY2UiCiAgICBkb25lCn0KCiMgY29uZmlndXJlX3NlcnZpY2VfZmx1ZW50Yml0CmNvbmZpZ3VyZV9zZXJ2aWNlX2ZsdWVudGJpdCgpIHsKICAgIGxvZyAic3RhcnRpbmciCiAgICBsb2cgImNvbmZpZ3VyaW5nIGZsdWVudGJpdCBzZXJ2aWNlIgoKICAgIG1rZGlyIC1wIC9ldGMvZmx1ZW50Yml0LwogICAgbWtkaXIgLXAgL3Zhci9saWIvZmx1ZW50CgogICAgbG9jYWwgLXIgZmx1ZW50Yml0X2NvbmZfZmlsZW5hbWU9Jy9ldGMvZmx1ZW50Yml0L2ZsdWVudGJpdC5jb25mJwogICAgbG9jYWwgLXIgZmx1ZW50Yml0X2NvbmZfZmlsZT0iW0lOUFVUXQpOYW1lIHN5c3RlbWQKVGFnIGpvdXJuYWxkClN5c3RlbWRfRmlsdGVyIF9DT01NPWFybwpEQiAvdmFyL2xpYi9mbHVlbnQvam91cm5hbGRiCgpbRklMVEVSXQoJTmFtZSBtb2RpZnkKCU1hdGNoIGpvdXJuYWxkCglSZW1vdmVfd2lsZGNhcmQgXwoJUmVtb3ZlIFRJTUVTVEFNUAoKW09VVFBVVF0KCU5hbWUgZm9yd2FyZAoJTWF0Y2ggKgoJUG9ydCAyOTIzMCIKCiAgICB3cml0ZV9maWxlIGZsdWVudGJpdF9jb25mX2ZpbGVuYW1lIGZsdWVudGJpdF9jb25mX2ZpbGUgdHJ1ZQoKICAgIGxvY2FsIC1yIHN5c2NvbmZpZ19mbHVlbnRiaXRfZmlsZW5hbWU9Jy9ldGMvc3lzY29uZmlnL2ZsdWVudGJpdCcKICAgIGxvY2FsIC1yIHN5c2NvbmZpZ19mbHVlbnRiaXRfZmlsZT0iRkxVRU5UQklUSU1BR0U9JEZMVUVOVEJJVElNQUdFIgoKICAgIHdyaXRlX2ZpbGUgc3lzY29uZmlnX2ZsdWVudGJpdF9maWxlbmFtZSBzeXNjb25maWdfZmx1ZW50Yml0X2ZpbGUgdHJ1ZQoKICAgIGxvY2FsIC1yIGZsdWVudGJpdF9zZXJ2aWNlX2ZpbGVuYW1lPScvZXRjL3N5c3RlbWQvc3lzdGVtL2ZsdWVudGJpdC5zZXJ2aWNlJwoKICAgIGxvY2FsIC1yIGZsdWVudGJpdF9zZXJ2aWNlX2ZpbGU9IltVbml0XQpBZnRlcj1uZXR3b3JrLW9ubGluZS50YXJnZXQKV2FudHM9bmV0d29yay1vbmxpbmUudGFyZ2V0ClN0YXJ0TGltaXRJbnRlcnZhbFNlYz0wCgpbU2VydmljZV0KUmVzdGFydFNlYz0xcwpFbnZpcm9ubWVudEZpbGU9L2V0Yy9zeXNjb25maWcvZmx1ZW50Yml0CkV4ZWNTdGFydFByZT0tL3Vzci9iaW4vZG9ja2VyIHJtIC1mICVOCkV4ZWNTdGFydD0vdXNyL2Jpbi9kb2NrZXIgcnVuIFwKICAtLXNlY3VyaXR5LW9wdCBsYWJlbD1kaXNhYmxlIFwKICAtLWVudHJ5cG9pbnQgL29wdC90ZC1hZ2VudC1iaXQvYmluL3RkLWFnZW50LWJpdCBcCiAgLS1uZXQ9aG9zdCBcCiAgLS1ob3N0bmFtZSAlSCBcCiAgLS1uYW1lICVOIFwKICAtLXJtIFwKICAtLWNhcC1kcm9wIG5ldF9yYXcgXAogIC12IC9ldGMvZmx1ZW50Yml0L2ZsdWVudGJpdC5jb25mOi9ldGMvZmx1ZW50Yml0L2ZsdWVudGJpdC5jb25mIFwKICAtdiAvdmFyL2xpYi9mbHVlbnQ6L3Zhci9saWIvZmx1ZW50OnogXAogIC12IC92YXIvbG9nL2pvdXJuYWw6L3Zhci9sb2cvam91cm5hbDpybyBcCiAgLXYgL2V0Yy9tYWNoaW5lLWlkOi9ldGMvbWFjaGluZS1pZDpybyBcCiAgJEZMVUVOVEJJVElNQUdFIFwKICAtYyAvZXRjL2ZsdWVudGJpdC9mbHVlbnRiaXQuY29uZgoKRXhlY1N0b3A9L3Vzci9iaW4vZG9ja2VyIHN0b3AgJU4KUmVzdGFydD1hbHdheXMKUmVzdGFydFNlYz01ClN0YXJ0TGltaXRJbnRlcnZhbD0wCgpbSW5zdGFsbF0KV2FudGVkQnk9bXVsdGktdXNlci50YXJnZXQiCgogICAgd3JpdGVfZmlsZSBmbHVlbnRiaXRfY29uZl9maWxlbmFtZSBmbHVlbnRiaXRfY29uZl9maWxlIHRydWUKfQoKIyBjb25maWd1cmVfY2VydHMKY29uZmlndXJlX2NlcnRzKCkgewogICAgbG9nICJzdGFydGluZyIKCiAgICBta2RpciAvZXRjL2Fyby1ycAogICAgYmFzZTY0IC1kIDw8PCIkQURNSU5BUElDQUJVTkRMRSIgPi9ldGMvYXJvLXJwL2FkbWluLWNhLWJ1bmRsZS5wZW0KICAgIGlmIFtbIC1uICIkQVJNQVBJQ0FCVU5ETEUiIF1dOyB0aGVuCiAgICBiYXNlNjQgLWQgPDw8IiRBUk1BUElDQUJVTkRMRSIgPi9ldGMvYXJvLXJwL2FybS1jYS1idW5kbGUucGVtCiAgICBmaQogICAgY2hvd24gLVIgMTAwMDoxMDAwIC9ldGMvYXJvLXJwCgogICAgIyBzZXR0aW5nIE1PTklUT1JJTkdfR0NTX0FVVEhfSURfVFlQRT1BdXRoS2V5VmF1bHQgc2VlbXMgdG8gaGF2ZSBjYXVzZWQgbWRzZCBub3QKICAgICMgdG8gaG9ub3VyIFNTTF9DRVJUX0ZJTEUgYW55IG1vcmUsIGhlYXZlbiBvbmx5IGtub3dzIHdoeS4KICAgIG1rZGlyIC1wIC91c3IvbGliL3NzbC9jZXJ0cwogICAgY3NwbGl0IC1mIC91c3IvbGliL3NzbC9jZXJ0cy9jZXJ0LSAtYiAlMDNkLnBlbSAvZXRjL3BraS90bHMvY2VydHMvY2EtYnVuZGxlLmNydCAvXiQvMSAieyp9IiA+L2Rldi9udWxsCiAgICBjX3JlaGFzaCAvdXNyL2xpYi9zc2wvY2VydHMKCiMgd2UgbGVhdmUgY2xpZW50SWQgYmxhbmsgYXMgbG9uZyBhcyBvbmx5IDEgbWFuYWdlZCBpZGVudGl0eSBhc3NpZ25lZCB0byB2bXNzCiMgaWYgd2UgaGF2ZSBtb3JlIHRoYW4gMSwgd2Ugd2lsbCBuZWVkIHRvIHBvcHVsYXRlIHdpdGggY2xpZW50SWQgdXNlZCBmb3Igb2ZmLW5vZGUgc2Nhbm5pbmcKICAgIGxvY2FsIC1yIG5vZGVzY2FuX2FnZW50X2ZpbGVuYW1lPSIvZXRjL2RlZmF1bHQvdnNhLW5vZGVzY2FuLWFnZW50LmNvbmZpZyIKICAgIGxvY2FsIC1yIG5vZGVzY2FuX2FnZW50X2ZpbGU9InsKICAgIFwiTmljZVwiOiAxOSwKICAgIFwiVGltZW91dFwiOiAxMDgwMCwKICAgIFwiQ2xpZW50SWRcIjogXCJcIiwKICAgIFwiVGVuYW50SWRcIjogJEFaVVJFU0VDUEFDS1ZTQVRFTkFOVElELAogICAgXCJRdWFseXNTdG9yZUJhc2VVcmxcIjogJEFaVVJFU0VDUEFDS1FVQUxZU1VSTCwKICAgIFwiUHJvY2Vzc1RpbWVvdXRcIjogMzAwLAogICAgXCJDb21tYW5kRGVsYXlcIjogMAogIH0iCgogICAgd3JpdGVfZmlsZSBub2Rlc2Nhbl9hZ2VudF9maWxlbmFtZSBub2Rlc2Nhbl9hZ2VudF9maWxlIHRydWUKfQoKIyBjb25maWd1cmVfc2VydmljZV9tZG0KY29uZmlndXJlX3NlcnZpY2VfbWRtKCkgewogICAgbG9nICJzdGFydGluZyIKICAgIGxvZyAiY29uZmlndXJpbmcgbWRtIHNlcnZpY2UiCgogICAgbG9jYWwgLXIgc3lzY29uZmlnX21kbV9maWxlbmFtZT0iL2V0Yy9zeXNjb25maWcvbWRtIgogICAgbG9jYWwgLXIgc3lzY29uZmlnX21kbV9maWxlPSJNRE1GUk9OVEVORFVSTD0nJE1ETUZST05URU5EVVJMJwpNRE1JTUFHRT0nJE1ETUlNQUdFJwpNRE1TT1VSQ0VFTlZJUk9OTUVOVD0nJExPQ0FUSU9OJwpNRE1TT1VSQ0VST0xFPWdhdGV3YXkKTURNU09VUkNFUk9MRUlOU1RBTkNFPVwiJChob3N0bmFtZSlcIiIKCiAgICB3cml0ZV9maWxlIHN5c2NvbmZpZ19tZG1fZmlsZW5hbWUgc3lzY29uZmlnX21kbV9maWxlIHRydWUKCiAgICBta2RpciAtcCAvdmFyL2V0dwogICAgbG9jYWwgLXIgbWRtX3NlcnZpY2VfZmlsZW5hbWU9Ii9ldGMvc3lzdGVtZC9zeXN0ZW0vbWRtLnNlcnZpY2UiCiAgICBsb2NhbCAtciBtZG1fc2VydmljZV9maWxlPSJbVW5pdF0KQWZ0ZXI9bmV0d29yay1vbmxpbmUudGFyZ2V0CldhbnRzPW5ldHdvcmstb25saW5lLnRhcmdldAoKW1NlcnZpY2VdCkVudmlyb25tZW50RmlsZT0vZXRjL3N5c2NvbmZpZy9tZG0KRXhlY1N0YXJ0UHJlPS0vdXNyL2Jpbi9kb2NrZXIgcm0gLWYgJU4KRXhlY1N0YXJ0PS91c3IvYmluL2RvY2tlciBydW4gXAogIC0tZW50cnlwb2ludCAvdXNyL3NiaW4vTWV0cmljc0V4dGVuc2lvbiBcCiAgLS1ob3N0bmFtZSAlSCBcCiAgLS1uYW1lICVOIFwKICAtLXJtIFwKICAtLWNhcC1kcm9wIG5ldF9yYXcgXAogIC1tIDJnIFwKICAtdiAvZXRjL21kbS5wZW06L2V0Yy9tZG0ucGVtIFwKICAtdiAvdmFyL2V0dzovdmFyL2V0dzp6IFwKICAkTURNSU1BR0UgXAogIC1DZXJ0RmlsZSAvZXRjL21kbS5wZW0gXAogIC1Gcm9udEVuZFVybCAkTURNRlJPTlRFTkRVUkwgXAogIC1Mb2dnZXIgQ29uc29sZSBcCiAgLUxvZ0xldmVsIFdhcm5pbmcgXAogIC1Qcml2YXRlS2V5RmlsZSAvZXRjL21kbS5wZW0gXAogIC1Tb3VyY2VFbnZpcm9ubWVudCAkTURNU09VUkNFRU5WSVJPTk1FTlQgXAogIC1Tb3VyY2VSb2xlICRNRE1TT1VSQ0VST0xFIFwKICAtU291cmNlUm9sZUluc3RhbmNlICRNRE1TT1VSQ0VST0xFSU5TVEFOQ0UKRXhlY1N0b3A9L3Vzci9iaW4vZG9ja2VyIHN0b3AgJU4KUmVzdGFydD1hbHdheXMKUmVzdGFydFNlYz0xClN0YXJ0TGltaXRJbnRlcnZhbD0wCgpbSW5zdGFsbF0KV2FudGVkQnk9bXVsdGktdXNlci50YXJnZXQiCgogICAgd3JpdGVfZmlsZSBtZG1fc2VydmljZV9maWxlbmFtZSBtZG1fc2VydmljZV9maWxlIHRydWUKfQoKIyBjb25maWd1cmVfdGltZXJzX21kbV9tZHNkCmNvbmZpZ3VyZV90aW1lcnNfbWRtX21kc2QoKSB7CiAgICBsb2cgInN0YXJ0aW5nIgoKICAgIGZvciB2YXIgaW4gIm1kc2QiICJtZG0iOyBkbwogICAgICAgIGxvY2FsIGRvd25sb2FkX2NyZWRzX3NlcnZpY2VfZmlsZW5hbWU9Ii9ldGMvc3lzdGVtZC9zeXN0ZW0vZG93bmxvYWQtJHZhci1jcmVkZW50aWFscy5zZXJ2aWNlIgogICAgICAgIGxvY2FsIGRvd25sb2FkX2NyZWRzX3NlcnZpY2VfZmlsZT0iW1VuaXRdCkRlc2NyaXB0aW9uPVBlcmlvZGljICR2YXIgY3JlZGVudGlhbHMgcmVmcmVzaAoKW1NlcnZpY2VdClR5cGU9b25lc2hvdApFeGVjU3RhcnQ9L3Vzci9sb2NhbC9iaW4vZG93bmxvYWQtY3JlZGVudGlhbHMuc2ggJHZhciIKCiAgICAgICAgd3JpdGVfZmlsZSBkb3dubG9hZF9jcmVkc19zZXJ2aWNlX2ZpbGVuYW1lIGRvd25sb2FkX2NyZWRzX3NlcnZpY2VfZmlsZSB0cnVlCgogICAgICAgIGxvY2FsIGRvd25sb2FkX2NyZWRzX3RpbWVyX2ZpbGVuYW1lPSIvZXRjL3N5c3RlbWQvc3lzdGVtL2Rvd25sb2FkLSR2YXItY3JlZGVudGlhbHMudGltZXIiCiAgICAgICAgbG9jYWwgZG93bmxvYWRfY3JlZHNfdGltZXJfZmlsZT0iW1VuaXRdCkRlc2NyaXB0aW9uPVBlcmlvZGljICR2YXIgY3JlZGVudGlhbHMgcmVmcmVzaApBZnRlcj1uZXR3b3JrLW9ubGluZS50YXJnZXQKV2FudHM9bmV0d29yay1vbmxpbmUudGFyZ2V0CgpbVGltZXJdCk9uQm9vdFNlYz0wbWluCk9uQ2FsZW5kYXI9MC8xMjowMDowMApBY2N1cmFjeVNlYz01cwoKW0luc3RhbGxdCldhbnRlZEJ5PXRpbWVycy50YXJnZXQiCgogICAgICAgIHdyaXRlX2ZpbGUgZG93bmxvYWRfY3JlZHNfdGltZXJfZmlsZW5hbWUgZG93bmxvYWRfY3JlZHNfdGltZXJfZmlsZSB0cnVlCiAgICBkb25lCgogICAgbG9jYWwgLXIgZG93bmxvYWRfY3JlZHNfc2NyaXB0X2ZpbGVuYW1lPSIvdXNyL2xvY2FsL2Jpbi9kb3dubG9hZC1jcmVkZW50aWFscy5zaCIKICAgIGxvY2FsIC1yIGRvd25sb2FkX2NyZWRzX3NjcmlwdF9maWxlPSIjIS9iaW4vYmFzaApzZXQgLWV1CgpDT01QT05FTlQ9XCQxCmVjaG8gXCJEb3dubG9hZCBcJENPTVBPTkVOVCBjcmVkZW50aWFsc1wiCgpURU1QX0RJUj1cIlwkKG1rdGVtcCAtZClcIgpleHBvcnQgQVpVUkVfQ09ORklHX0RJUj1cIlwkKG1rdGVtcCAtZClcIgoKZWNobyBcIkxvZ2dpbmcgaW50byBBenVyZS4uLlwiClJFVFJJRVM9Mwp3aGlsZSBbWyBcJFJFVFJJRVMgLWd0IDAgXV07IGRvCiAgICBpZiBheiBsb2dpbiAtaSAtLWFsbG93LW5vLXN1YnNjcmlwdGlvbnMKICAgIHRoZW4KICAgICAgICBlY2hvIFwiYXogbG9naW4gc3VjY2Vzc2Z1bFwiCiAgICAgICAgYnJlYWsKICAgIGVsc2UKICAgICAgICBlY2hvIFwiYXogbG9naW4gZmFpbGVkLiBSZXRyeWluZy4uLlwiCiAgICAgICAgbGV0IFJFVFJJRVMtPTEKICAgICAgICBzbGVlcCA1CiAgICBmaQpkb25lCgp0cmFwIFwiY2xlYW51cFwiIEVYSVQKCmNsZWFudXAoKSB7CiAgYXogbG9nb3V0CiAgW1sgXCRURU1QX0RJUiA9fiAvdG1wLy4rIF1dICYmIHJtIC1yZiBcJFRFTVBfRElSCiAgW1sgXCRBWlVSRV9DT05GSUdfRElSID1+IC90bXAvLisgXV0gJiYgcm0gLXJmIFwkQVpVUkVfQ09ORklHX0RJUgp9CgppZiBbWyBcJENPTVBPTkVOVCA9IFwibWRtXCIgXV07IHRoZW4KICBDVVJSRU5UX0NFUlRfRklMRT1cIi9ldGMvbWRtLnBlbVwiCmVsaWYgW1sgXCRDT01QT05FTlRcID0gXCJtZHNkXCIgXV07IHRoZW4KICBDVVJSRU5UX0NFUlRfRklMRT1cIi92YXIvbGliL3dhYWdlbnQvTWljcm9zb2Z0LkF6dXJlLktleVZhdWx0LlN0b3JlL21kc2QucGVtXCIKZWxzZQogIGVjaG8gSW52YWxpZCB1c2FnZSAmJiBleGl0IDEKZmkKClNFQ1JFVF9OQU1FPVwiZ3d5LVwke0NPTVBPTkVOVH1cIgpORVdfQ0VSVF9GSUxFPVwiXCRURU1QX0RJUi9cJENPTVBPTkVOVC5wZW1cIgpmb3IgYXR0ZW1wdCBpbiB7MS4uNX07IGRvCiAgYXoga2V5dmF1bHQgXAogICAgc2VjcmV0IFwKICAgIGRvd25sb2FkIFwKICAgIC0tZmlsZSBcIlwkTkVXX0NFUlRfRklMRVwiIFwKICAgIC0taWQgXCJodHRwczovLyRLRVlWQVVMVFBSRUZJWC1nd3kuJEtFWVZBVUxURE5TU1VGRklYL3NlY3JldHMvXCRTRUNSRVRfTkFNRVwiIFwKICAgICYmIGJyZWFrCiAgaWYgW1sgXCRhdHRlbXB0IC1sdCA1IF1dOyB0aGVuIHNsZWVwIDEwOyBlbHNlIGV4aXQgMTsgZmkKZG9uZQoKaWYgWyAtZiBcJE5FV19DRVJUX0ZJTEUgXTsgdGhlbgogIGlmIFtbIFwkQ09NUE9ORU5UID0gXCJtZHNkXCIgXV07IHRoZW4KICAgIGNob3duIHN5c2xvZzpzeXNsb2cgXCRORVdfQ0VSVF9GSUxFCiAgZWxzZQogICAgc2VkIC1pIC1uZSAnMSwvRU5EIENFUlRJRklDQVRFLyBwJyBcJE5FV19DRVJUX0ZJTEUKICBmaQoKICBuZXdfY2VydF9zbj1cIlwkKG9wZW5zc2wgeDUwOSAtaW4gXCJcJE5FV19DRVJUX0ZJTEVcIiAtbm9vdXQgLXNlcmlhbCB8IGF3ayAtRj0gJ3twcmludCBcJDJ9JylcIgogIGN1cnJlbnRfY2VydF9zbj1cIlwkKG9wZW5zc2wgeDUwOSAtaW4gXCJcJENVUlJFTlRfQ0VSVF9GSUxFXCIgLW5vb3V0IC1zZXJpYWwgfCBhd2sgLUY9ICd7cHJpbnQgXCQyfScpXCIKICBpZiBbWyAhIC16IFwkbmV3X2NlcnRfc24gXV0gJiYgW1sgXCRuZXdfY2VydF9zbiAhPSBcIlwkY3VycmVudF9jZXJ0X3NuXCIgXV07IHRoZW4KICAgIGVjaG8gdXBkYXRpbmcgY2VydGlmaWNhdGUgZm9yIFwkQ09NUE9ORU5UCiAgICBjaG1vZCAwNjAwIFwkTkVXX0NFUlRfRklMRQogICAgbXYgXCRORVdfQ0VSVF9GSUxFIFwkQ1VSUkVOVF9DRVJUX0ZJTEUKICBmaQplbHNlCiAgZWNobyBGYWlsZWQgdG8gcmVmcmVzaCBjZXJ0aWZpY2F0ZSBmb3IgXCRDT01QT05FTlQgJiYgZXhpdCAxCmZpIgoKICAgIHdyaXRlX2ZpbGUgZG93bmxvYWRfY3JlZHNfc2NyaXB0X2ZpbGVuYW1lIGRvd25sb2FkX2NyZWRzX3NjcmlwdF9maWxlIHRydWUKCiAgICBjaG1vZCB1K3ggL3Vzci9sb2NhbC9iaW4vZG93bmxvYWQtY3JlZGVudGlhbHMuc2gKCiAgICBzeXN0ZW1jdGwgZW5hYmxlIGRvd25sb2FkLW1kc2QtY3JlZGVudGlhbHMudGltZXIKICAgIHN5c3RlbWN0bCBlbmFibGUgZG93bmxvYWQtbWRtLWNyZWRlbnRpYWxzLnRpbWVyCgogICAgL3Vzci9sb2NhbC9iaW4vZG93bmxvYWQtY3JlZGVudGlhbHMuc2ggbWRzZAogICAgL3Vzci9sb2NhbC9iaW4vZG93bmxvYWQtY3JlZGVudGlhbHMuc2ggbWRtCgogICAgbG9jYWwgLXIgTURTRENFUlRJRklDQVRFU0FOPSIkKG9wZW5zc2wgeDUwOSAtaW4gL3Zhci9saWIvd2FhZ2VudC9NaWNyb3NvZnQuQXp1cmUuS2V5VmF1bHQuU3RvcmUvbWRzZC5wZW0gLW5vb3V0IC1zdWJqZWN0IHwgc2VkIC1lICdzLy4qQ04gPSAvLycpIgogICAgbG9jYWwgLXIgd2F0Y2hfbWRtX2NyZWRzX3NlcnZpY2VfZmlsZW5hbWU9Ii9ldGMvc3lzdGVtZC9zeXN0ZW0vd2F0Y2gtbWRtLWNyZWRlbnRpYWxzLnNlcnZpY2UiCiAgICBsb2NhbCAtciB3YXRjaF9tZG1fY3JlZHNfc2VydmljZV9maWxlPSJbVW5pdF0KRGVzY3JpcHRpb249V2F0Y2ggZm9yIGNoYW5nZXMgaW4gbWRtLnBlbSBhbmQgcmVzdGFydHMgdGhlIG1kbSBzZXJ2aWNlCgpbU2VydmljZV0KVHlwZT1vbmVzaG90CkV4ZWNTdGFydD0vdXNyL2Jpbi9zeXN0ZW1jdGwgcmVzdGFydCBtZG0uc2VydmljZQoKW0luc3RhbGxdCldhbnRlZEJ5PW11bHRpLXVzZXIudGFyZ2V0IgoKICAgIHdyaXRlX2ZpbGUgd2F0Y2hfbWRtX2NyZWRzX3NlcnZpY2VfZmlsZW5hbWUgd2F0Y2hfbWRtX2NyZWRzX3NlcnZpY2VfZmlsZSB0cnVlCgogICAgbG9jYWwgLXIgd2F0Y2hfbWRtX2NyZWRzX3BhdGhfZmlsZW5hbWU9Jy9ldGMvc3lzdGVtZC9zeXN0ZW0vd2F0Y2gtbWRtLWNyZWRlbnRpYWxzLnBhdGgnCiAgICBsb2NhbCAtciB3YXRjaF9tZG1fY3JlZHNfcGF0aF9maWxlPSdbUGF0aF0KUGF0aE1vZGlmaWVkPS9ldGMvbWRtLnBlbQoKW0luc3RhbGxdCldhbnRlZEJ5PW11bHRpLXVzZXIudGFyZ2V0JwoKICAgIHdyaXRlX2ZpbGUgd2F0Y2hfbWRtX2NyZWRzX3BhdGhfZmlsZW5hbWUgd2F0Y2hfbWRtX2NyZWRzX3BhdGhfZmlsZSB0cnVlCgogICAgbG9jYWwgLXIgd2F0Y2hfbWRtX2NyZWRzPSd3YXRjaC1tZG0tY3JlZGVudGlhbHMucGF0aCcKICAgIHN5c3RlbWN0bCBlbmFibGUgIiR3YXRjaF9tZG1fY3JlZHMiIHx8IGFib3J0ICJmYWlsZWQgdG8gZW5hYmxlICR3YXRjaF9tZG1fY3JlZHMiCiAgICBzeXN0ZW1jdGwgc3RhcnQgIiR3YXRjaF9tZG1fY3JlZHMiIHx8IGFib3J0ICJmYWlsZWQgdG8gc3RhcnQgJHdhdGNoX21kbV9jcmVkcyIKfQoKIyBjb25maWd1cmVfc2VydmljZV9hcm9fcnAKY29uZmlndXJlX3NlcnZpY2VfYXJvX2dhdGV3YXkoKSB7CiAgICBsb2NhbCAtbiBsb2dfZGlyPSIkMSIKICAgIGxvZyAic3RhcnRpbmciCgogICAgbG9jYWwgLXIgYXJvX2dhdGV3YXlfY29uZl9maWxlbmFtZT0nL2V0Yy9zeXNjb25maWcvYXJvLWdhdGV3YXknCiAgICBsb2NhbCAtciBhcm9fZ2F0ZXdheV9jb25mX2ZpbGU9IkFDUl9SRVNPVVJDRV9JRD0nJEFDUlJFU09VUkNFSUQnCkFETUlOX0FQSV9DTElFTlRfQ0VSVF9DT01NT05fTkFNRT0nJEFETUlOQVBJQ0xJRU5UQ0VSVENPTU1PTk5BTUUnCkFSTV9BUElfQ0xJRU5UX0NFUlRfQ09NTU9OX05BTUU9JyRBUk1BUElDTElFTlRDRVJUQ09NTU9OTkFNRScKQVpVUkVfQVJNX0NMSUVOVF9JRD0nJEFSTUNMSUVOVElEJwpBWlVSRV9GUF9DTElFTlRfSUQ9JyRGUENMSUVOVElEJwpBWlVSRV9GUF9TRVJWSUNFX1BSSU5DSVBBTF9JRD0nJEZQU0VSVklDRVBSSU5DSVBBTElEJwpCSUxMSU5HX0UyRV9TVE9SQUdFX0FDQ09VTlRfSUQ9JyRCSUxMSU5HRTJFU1RPUkFHRUFDQ09VTlRJRCcKQ0xVU1RFUl9NRE1fQUNDT1VOVD0nJENMVVNURVJNRE1BQ0NPVU5UJwpDTFVTVEVSX01ETV9OQU1FU1BBQ0U9UlAKQ0xVU1RFUl9NRFNEX0FDQ09VTlQ9JyRDTFVTVEVSTURTREFDQ09VTlQnCkNMVVNURVJfTURTRF9DT05GSUdfVkVSU0lPTj0nJENMVVNURVJNRFNEQ09ORklHVkVSU0lPTicKQ0xVU1RFUl9NRFNEX05BTUVTUEFDRT0nJENMVVNURVJNRFNETkFNRVNQQUNFJwpEQVRBQkFTRV9BQ0NPVU5UX05BTUU9JyREQVRBQkFTRUFDQ09VTlROQU1FJwpET01BSU5fTkFNRT0nJExPQ0FUSU9OLiRDTFVTVEVSUEFSRU5URE9NQUlOTkFNRScKQVpVUkVfREJUT0tFTl9DTElFTlRfSUQ9JyREQlRPS0VOQ0xJRU5USUQnCkRCVE9LRU5fVVJMPSckREJUT0tFTlVSTCcKTURNX0FDQ09VTlQ9JyRSUE1ETUFDQ09VTlQnCk1ETV9OQU1FU1BBQ0U9R2F0ZXdheQpHQVRFV0FZX0RPTUFJTlM9JyRHQVRFV0FZRE9NQUlOUycKR0FURVdBWV9GRUFUVVJFUz0nJEdBVEVXQVlGRUFUVVJFUycKR0FURVdBWV9SRVNPVVJDRUdST1VQPSckR0FURVdBWVJFU09VUkNFR1JPVVBOQU1FJwpLRVlWQVVMVF9QUkVGSVg9JyRLRVlWQVVMVFBSRUZJWCcKTURNX0FDQ09VTlQ9JyRSUE1ETUFDQ09VTlQnCk1ETV9OQU1FU1BBQ0U9UlAKTURTRF9FTlZJUk9OTUVOVD0nJE1EU0RFTlZJUk9OTUVOVCcKUlBfRkVBVFVSRVM9JyRSUEZFQVRVUkVTJwpSUElNQUdFPSckUlBJTUFHRScKQVJPX0lOU1RBTExfVklBX0hJVkU9JyRDTFVTVEVSU0lOU1RBTExWSUFISVZFJwpBUk9fSElWRV9ERUZBVUxUX0lOU1RBTExFUl9QVUxMU1BFQz0nJENMVVNURVJERUZBVUxUSU5TVEFMTEVSUFVMTFNQRUMnCkFST19BRE9QVF9CWV9ISVZFPSckQ0xVU1RFUlNBRE9QVEJZSElWRScKVVNFX0NIRUNLQUNDRVNTPSckVVNFQ0hFQ0tBQ0NFU1MnIgoKICAgIHdyaXRlX2ZpbGUgYXJvX2dhdGV3YXlfY29uZl9maWxlbmFtZSBhcm9fZ2F0ZXdheV9jb25mX2ZpbGUgdHJ1ZQoKICAgIGxvY2FsIC1yIGFyb19nYXRld2F5X3NlcnZpY2VfZmlsZW5hbWU9Jy9ldGMvc3lzdGVtZC9zeXN0ZW0vYXJvLWdhdGV3YXkuc2VydmljZScKCiAgICBsb2NhbCAtciBhcm9fZ2F0ZXdheV9zZXJ2aWNlX2ZpbGU9IltVbml0XQpBZnRlcj1uZXR3b3JrLW9ubGluZS50YXJnZXQKV2FudHM9bmV0d29yay1vbmxpbmUudGFyZ2V0CgpbU2VydmljZV0KRW52aXJvbm1lbnRGaWxlPS9ldGMvc3lzY29uZmlnL2Fyby1nYXRld2F5CkV4ZWNTdGFydFByZT0tL3Vzci9iaW4vZG9ja2VyIHJtIC1mICVOCkV4ZWNTdGFydFByZT0vdXNyL2Jpbi9ta2RpciAtcCAke2xvZ19kaXJ9CkV4ZWNTdGFydD0vdXNyL2Jpbi9kb2NrZXIgcnVuIFwKICAtLWhvc3RuYW1lICVIIFwKICAtLW5hbWUgJU4gXAogIC0tcm0gXAogIC0tY2FwLWRyb3AgbmV0X3JhdyBcCiAgLWUgQUNSX1JFU09VUkNFX0lEIFwKICAtZSBEQVRBQkFTRV9BQ0NPVU5UX05BTUUgXAogIC1lIEFaVVJFX0RCVE9LRU5fQ0xJRU5UX0lEIFwKICAtZSBEQlRPS0VOX1VSTCBcCiAgLWUgR0FURVdBWV9ET01BSU5TIFwKICAtZSBHQVRFV0FZX0ZFQVRVUkVTIFwKICAtZSBNRE1fQUNDT1VOVCBcCiAgLWUgTURNX05BTUVTUEFDRSBcCiAgLW0gMmcgXAogIC1wIDgwOjgwODAgXAogIC1wIDgwODE6ODA4MSBcCiAgLXAgNDQzOjg0NDMgXAogIC12IC9ydW4vc3lzdGVtZC9qb3VybmFsOi9ydW4vc3lzdGVtZC9qb3VybmFsIFwKICAtdiAvdmFyL2V0dzovdmFyL2V0dzp6IFwKICAtdiAke2xvZ19kaXJ9Oi9jdHIubG9nOnogXAogIFwkUlBJTUFHRSBcCiAgZ2F0ZXdheQpFeGVjU3RvcD0vdXNyL2Jpbi9kb2NrZXIgc3RvcCAtdCAzNjAwICVOClRpbWVvdXRTdG9wU2VjPTM2MDAKUmVzdGFydD1hbHdheXMKUmVzdGFydFNlYz0xClN0YXJ0TGltaXRJbnRlcnZhbD0wCgpbSW5zdGFsbF0KV2FudGVkQnk9bXVsdGktdXNlci50YXJnZXQKICAgICIKCiAgICB3cml0ZV9maWxlIGFyb19nYXRld2F5X3NlcnZpY2VfZmlsZW5hbWUgYXJvX2dhdGV3YXlfc2VydmljZV9maWxlIHRydWUKfQoKIyBjb25maWd1cmVfc2VydmljZV9hcm9fZGJ0b2tlbgpjb25maWd1cmVfc2VydmljZV9hcm9fZGJ0b2tlbigpIHsKICAgIGxvZyAic3RhcnRpbmciCgogICAgbG9jYWwgLXIgYXJvX2RidG9rZW5fc2VydmljZV9jb25mX2ZpbGVuYW1lPScvZXRjL3N5c2NvbmZpZy9hcm8tZGJ0b2tlbicKICAgIGxvY2FsIC1yIGFyb19kYnRva2VuX3NlcnZpY2VfY29uZl9maWxlPSJBQ1JfUkVTT1VSQ0VfSUQ9JyRBQ1JSRVNPVVJDRUlEJwpEQVRBQkFTRV9BQ0NPVU5UX05BTUU9JyREQVRBQkFTRUFDQ09VTlROQU1FJwpBWlVSRV9EQlRPS0VOX0NMSUVOVF9JRD0nJERCVE9LRU5DTElFTlRJRCcKREJUT0tFTl9VUkw9JyREQlRPS0VOVVJMJwpNRE1fQUNDT1VOVD0nJFJQTURNQUNDT1VOVCcKTURNX05BTUVTUEFDRT1HYXRld2F5CkdBVEVXQVlfRE9NQUlOUz0nJEdBVEVXQVlET01BSU5TJwpHQVRFV0FZX0ZFQVRVUkVTPSckR0FURVdBWUZFQVRVUkVTJwpSUElNQUdFPSckUlBJTUFHRSciCgogICAgd3JpdGVfZmlsZSBhcm9fZGJ0b2tlbl9zZXJ2aWNlX2NvbmZfZmlsZW5hbWUgYXJvX2RidG9rZW5fc2VydmljZV9jb25mX2ZpbGUgdHJ1ZQoKICAgIGxvY2FsIC1yIGFyb19kYnRva2VuX3NlcnZpY2VfZmlsZW5hbWU9Jy9ldGMvc3lzdGVtZC9zeXN0ZW0vYXJvLWRidG9rZW4uc2VydmljZScKICAgIGxvY2FsIC1yIGFyb19kYnRva2VuX3NlcnZpY2VfZmlsZT0iW1VuaXRdCkFmdGVyPW5ldHdvcmstb25saW5lLnRhcmdldApXYW50cz1uZXR3b3JrLW9ubGluZS50YXJnZXQKCltTZXJ2aWNlXQpFbnZpcm9ubWVudEZpbGU9L2V0Yy9zeXNjb25maWcvYXJvLWdhdGV3YXkKRXhlY1N0YXJ0UHJlPS0vdXNyL2Jpbi9kb2NrZXIgcm0gLWYgJU4KRXhlY1N0YXJ0UHJlPS91c3IvYmluL21rZGlyIC1wICR7Z2F0ZXdheV9sb2dkaXJ9CkV4ZWNTdGFydD0vdXNyL2Jpbi9kb2NrZXIgcnVuIFwKICAtLWhvc3RuYW1lICVIIFwKICAtLW5hbWUgJU4gXAogIC0tcm0gXAogIC0tY2FwLWRyb3AgbmV0X3JhdyBcCiAgLWUgQUNSX1JFU09VUkNFX0lEIFwKICAtZSBEQVRBQkFTRV9BQ0NPVU5UX05BTUUgXAogIC1lIEFaVVJFX0RCVE9LRU5fQ0xJRU5UX0lEIFwKICAtZSBEQlRPS0VOX1VSTCBcCiAgLWUgR0FURVdBWV9ET01BSU5TIFwKICAtZSBHQVRFV0FZX0ZFQVRVUkVTIFwKICAtZSBNRE1fQUNDT1VOVCBcCiAgLWUgTURNX05BTUVTUEFDRSBcCiAgLW0gMmcgXAogIC1wIDgwOjgwODAgXAogIC1wIDgwODE6ODA4MSBcCiAgLXAgNDQzOjg0NDMgXAogIC12IC9ydW4vc3lzdGVtZC9qb3VybmFsOi9ydW4vc3lzdGVtZC9qb3VybmFsIFwKICAtdiAvdmFyL2V0dzovdmFyL2V0dzp6IFwKICAtdiAke2dhdGV3YXlfbG9nZGlyfTovY3RyLmxvZzp6IFwKICBcJFJQSU1BR0UgXAogIGdhdGV3YXkKRXhlY1N0b3A9L3Vzci9iaW4vZG9ja2VyIHN0b3AgLXQgMzYwMCAlTgpUaW1lb3V0U3RvcFNlYz0zNjAwClJlc3RhcnQ9YWx3YXlzClJlc3RhcnRTZWM9MQpTdGFydExpbWl0SW50ZXJ2YWw9MAoKW0luc3RhbGxdCldhbnRlZEJ5PW11bHRpLXVzZXIudGFyZ2V0IgoKICAgIHdyaXRlX2ZpbGUgYXJvX2RidG9rZW5fc2VydmljZV9maWxlbmFtZSBhcm9fZGJ0b2tlbl9zZXJ2aWNlX2ZpbGUgdHJ1ZQp9CgojIGNvbmZpZ3VyZV9zZXJ2aWNlX21kc2QKY29uZmlndXJlX3NlcnZpY2VfbWRzZCgpIHsKICAgIGxvZyAic3RhcnRpbmciCgogICAgbG9jYWwgLXIgbWRzZF9zZXJ2aWNlX2Rpcj0iL2V0Yy9zeXN0ZW1kL3N5c3RlbS9tZHNkLnNlcnZpY2UuZCIKICAgIG1rZGlyICIkbWRzZF9zZXJ2aWNlX2RpciIKCiAgICBsb2NhbCAtciBtZHNkX292ZXJyaWRlX2NvbmZfZmlsZW5hbWU9IiRtZHNkX3NlcnZpY2VfZGlyL292ZXJyaWRlLmNvbmYiCiAgICBsb2NhbCAtciBtZHNkX292ZXJyaWRlX2NvbmZfZmlsZT0iW1VuaXRdCkFmdGVyPW5ldHdvcmstb25saW5lLnRhcmdldCIKCiAgICB3cml0ZV9maWxlIG1kc2Rfb3ZlcnJpZGVfY29uZl9maWxlbmFtZSBtZHNkX292ZXJyaWRlX2NvbmZfZmlsZSB0cnVlCgogICAgbG9jYWwgLXIgZGVmYXVsdF9tZHNkX2ZpbGVuYW1lPSIvZXRjL2RlZmF1bHQvbWRzZCIKICAgIGxvY2FsIC1yIGRlZmF1bHRfbWRzZF9maWxlPSJNRFNEX1JPTEVfUFJFRklYPS92YXIvcnVuL21kc2QvZGVmYXVsdApNRFNEX09QVElPTlM9XCItQSAtZCAtciBcJE1EU0RfUk9MRV9QUkVGSVhcIgoKZXhwb3J0IE1PTklUT1JJTkdfR0NTX0VOVklST05NRU5UPSckTURTREVOVklST05NRU5UJwpleHBvcnQgTU9OSVRPUklOR19HQ1NfQUNDT1VOVD0nJFJQTURTREFDQ09VTlQnCmV4cG9ydCBNT05JVE9SSU5HX0dDU19SRUdJT049JyRMT0NBVElPTicKZXhwb3J0IE1PTklUT1JJTkdfR0NTX0FVVEhfSURfVFlQRT1BdXRoS2V5VmF1bHQKZXhwb3J0IE1PTklUT1JJTkdfR0NTX0FVVEhfSUQ9JyRNRFNEQ0VSVElGSUNBVEVTQU4nCmV4cG9ydCBNT05JVE9SSU5HX0dDU19OQU1FU1BBQ0U9JyRSUE1EU0ROQU1FU1BBQ0UnCmV4cG9ydCBNT05JVE9SSU5HX0NPTkZJR19WRVJTSU9OPSckR0FURVdBWU1EU0RDT05GSUdWRVJTSU9OJwpleHBvcnQgTU9OSVRPUklOR19VU0VfR0VORVZBX0NPTkZJR19TRVJWSUNFPXRydWUKCmV4cG9ydCBNT05JVE9SSU5HX1RFTkFOVD0nJExPQ0FUSU9OJwpleHBvcnQgTU9OSVRPUklOR19ST0xFPWdhdGV3YXkKZXhwb3J0IE1PTklUT1JJTkdfUk9MRV9JTlNUQU5DRT1cIiQoaG9zdG5hbWUpXCIKCmV4cG9ydCBNRFNEX01TR1BBQ0tfU09SVF9DT0xVTU5TPTFcIiIKCiAgICB3cml0ZV9maWxlIGRlZmF1bHRfbWRzZF9maWxlbmFtZSBkZWZhdWx0X21kc2RfZmlsZSB0cnVlCgp9CgojIHJ1bl9henNlY2RfY29uZmlnX3NjYW4KcnVuX2F6c2VjZF9jb25maWdfc2NhbigpIHsKICAgIGxvZyAic3RhcnRpbmciCgogICAgbG9jYWwgLWFyIGNvbmZpZ3M9KAogICAgICAgICJiYXNlbGluZSIKICAgICAgICAiY2xhbWF2IgogICAgICAgICJzb2Z0d2FyZSIKICAgICkKCiAgICBsb2cgIlNjYW5uaW5nIGNvbmZpZ3VyYXRpb24gZmlsZXMgJHtjb25maWdzWypdfSIKICAgICMgc2hlbGxjaGVjayBkaXNhYmxlPVNDMjA2OAogICAgZm9yIHNjYW4gaW4gJHtjb25maWdzW0BdfTsgZG8KICAgICAgICBsb2cgIlNjYW5uaW5nIGNvbmZpZyBmaWxlICRzY2FuIG5vdyIKICAgICAgICAvdXNyL2xvY2FsL2Jpbi9henNlY2QgY29uZmlnIC1zICIkc2NhbiIgLWQgUDFECiAgICBkb25lCn0KCiMgd3JpdGVfZmlsZQojIEFyZ3MKIyAxKSBmaWxlbmFtZSAtIHN0cmluZwojIDIpIGZpbGVfY29udGVudHMgLSBzdHJpbmcKIyAzKSBjbG9iYmVyIC0gYm9vbGVhbjsgb3B0aW9uYWwgLSBkZWZhdWx0cyB0byBmYWxzZQp3cml0ZV9maWxlKCkgewogICAgbG9jYWwgLW4gZmlsZW5hbWU9IiQxIgogICAgbG9jYWwgLW4gZmlsZV9jb250ZW50cz0iJDIiCiAgICBsb2NhbCAtciBjbG9iYmVyPSIkezM6LWZhbHNlfSIKCiAgICBpZiAkY2xvYmJlcjsgdGhlbgogICAgICAgIGxvZyAiT3ZlcndyaXRpbmcgZmlsZSAkZmlsZW5hbWUiCiAgICAgICAgZWNobyAiJGZpbGVfY29udGVudHMiID4gIiRmaWxlbmFtZSIKICAgIGVsc2UKICAgICAgICBsb2cgIkFwcGVuZGluZyB0byAkZmlsZW5hbWUiCiAgICAgICAgZWNobyAiJGZpbGVfY29udGVudHMiID4+ICIkZmlsZW5hbWUiCiAgICBmaQp9CgojIHJlYm9vdF92bSByZXN0b3JlcyBhbGwgc2VsaW51eCBmaWxlIGNvbnRleHRzLCB3YWl0cyAzMCBzZWNvbmRzIHRoZW4gcmVib290cwpyZWJvb3Rfdm0oKSB7CiAgICBsb2cgInN0YXJ0aW5nIgoKICAgIGNvbmZpZ3VyZV9zZWxpbnV4ICJ0cnVlIgogICAgKHNsZWVwIDMwICYmIGxvZyAicmVib290aW5nIHZtIG5vdyI7IHJlYm9vdCkgJgp9CgojIGxvZyBpcyBhIHdyYXBwZXIgZm9yIGVjaG8gdGhhdCBpbmNsdWRlcyB0aGUgZnVuY3Rpb24gbmFtZQpsb2coKSB7CiAgICBsb2NhbCAtciBtc2c9IiR7MTotImxvZyBtZXNzYWdlIGlzIGVtcHR5In0iCiAgICBsb2NhbCAtciBzdGFja19sZXZlbD0iJHsyOi0xfSIKICAgIGVjaG8gIiR7RlVOQ05BTUVbJHtzdGFja19sZXZlbH1dfTogJHttc2d9Igp9CgojIGFib3J0IGlzIGEgd3JhcHBlciBmb3IgbG9nIHRoYXQgZXhpdHMgd2l0aCBhbiBlcnJvciBjb2RlCmFib3J0KCkgewogICAgbG9jYWwgLXJpIG9yaWdpbl9zdGFja2xldmVsPTIKICAgIGxvZyAiJHsxfSIgIiRvcmlnaW5fc3RhY2tsZXZlbCIKICAgIGxvZyAiRXhpdGluZyIKICAgIGV4aXQgMQp9CgpleHBvcnQgQVpVUkVfQ0xPVURfTkFNRT0iJHtBWlVSRUNMT1VETkFNRTo/IkZhaWxlZCB0byBjYXJyeSBvdmVyIHZhcmlhYmxlcyJ9IgoKbWFpbiAiJEAiCg==')))]" } } } diff --git a/pkg/deploy/assets/rp-production.json b/pkg/deploy/assets/rp-production.json index 7b80cdb2236..99f72f4d6ff 100644 --- a/pkg/deploy/assets/rp-production.json +++ b/pkg/deploy/assets/rp-production.json @@ -516,7 +516,7 @@ "autoUpgradeMinorVersion": true, "settings": {}, "protectedSettings": { - "script": "[base64(concat(base64ToString('c2V0IC1leAoK'),'ACRRESOURCEID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('acrResourceId')),''')\n','ADMINAPICLIENTCERTCOMMONNAME=$(base64 -d \u003c\u003c\u003c''',base64(parameters('adminApiClientCertCommonName')),''')\n','ARMAPICLIENTCERTCOMMONNAME=$(base64 -d \u003c\u003c\u003c''',base64(parameters('armApiClientCertCommonName')),''')\n','ARMCLIENTID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('armClientId')),''')\n','AZURECLOUDNAME=$(base64 -d \u003c\u003c\u003c''',base64(parameters('azureCloudName')),''')\n','AZURESECPACKQUALYSURL=$(base64 -d \u003c\u003c\u003c''',base64(parameters('azureSecPackQualysUrl')),''')\n','AZURESECPACKVSATENANTID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('azureSecPackVSATenantId')),''')\n','BILLINGE2ESTORAGEACCOUNTID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('billingE2EStorageAccountId')),''')\n','CLUSTERMDMACCOUNT=$(base64 -d \u003c\u003c\u003c''',base64(parameters('clusterMdmAccount')),''')\n','CLUSTERMDSDACCOUNT=$(base64 -d \u003c\u003c\u003c''',base64(parameters('clusterMdsdAccount')),''')\n','CLUSTERMDSDCONFIGVERSION=$(base64 -d \u003c\u003c\u003c''',base64(parameters('clusterMdsdConfigVersion')),''')\n','CLUSTERMDSDNAMESPACE=$(base64 -d \u003c\u003c\u003c''',base64(parameters('clusterMdsdNamespace')),''')\n','CLUSTERPARENTDOMAINNAME=$(base64 -d \u003c\u003c\u003c''',base64(parameters('clusterParentDomainName')),''')\n','DATABASEACCOUNTNAME=$(base64 -d \u003c\u003c\u003c''',base64(parameters('databaseAccountName')),''')\n','DBTOKENCLIENTID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('dbtokenClientId')),''')\n','FLUENTBITIMAGE=$(base64 -d \u003c\u003c\u003c''',base64(parameters('fluentbitImage')),''')\n','FPCLIENTID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('fpClientId')),''')\n','FPSERVICEPRINCIPALID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('fpServicePrincipalId')),''')\n','GATEWAYDOMAINS=$(base64 -d \u003c\u003c\u003c''',base64(parameters('gatewayDomains')),''')\n','GATEWAYRESOURCEGROUPNAME=$(base64 -d \u003c\u003c\u003c''',base64(parameters('gatewayResourceGroupName')),''')\n','GATEWAYSERVICEPRINCIPALID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('gatewayServicePrincipalId')),''')\n','KEYVAULTDNSSUFFIX=$(base64 -d \u003c\u003c\u003c''',base64(parameters('keyvaultDNSSuffix')),''')\n','KEYVAULTPREFIX=$(base64 -d \u003c\u003c\u003c''',base64(parameters('keyvaultPrefix')),''')\n','MDMFRONTENDURL=$(base64 -d \u003c\u003c\u003c''',base64(parameters('mdmFrontendUrl')),''')\n','MDSDENVIRONMENT=$(base64 -d \u003c\u003c\u003c''',base64(parameters('mdsdEnvironment')),''')\n','PORTALACCESSGROUPIDS=$(base64 -d \u003c\u003c\u003c''',base64(parameters('portalAccessGroupIds')),''')\n','PORTALCLIENTID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('portalClientId')),''')\n','PORTALELEVATEDGROUPIDS=$(base64 -d \u003c\u003c\u003c''',base64(parameters('portalElevatedGroupIds')),''')\n','RPFEATURES=$(base64 -d \u003c\u003c\u003c''',base64(parameters('rpFeatures')),''')\n','RPIMAGE=$(base64 -d \u003c\u003c\u003c''',base64(parameters('rpImage')),''')\n','RPMDMACCOUNT=$(base64 -d \u003c\u003c\u003c''',base64(parameters('rpMdmAccount')),''')\n','RPMDSDACCOUNT=$(base64 -d \u003c\u003c\u003c''',base64(parameters('rpMdsdAccount')),''')\n','RPMDSDCONFIGVERSION=$(base64 -d \u003c\u003c\u003c''',base64(parameters('rpMdsdConfigVersion')),''')\n','RPMDSDNAMESPACE=$(base64 -d \u003c\u003c\u003c''',base64(parameters('rpMdsdNamespace')),''')\n','RPPARENTDOMAINNAME=$(base64 -d \u003c\u003c\u003c''',base64(parameters('rpParentDomainName')),''')\n','CLUSTERSINSTALLVIAHIVE=$(base64 -d \u003c\u003c\u003c''',base64(parameters('clustersInstallViaHive')),''')\n','CLUSTERSADOPTBYHIVE=$(base64 -d \u003c\u003c\u003c''',base64(parameters('clustersAdoptByHive')),''')\n','CLUSTERDEFAULTINSTALLERPULLSPEC=$(base64 -d \u003c\u003c\u003c''',base64(parameters('clusterDefaultInstallerPullspec')),''')\n','USECHECKACCESS=$(base64 -d \u003c\u003c\u003c''',base64(parameters('useCheckAccess')),''')\n','ADMINAPICABUNDLE=''',parameters('adminApiCaBundle'),'''\n','ARMAPICABUNDLE=''',parameters('armApiCaBundle'),'''\n','MDMIMAGE=''/genevamdm:2.2024.328.1744-c5fb79-20240328t1935''\n','LOCATION=$(base64 -d \u003c\u003c\u003c''',base64(resourceGroup().location),''')\n','SUBSCRIPTIONID=$(base64 -d \u003c\u003c\u003c''',base64(subscription().subscriptionId),''')\n','RESOURCEGROUPNAME=$(base64 -d \u003c\u003c\u003c''',base64(resourceGroup().name),''')\n','\n',base64ToString('IyEvYmluL2Jhc2gKCmVjaG8gInNldHRpbmcgc3NoIHBhc3N3b3JkIGF1dGhlbnRpY2F0aW9uIgojIFdlIG5lZWQgdG8gbWFudWFsbHkgc2V0IFBhc3N3b3JkQXV0aGVudGljYXRpb24gdG8gdHJ1ZSBpbiBvcmRlciBmb3IgdGhlIFZNU1MgQWNjZXNzIEpJVCB0byB3b3JrCnNlZCAtaSAncy9QYXNzd29yZEF1dGhlbnRpY2F0aW9uIG5vL1Bhc3N3b3JkQXV0aGVudGljYXRpb24geWVzL2cnIC9ldGMvc3NoL3NzaGRfY29uZmlnCnN5c3RlbWN0bCByZWxvYWQgc3NoZC5zZXJ2aWNlCgojQWRkaW5nIHJldHJ5IGxvZ2ljIHRvIHl1bSBjb21tYW5kcyBpbiBvcmRlciB0byBhdm9pZCBzdGFsbGluZyBvdXQgb24gcmVzb3VyY2UgbG9ja3MKZWNobyAicnVubmluZyBSSFVJIGZpeCIKZm9yIGF0dGVtcHQgaW4gezEuLjV9OyBkbwogIHl1bSB1cGRhdGUgLXkgLS1kaXNhYmxlcmVwbz0nKicgLS1lbmFibGVyZXBvPSdyaHVpLW1pY3Jvc29mdC1henVyZSonICYmIGJyZWFrCiAgaWYgW1sgJHthdHRlbXB0fSAtbHQgNSBdXTsgdGhlbiBzbGVlcCAxMDsgZWxzZSBleGl0IDE7IGZpCmRvbmUKCmVjaG8gInJ1bm5pbmcgeXVtIHVwZGF0ZSIKZm9yIGF0dGVtcHQgaW4gezEuLjV9OyBkbwogIHl1bSAteSAteCBXQUxpbnV4QWdlbnQgLXggV0FMaW51eEFnZW50LXVkZXYgdXBkYXRlIC0tYWxsb3dlcmFzaW5nICYmIGJyZWFrCiAgaWYgW1sgJHthdHRlbXB0fSAtbHQgNSBdXTsgdGhlbiBzbGVlcCAxMDsgZWxzZSBleGl0IDE7IGZpCmRvbmUKCmVjaG8gImV4dGVuZGluZyBwYXJ0aXRpb24gdGFibGUiCiMgTGludXggYmxvY2sgZGV2aWNlcyBhcmUgaW5jb25zaXN0ZW50bHkgbmFtZWQKIyBpdCdzIGRpZmZpY3VsdCB0byB0aWUgdGhlIGx2bSBwdiB0byB0aGUgcGh5c2ljYWwgZGlzayB1c2luZyAvZGV2L2Rpc2sgZmlsZXMsIHdoaWNoIGlzIHdoeSBsdnMgaXMgdXNlZCBoZXJlCnBoeXNpY2FsRGlzaz0iJChsdnMgLW8gZGV2aWNlcyAtYSB8IGhlYWQgLW4yIHwgdGFpbCAtbjEgfCBjdXQgLWQgJyAnIC1mIDMgfCBjdXQgLWQgXCggLWYgMSB8IHRyIC1kICdbOmRpZ2l0Ol0nKSIKZ3Jvd3BhcnQgIiRwaHlzaWNhbERpc2siIDIKCmVjaG8gImV4dGVuZGluZyBmaWxlc3lzdGVtcyIKbHZleHRlbmQgLWwgKzIwJUZSRUUgL2Rldi9yb290dmcvcm9vdGx2Cnhmc19ncm93ZnMgLwoKbHZleHRlbmQgLWwgKzEwMCVGUkVFIC9kZXYvcm9vdHZnL3Zhcmx2Cnhmc19ncm93ZnMgL3ZhcgoKZWNobyAiaW1wb3J0aW5nIHJwbSByZXBvc2l0b3JpZXMiCnJwbSAtLWltcG9ydCBodHRwczovL2RsLmZlZG9yYXByb2plY3Qub3JnL3B1Yi9lcGVsL1JQTS1HUEctS0VZLUVQRUwtOApycG0gLS1pbXBvcnQgaHR0cHM6Ly9wYWNrYWdlcy5taWNyb3NvZnQuY29tL2tleXMvbWljcm9zb2Z0LmFzYwoKZm9yIGF0dGVtcHQgaW4gezEuLjV9OyBkbwogIHl1bSAteSBpbnN0YWxsIGh0dHBzOi8vZGwuZmVkb3JhcHJvamVjdC5vcmcvcHViL2VwZWwvZXBlbC1yZWxlYXNlLWxhdGVzdC04Lm5vYXJjaC5ycG0gJiYgYnJlYWsKICBpZiBbWyAke2F0dGVtcHR9IC1sdCA1IF1dOyB0aGVuIHNsZWVwIDEwOyBlbHNlIGV4aXQgMTsgZmkKZG9uZQoKZWNobyAiY29uZmlndXJpbmcgbG9ncm90YXRlIgpjYXQgPi9ldGMvbG9ncm90YXRlLmNvbmYgPDwnRU9GJwojIHNlZSAibWFuIGxvZ3JvdGF0ZSIgZm9yIGRldGFpbHMKIyByb3RhdGUgbG9nIGZpbGVzIHdlZWtseQp3ZWVrbHkKCiMga2VlcCAyIHdlZWtzIHdvcnRoIG9mIGJhY2tsb2dzCnJvdGF0ZSAyCgojIGNyZWF0ZSBuZXcgKGVtcHR5KSBsb2cgZmlsZXMgYWZ0ZXIgcm90YXRpbmcgb2xkIG9uZXMKY3JlYXRlCgojIHVzZSBkYXRlIGFzIGEgc3VmZml4IG9mIHRoZSByb3RhdGVkIGZpbGUKZGF0ZWV4dAoKIyB1bmNvbW1lbnQgdGhpcyBpZiB5b3Ugd2FudCB5b3VyIGxvZyBmaWxlcyBjb21wcmVzc2VkCmNvbXByZXNzCgojIFJQTSBwYWNrYWdlcyBkcm9wIGxvZyByb3RhdGlvbiBpbmZvcm1hdGlvbiBpbnRvIHRoaXMgZGlyZWN0b3J5CmluY2x1ZGUgL2V0Yy9sb2dyb3RhdGUuZAoKIyBubyBwYWNrYWdlcyBvd24gd3RtcCBhbmQgYnRtcCAtLSB3ZSdsbCByb3RhdGUgdGhlbSBoZXJlCi92YXIvbG9nL3d0bXAgewogICAgbW9udGhseQogICAgY3JlYXRlIDA2NjQgcm9vdCB1dG1wCiAgICAgICAgbWluc2l6ZSAxTQogICAgcm90YXRlIDEKfQoKL3Zhci9sb2cvYnRtcCB7CiAgICBtaXNzaW5nb2sKICAgIG1vbnRobHkKICAgIGNyZWF0ZSAwNjAwIHJvb3QgdXRtcAogICAgcm90YXRlIDEKfQpFT0YKCmVjaG8gImNvbmZpZ3VyaW5nIHl1bSByZXBvc2l0b3J5IGFuZCBydW5uaW5nIHl1bSB1cGRhdGUiCmNhdCA+L2V0Yy95dW0ucmVwb3MuZC9henVyZS5yZXBvIDw8J0VPRicKW2F6dXJlLWNsaV0KbmFtZT1henVyZS1jbGkKYmFzZXVybD1odHRwczovL3BhY2thZ2VzLm1pY3Jvc29mdC5jb20veXVtcmVwb3MvYXp1cmUtY2xpCmVuYWJsZWQ9eWVzCmdwZ2NoZWNrPXllcwoKW2F6dXJlY29yZV0KbmFtZT1henVyZWNvcmUKYmFzZXVybD1odHRwczovL3BhY2thZ2VzLm1pY3Jvc29mdC5jb20veXVtcmVwb3MvYXp1cmVjb3JlCmVuYWJsZWQ9eWVzCmdwZ2NoZWNrPW5vCkVPRgoKc2VtYW5hZ2UgZmNvbnRleHQgLWEgLXQgdmFyX2xvZ190ICIvdmFyL2xvZy9qb3VybmFsKC8uKik/Igpta2RpciAtcCAvdmFyL2xvZy9qb3VybmFsCgpmb3IgYXR0ZW1wdCBpbiB7MS4uNX07IGRvCnl1bSAteSBpbnN0YWxsIGNsYW1hdiBhenNlYy1jbGFtYXYgYXpzZWMtbW9uaXRvciBhenVyZS1jbGkgYXp1cmUtbWRzZCBhenVyZS1zZWN1cml0eSBwb2RtYW4gcG9kbWFuLWRvY2tlciBvcGVuc3NsLXBlcmwgcHl0aG9uMyAmJiBicmVhawogICMgaGFjayAtIHdlIGFyZSBpbnN0YWxsaW5nIHB5dGhvbjMgb24gaG9zdHMgZHVlIHRvIGFuIGlzc3VlIHdpdGggQXp1cmUgTGludXggRXh0ZW5zaW9ucyBodHRwczovL2dpdGh1Yi5jb20vQXp1cmUvYXp1cmUtbGludXgtZXh0ZW5zaW9ucy9wdWxsLzE1MDUKICBpZiBbWyAke2F0dGVtcHR9IC1sdCA1IF1dOyB0aGVuIHNsZWVwIDEwOyBlbHNlIGV4aXQgMTsgZmkKZG9uZQoKIyBodHRwczovL2FjY2Vzcy5yZWRoYXQuY29tL3NlY3VyaXR5L2N2ZS9jdmUtMjAyMC0xMzQwMQplY2hvICJhcHBseWluZyBmaXJld2FsbCBydWxlcyIKY2F0ID4vZXRjL3N5c2N0bC5kLzAyLWRpc2FibGUtYWNjZXB0LXJhLmNvbmYgPDwnRU9GJwpuZXQuaXB2Ni5jb25mLmFsbC5hY2NlcHRfcmE9MApFT0YKCmNhdCA+L2V0Yy9zeXNjdGwuZC8wMS1kaXNhYmxlLWNvcmUuY29uZiA8PCdFT0YnCmtlcm5lbC5jb3JlX3BhdHRlcm4gPSB8L2Jpbi90cnVlCkVPRgpzeXNjdGwgLS1zeXN0ZW0KCmZpcmV3YWxsLWNtZCAtLWFkZC1wb3J0PTQ0My90Y3AgLS1wZXJtYW5lbnQKZmlyZXdhbGwtY21kIC0tYWRkLXBvcnQ9NDQ0L3RjcCAtLXBlcm1hbmVudApmaXJld2FsbC1jbWQgLS1hZGQtcG9ydD00NDUvdGNwIC0tcGVybWFuZW50CmZpcmV3YWxsLWNtZCAtLWFkZC1wb3J0PTIyMjIvdGNwIC0tcGVybWFuZW50CgpleHBvcnQgQVpVUkVfQ0xPVURfTkFNRT0kQVpVUkVDTE9VRE5BTUUKCmVjaG8gImxvZ2dpbmcgaW50byBwcm9kIGFjciIKYXogbG9naW4gLWkgLS1hbGxvdy1uby1zdWJzY3JpcHRpb25zCgojIFN1cHByZXNzIGVtdWxhdGlvbiBvdXRwdXQgZm9yIHBvZG1hbiBpbnN0ZWFkIG9mIGRvY2tlciBmb3IgYXogYWNyIGNvbXBhdGFiaWxpdHkKbWtkaXIgLXAgL2V0Yy9jb250YWluZXJzLwp0b3VjaCAvZXRjL2NvbnRhaW5lcnMvbm9kb2NrZXIKCm1rZGlyIC1wIC9yb290Ly5kb2NrZXIKUkVHSVNUUllfQVVUSF9GSUxFPS9yb290Ly5kb2NrZXIvY29uZmlnLmpzb24gYXogYWNyIGxvZ2luIC0tbmFtZSAiJChzZWQgLWUgJ3N8LiovfHwnIDw8PCIkQUNSUkVTT1VSQ0VJRCIpIgoKTURNSU1BR0U9IiR7UlBJTUFHRSUlLyp9LyR7TURNSU1BR0UjIyovfSIKZG9ja2VyIHB1bGwgIiRNRE1JTUFHRSIKZG9ja2VyIHB1bGwgIiRSUElNQUdFIgpkb2NrZXIgcHVsbCAiJEZMVUVOVEJJVElNQUdFIgoKYXogbG9nb3V0CgplY2hvICJjb25maWd1cmluZyBmbHVlbnRiaXQgc2VydmljZSIKbWtkaXIgLXAgL2V0Yy9mbHVlbnRiaXQvCm1rZGlyIC1wIC92YXIvbGliL2ZsdWVudAoKY2F0ID4vZXRjL2ZsdWVudGJpdC9mbHVlbnRiaXQuY29uZiA8PCdFT0YnCltJTlBVVF0KCU5hbWUgc3lzdGVtZAoJVGFnIGpvdXJuYWxkCglTeXN0ZW1kX0ZpbHRlciBfQ09NTT1hcm8KCURCIC92YXIvbGliL2ZsdWVudC9qb3VybmFsZGIKCltGSUxURVJdCglOYW1lIG1vZGlmeQoJTWF0Y2ggam91cm5hbGQKCVJlbW92ZV93aWxkY2FyZCBfCglSZW1vdmUgVElNRVNUQU1QCgpbRklMVEVSXQoJTmFtZSByZXdyaXRlX3RhZwoJTWF0Y2ggam91cm5hbGQKCVJ1bGUgJExPR0tJTkQgYXN5bmNxb3MgYXN5bmNxb3MgdHJ1ZQoKW0ZJTFRFUl0KCU5hbWUgbW9kaWZ5CglNYXRjaCBhc3luY3FvcwoJUmVtb3ZlIENMSUVOVF9QUklOQ0lQQUxfTkFNRQoJUmVtb3ZlIEZJTEUKCVJlbW92ZSBDT01QT05FTlQKCltGSUxURVJdCglOYW1lIHJld3JpdGVfdGFnCglNYXRjaCBqb3VybmFsZAoJUnVsZSAkTE9HS0lORCBpZnhhdWRpdCBpZnhhdWRpdCBmYWxzZQoKW09VVFBVVF0KCU5hbWUgZm9yd2FyZAoJTWF0Y2ggKgoJUG9ydCAyOTIzMApFT0YKCmVjaG8gIkZMVUVOVEJJVElNQUdFPSRGTFVFTlRCSVRJTUFHRSIgPi9ldGMvc3lzY29uZmlnL2ZsdWVudGJpdAoKY2F0ID4vZXRjL3N5c3RlbWQvc3lzdGVtL2ZsdWVudGJpdC5zZXJ2aWNlIDw8J0VPRicKW1VuaXRdCkFmdGVyPW5ldHdvcmstb25saW5lLnRhcmdldApXYW50cz1uZXR3b3JrLW9ubGluZS50YXJnZXQKU3RhcnRMaW1pdEludGVydmFsU2VjPTAKCltTZXJ2aWNlXQpSZXN0YXJ0U2VjPTFzCkVudmlyb25tZW50RmlsZT0vZXRjL3N5c2NvbmZpZy9mbHVlbnRiaXQKRXhlY1N0YXJ0UHJlPS0vdXNyL2Jpbi9kb2NrZXIgcm0gLWYgJU4KRXhlY1N0YXJ0PS91c3IvYmluL2RvY2tlciBydW4gXAogIC0tc2VjdXJpdHktb3B0IGxhYmVsPWRpc2FibGUgXAogIC0tZW50cnlwb2ludCAvb3B0L3RkLWFnZW50LWJpdC9iaW4vdGQtYWdlbnQtYml0IFwKICAtLW5ldD1ob3N0IFwKICAtLWhvc3RuYW1lICVIIFwKICAtLW5hbWUgJU4gXAogIC0tcm0gXAogIC0tY2FwLWRyb3AgbmV0X3JhdyBcCiAgLXYgL2V0Yy9mbHVlbnRiaXQvZmx1ZW50Yml0LmNvbmY6L2V0Yy9mbHVlbnRiaXQvZmx1ZW50Yml0LmNvbmYgXAogIC12IC92YXIvbGliL2ZsdWVudDovdmFyL2xpYi9mbHVlbnQ6eiBcCiAgLXYgL3Zhci9sb2cvam91cm5hbDovdmFyL2xvZy9qb3VybmFsOnJvIFwKICAtdiAvZXRjL21hY2hpbmUtaWQ6L2V0Yy9tYWNoaW5lLWlkOnJvIFwKICAkRkxVRU5UQklUSU1BR0UgXAogIC1jIC9ldGMvZmx1ZW50Yml0L2ZsdWVudGJpdC5jb25mCgpFeGVjU3RvcD0vdXNyL2Jpbi9kb2NrZXIgc3RvcCAlTgpSZXN0YXJ0PWFsd2F5cwpSZXN0YXJ0U2VjPTUKU3RhcnRMaW1pdEludGVydmFsPTAKCltJbnN0YWxsXQpXYW50ZWRCeT1tdWx0aS11c2VyLnRhcmdldApFT0YKCm1rZGlyIC9ldGMvYXJvLXJwCmJhc2U2NCAtZCA8PDwiJEFETUlOQVBJQ0FCVU5ETEUiID4vZXRjL2Fyby1ycC9hZG1pbi1jYS1idW5kbGUucGVtCmlmIFtbIC1uICIkQVJNQVBJQ0FCVU5ETEUiIF1dOyB0aGVuCiAgYmFzZTY0IC1kIDw8PCIkQVJNQVBJQ0FCVU5ETEUiID4vZXRjL2Fyby1ycC9hcm0tY2EtYnVuZGxlLnBlbQpmaQpjaG93biAtUiAxMDAwOjEwMDAgL2V0Yy9hcm8tcnAKCmVjaG8gImNvbmZpZ3VyaW5nIG1kbSBzZXJ2aWNlIgpjYXQgPi9ldGMvc3lzY29uZmlnL21kbSA8PEVPRgpNRE1GUk9OVEVORFVSTD0nJE1ETUZST05URU5EVVJMJwpNRE1JTUFHRT0nJE1ETUlNQUdFJwpNRE1TT1VSQ0VFTlZJUk9OTUVOVD0nJExPQ0FUSU9OJwpNRE1TT1VSQ0VST0xFPXJwCk1ETVNPVVJDRVJPTEVJTlNUQU5DRT0nJChob3N0bmFtZSknCkVPRgoKbWtkaXIgL3Zhci9ldHcKY2F0ID4vZXRjL3N5c3RlbWQvc3lzdGVtL21kbS5zZXJ2aWNlIDw8J0VPRicKW1VuaXRdCkFmdGVyPW5ldHdvcmstb25saW5lLnRhcmdldApXYW50cz1uZXR3b3JrLW9ubGluZS50YXJnZXQKCltTZXJ2aWNlXQpFbnZpcm9ubWVudEZpbGU9L2V0Yy9zeXNjb25maWcvbWRtCkV4ZWNTdGFydFByZT0tL3Vzci9iaW4vZG9ja2VyIHJtIC1mICVOCkV4ZWNTdGFydD0vdXNyL2Jpbi9kb2NrZXIgcnVuIFwKICAtLWVudHJ5cG9pbnQgL3Vzci9zYmluL01ldHJpY3NFeHRlbnNpb24gXAogIC0taG9zdG5hbWUgJUggXAogIC0tbmFtZSAlTiBcCiAgLS1ybSBcCiAgLS1jYXAtZHJvcCBuZXRfcmF3IFwKICAtbSAyZyBcCiAgLXYgL2V0Yy9tZG0ucGVtOi9ldGMvbWRtLnBlbSBcCiAgLXYgL3Zhci9ldHc6L3Zhci9ldHc6eiBcCiAgJE1ETUlNQUdFIFwKICAtQ2VydEZpbGUgL2V0Yy9tZG0ucGVtIFwKICAtRnJvbnRFbmRVcmwgJE1ETUZST05URU5EVVJMIFwKICAtTG9nZ2VyIENvbnNvbGUgXAogIC1Mb2dMZXZlbCBXYXJuaW5nIFwKICAtUHJpdmF0ZUtleUZpbGUgL2V0Yy9tZG0ucGVtIFwKICAtU291cmNlRW52aXJvbm1lbnQgJE1ETVNPVVJDRUVOVklST05NRU5UIFwKICAtU291cmNlUm9sZSAkTURNU09VUkNFUk9MRSBcCiAgLVNvdXJjZVJvbGVJbnN0YW5jZSAkTURNU09VUkNFUk9MRUlOU1RBTkNFCkV4ZWNTdG9wPS91c3IvYmluL2RvY2tlciBzdG9wICVOClJlc3RhcnQ9YWx3YXlzClJlc3RhcnRTZWM9MQpTdGFydExpbWl0SW50ZXJ2YWw9MAoKW0luc3RhbGxdCldhbnRlZEJ5PW11bHRpLXVzZXIudGFyZ2V0CkVPRgoKZWNobyAiY29uZmlndXJpbmcgYXJvLXJwIHNlcnZpY2UiCmNhdCA+L2V0Yy9zeXNjb25maWcvYXJvLXJwIDw8RU9GCkFDUl9SRVNPVVJDRV9JRD0nJEFDUlJFU09VUkNFSUQnCkFETUlOX0FQSV9DTElFTlRfQ0VSVF9DT01NT05fTkFNRT0nJEFETUlOQVBJQ0xJRU5UQ0VSVENPTU1PTk5BTUUnCkFSTV9BUElfQ0xJRU5UX0NFUlRfQ09NTU9OX05BTUU9JyRBUk1BUElDTElFTlRDRVJUQ09NTU9OTkFNRScKQVpVUkVfQVJNX0NMSUVOVF9JRD0nJEFSTUNMSUVOVElEJwpBWlVSRV9GUF9DTElFTlRfSUQ9JyRGUENMSUVOVElEJwpBWlVSRV9GUF9TRVJWSUNFX1BSSU5DSVBBTF9JRD0nJEZQU0VSVklDRVBSSU5DSVBBTElEJwpCSUxMSU5HX0UyRV9TVE9SQUdFX0FDQ09VTlRfSUQ9JyRCSUxMSU5HRTJFU1RPUkFHRUFDQ09VTlRJRCcKQ0xVU1RFUl9NRE1fQUNDT1VOVD0nJENMVVNURVJNRE1BQ0NPVU5UJwpDTFVTVEVSX01ETV9OQU1FU1BBQ0U9UlAKQ0xVU1RFUl9NRFNEX0FDQ09VTlQ9JyRDTFVTVEVSTURTREFDQ09VTlQnCkNMVVNURVJfTURTRF9DT05GSUdfVkVSU0lPTj0nJENMVVNURVJNRFNEQ09ORklHVkVSU0lPTicKQ0xVU1RFUl9NRFNEX05BTUVTUEFDRT0nJENMVVNURVJNRFNETkFNRVNQQUNFJwpEQVRBQkFTRV9BQ0NPVU5UX05BTUU9JyREQVRBQkFTRUFDQ09VTlROQU1FJwpET01BSU5fTkFNRT0nJExPQ0FUSU9OLiRDTFVTVEVSUEFSRU5URE9NQUlOTkFNRScKR0FURVdBWV9ET01BSU5TPSckR0FURVdBWURPTUFJTlMnCkdBVEVXQVlfUkVTT1VSQ0VHUk9VUD0nJEdBVEVXQVlSRVNPVVJDRUdST1VQTkFNRScKS0VZVkFVTFRfUFJFRklYPSckS0VZVkFVTFRQUkVGSVgnCk1ETV9BQ0NPVU5UPSckUlBNRE1BQ0NPVU5UJwpNRE1fTkFNRVNQQUNFPVJQCk1EU0RfRU5WSVJPTk1FTlQ9JyRNRFNERU5WSVJPTk1FTlQnClJQX0ZFQVRVUkVTPSckUlBGRUFUVVJFUycKUlBJTUFHRT0nJFJQSU1BR0UnCkFST19JTlNUQUxMX1ZJQV9ISVZFPSckQ0xVU1RFUlNJTlNUQUxMVklBSElWRScKQVJPX0hJVkVfREVGQVVMVF9JTlNUQUxMRVJfUFVMTFNQRUM9JyRDTFVTVEVSREVGQVVMVElOU1RBTExFUlBVTExTUEVDJwpBUk9fQURPUFRfQllfSElWRT0nJENMVVNURVJTQURPUFRCWUhJVkUnClVTRV9DSEVDS0FDQ0VTUz0nJFVTRUNIRUNLQUNDRVNTJwpFT0YKCmNhdCA+L2V0Yy9zeXN0ZW1kL3N5c3RlbS9hcm8tcnAuc2VydmljZSA8PCdFT0YnCltVbml0XQpBZnRlcj1uZXR3b3JrLW9ubGluZS50YXJnZXQKV2FudHM9bmV0d29yay1vbmxpbmUudGFyZ2V0CgpbU2VydmljZV0KRW52aXJvbm1lbnRGaWxlPS9ldGMvc3lzY29uZmlnL2Fyby1ycApFeGVjU3RhcnRQcmU9LS91c3IvYmluL2RvY2tlciBybSAtZiAlTgpFeGVjU3RhcnQ9L3Vzci9iaW4vZG9ja2VyIHJ1biBcCiAgLS1ob3N0bmFtZSAlSCBcCiAgLS1uYW1lICVOIFwKICAtLXJtIFwKICAtLWNhcC1kcm9wIG5ldF9yYXcgXAogIC1lIEFDUl9SRVNPVVJDRV9JRCBcCiAgLWUgQURNSU5fQVBJX0NMSUVOVF9DRVJUX0NPTU1PTl9OQU1FIFwKICAtZSBBUk1fQVBJX0NMSUVOVF9DRVJUX0NPTU1PTl9OQU1FIFwKICAtZSBBWlVSRV9BUk1fQ0xJRU5UX0lEIFwKICAtZSBBWlVSRV9GUF9DTElFTlRfSUQgXAogIC1lIEJJTExJTkdfRTJFX1NUT1JBR0VfQUNDT1VOVF9JRCBcCiAgLWUgQ0xVU1RFUl9NRE1fQUNDT1VOVCBcCiAgLWUgQ0xVU1RFUl9NRE1fTkFNRVNQQUNFIFwKICAtZSBDTFVTVEVSX01EU0RfQUNDT1VOVCBcCiAgLWUgQ0xVU1RFUl9NRFNEX0NPTkZJR19WRVJTSU9OIFwKICAtZSBDTFVTVEVSX01EU0RfTkFNRVNQQUNFIFwKICAtZSBEQVRBQkFTRV9BQ0NPVU5UX05BTUUgXAogIC1lIERPTUFJTl9OQU1FIFwKICAtZSBHQVRFV0FZX0RPTUFJTlMgXAogIC1lIEdBVEVXQVlfUkVTT1VSQ0VHUk9VUCBcCiAgLWUgS0VZVkFVTFRfUFJFRklYIFwKICAtZSBNRE1fQUNDT1VOVCBcCiAgLWUgTURNX05BTUVTUEFDRSBcCiAgLWUgTURTRF9FTlZJUk9OTUVOVCBcCiAgLWUgUlBfRkVBVFVSRVMgXAogIC1lIEFST19JTlNUQUxMX1ZJQV9ISVZFIFwKICAtZSBBUk9fSElWRV9ERUZBVUxUX0lOU1RBTExFUl9QVUxMU1BFQyBcCiAgLWUgQVJPX0FET1BUX0JZX0hJVkUgXAogIC1lIFVTRV9DSEVDS0FDQ0VTUyBcCiAgLW0gMmcgXAogIC1wIDQ0Mzo4NDQzIFwKICAtdiAvZXRjL2Fyby1ycDovZXRjL2Fyby1ycCBcCiAgLXYgL3J1bi9zeXN0ZW1kL2pvdXJuYWw6L3J1bi9zeXN0ZW1kL2pvdXJuYWwgXAogIC12IC92YXIvZXR3Oi92YXIvZXR3OnogXAogICRSUElNQUdFIFwKICBycApFeGVjU3RvcD0vdXNyL2Jpbi9kb2NrZXIgc3RvcCAtdCAzNjAwICVOClRpbWVvdXRTdG9wU2VjPTM2MDAKUmVzdGFydD1hbHdheXMKUmVzdGFydFNlYz0xClN0YXJ0TGltaXRJbnRlcnZhbD0wCgpbSW5zdGFsbF0KV2FudGVkQnk9bXVsdGktdXNlci50YXJnZXQKRU9GCgplY2hvICJjb25maWd1cmluZyBhcm8tZGJ0b2tlbiBzZXJ2aWNlIgpjYXQgPi9ldGMvc3lzY29uZmlnL2Fyby1kYnRva2VuIDw8RU9GCkRBVEFCQVNFX0FDQ09VTlRfTkFNRT0nJERBVEFCQVNFQUNDT1VOVE5BTUUnCkFaVVJFX0RCVE9LRU5fQ0xJRU5UX0lEPSckREJUT0tFTkNMSUVOVElEJwpBWlVSRV9HQVRFV0FZX1NFUlZJQ0VfUFJJTkNJUEFMX0lEPSckR0FURVdBWVNFUlZJQ0VQUklOQ0lQQUxJRCcKS0VZVkFVTFRfUFJFRklYPSckS0VZVkFVTFRQUkVGSVgnCk1ETV9BQ0NPVU5UPSckUlBNRE1BQ0NPVU5UJwpNRE1fTkFNRVNQQUNFPURCVG9rZW4KUlBJTUFHRT0nJFJQSU1BR0UnCkVPRgoKY2F0ID4vZXRjL3N5c3RlbWQvc3lzdGVtL2Fyby1kYnRva2VuLnNlcnZpY2UgPDwnRU9GJwpbVW5pdF0KQWZ0ZXI9bmV0d29yay1vbmxpbmUudGFyZ2V0CldhbnRzPW5ldHdvcmstb25saW5lLnRhcmdldAoKW1NlcnZpY2VdCkVudmlyb25tZW50RmlsZT0vZXRjL3N5c2NvbmZpZy9hcm8tZGJ0b2tlbgpFeGVjU3RhcnRQcmU9LS91c3IvYmluL2RvY2tlciBybSAtZiAlTgpFeGVjU3RhcnQ9L3Vzci9iaW4vZG9ja2VyIHJ1biBcCiAgLS1ob3N0bmFtZSAlSCBcCiAgLS1uYW1lICVOIFwKICAtLXJtIFwKICAtLWNhcC1kcm9wIG5ldF9yYXcgXAogIC1lIEFaVVJFX0dBVEVXQVlfU0VSVklDRV9QUklOQ0lQQUxfSUQgXAogIC1lIERBVEFCQVNFX0FDQ09VTlRfTkFNRSBcCiAgLWUgQVpVUkVfREJUT0tFTl9DTElFTlRfSUQgXAogIC1lIEtFWVZBVUxUX1BSRUZJWCBcCiAgLWUgTURNX0FDQ09VTlQgXAogIC1lIE1ETV9OQU1FU1BBQ0UgXAogIC1tIDJnIFwKICAtcCA0NDU6ODQ0NSBcCiAgLXYgL3J1bi9zeXN0ZW1kL2pvdXJuYWw6L3J1bi9zeXN0ZW1kL2pvdXJuYWwgXAogIC12IC92YXIvZXR3Oi92YXIvZXR3OnogXAogICRSUElNQUdFIFwKICBkYnRva2VuCkV4ZWNTdG9wPS91c3IvYmluL2RvY2tlciBzdG9wIC10IDM2MDAgJU4KVGltZW91dFN0b3BTZWM9MzYwMApSZXN0YXJ0PWFsd2F5cwpSZXN0YXJ0U2VjPTEKU3RhcnRMaW1pdEludGVydmFsPTAKCltJbnN0YWxsXQpXYW50ZWRCeT1tdWx0aS11c2VyLnRhcmdldApFT0YKCiMgRE9NQUlOX05BTUUsIENMVVNURVJfTURTRF9BQ0NPVU5ULCBDTFVTVEVSX01EU0RfQ09ORklHX1ZFUlNJT04sIEdBVEVXQVlfRE9NQUlOUywgR0FURVdBWV9SRVNPVVJDRUdST1VQLCBNRFNEX0VOVklST05NRU5UIENMVVNURVJfTURTRF9OQU1FU1BBQ0UKIyBhcmUgbm90IHVzZWQsIGJ1dCBjYW4ndCBlYXNpbHkgYmUgcmVmYWN0b3JlZCBvdXQuIFNob3VsZCBiZSByZXZpc2l0ZWQgaW4gdGhlIGZ1dHVyZS4KZWNobyAiY29uZmlndXJpbmcgYXJvLW1vbml0b3Igc2VydmljZSIKY2F0ID4vZXRjL3N5c2NvbmZpZy9hcm8tbW9uaXRvciA8PEVPRgpBWlVSRV9GUF9DTElFTlRfSUQ9JyRGUENMSUVOVElEJwpET01BSU5fTkFNRT0nJExPQ0FUSU9OLiRDTFVTVEVSUEFSRU5URE9NQUlOTkFNRScKQ0xVU1RFUl9NRFNEX0FDQ09VTlQ9JyRDTFVTVEVSTURTREFDQ09VTlQnCkNMVVNURVJfTURTRF9DT05GSUdfVkVSU0lPTj0nJENMVVNURVJNRFNEQ09ORklHVkVSU0lPTicKR0FURVdBWV9ET01BSU5TPSckR0FURVdBWURPTUFJTlMnCkdBVEVXQVlfUkVTT1VSQ0VHUk9VUD0nJEdBVEVXQVlSRVNPVVJDRUdST1VQTkFNRScKTURTRF9FTlZJUk9OTUVOVD0nJE1EU0RFTlZJUk9OTUVOVCcKQ0xVU1RFUl9NRFNEX05BTUVTUEFDRT0nJENMVVNURVJNRFNETkFNRVNQQUNFJwpDTFVTVEVSX01ETV9BQ0NPVU5UPSckQ0xVU1RFUk1ETUFDQ09VTlQnCkNMVVNURVJfTURNX05BTUVTUEFDRT1CQk0KREFUQUJBU0VfQUNDT1VOVF9OQU1FPSckREFUQUJBU0VBQ0NPVU5UTkFNRScKS0VZVkFVTFRfUFJFRklYPSckS0VZVkFVTFRQUkVGSVgnCk1ETV9BQ0NPVU5UPSckUlBNRE1BQ0NPVU5UJwpNRE1fTkFNRVNQQUNFPUJCTQpSUElNQUdFPSckUlBJTUFHRScKRU9GCgpjYXQgPi9ldGMvc3lzdGVtZC9zeXN0ZW0vYXJvLW1vbml0b3Iuc2VydmljZSA8PCdFT0YnCltVbml0XQpBZnRlcj1uZXR3b3JrLW9ubGluZS50YXJnZXQKV2FudHM9bmV0d29yay1vbmxpbmUudGFyZ2V0CgpbU2VydmljZV0KRW52aXJvbm1lbnRGaWxlPS9ldGMvc3lzY29uZmlnL2Fyby1tb25pdG9yCkV4ZWNTdGFydFByZT0tL3Vzci9iaW4vZG9ja2VyIHJtIC1mICVOCkV4ZWNTdGFydD0vdXNyL2Jpbi9kb2NrZXIgcnVuIFwKICAtLWhvc3RuYW1lICVIIFwKICAtLW5hbWUgJU4gXAogIC0tcm0gXAogIC0tY2FwLWRyb3AgbmV0X3JhdyBcCiAgLWUgQVpVUkVfRlBfQ0xJRU5UX0lEIFwKICAtZSBET01BSU5fTkFNRSBcCiAgLWUgQ0xVU1RFUl9NRFNEX0FDQ09VTlQgXAogIC1lIENMVVNURVJfTURTRF9DT05GSUdfVkVSU0lPTiBcCiAgLWUgR0FURVdBWV9ET01BSU5TIFwKICAtZSBHQVRFV0FZX1JFU09VUkNFR1JPVVAgXAogIC1lIE1EU0RfRU5WSVJPTk1FTlQgXAogIC1lIENMVVNURVJfTURTRF9OQU1FU1BBQ0UgXAogIC1lIENMVVNURVJfTURNX0FDQ09VTlQgXAogIC1lIENMVVNURVJfTURNX05BTUVTUEFDRSBcCiAgLWUgREFUQUJBU0VfQUNDT1VOVF9OQU1FIFwKICAtZSBLRVlWQVVMVF9QUkVGSVggXAogIC1lIE1ETV9BQ0NPVU5UIFwKICAtZSBNRE1fTkFNRVNQQUNFIFwKICAtbSAyLjVnIFwKICAtdiAvcnVuL3N5c3RlbWQvam91cm5hbDovcnVuL3N5c3RlbWQvam91cm5hbCBcCiAgLXYgL3Zhci9ldHc6L3Zhci9ldHc6eiBcCiAgJFJQSU1BR0UgXAogIG1vbml0b3IKUmVzdGFydD1hbHdheXMKUmVzdGFydFNlYz0xClN0YXJ0TGltaXRJbnRlcnZhbD0wCgpbSW5zdGFsbF0KV2FudGVkQnk9bXVsdGktdXNlci50YXJnZXQKRU9GCgplY2hvICJjb25maWd1cmluZyBhcm8tcG9ydGFsIHNlcnZpY2UiCmNhdCA+L2V0Yy9zeXNjb25maWcvYXJvLXBvcnRhbCA8PEVPRgpBWlVSRV9QT1JUQUxfQUNDRVNTX0dST1VQX0lEUz0nJFBPUlRBTEFDQ0VTU0dST1VQSURTJwpBWlVSRV9QT1JUQUxfQ0xJRU5UX0lEPSckUE9SVEFMQ0xJRU5USUQnCkFaVVJFX1BPUlRBTF9FTEVWQVRFRF9HUk9VUF9JRFM9JyRQT1JUQUxFTEVWQVRFREdST1VQSURTJwpEQVRBQkFTRV9BQ0NPVU5UX05BTUU9JyREQVRBQkFTRUFDQ09VTlROQU1FJwpLRVlWQVVMVF9QUkVGSVg9JyRLRVlWQVVMVFBSRUZJWCcKTURNX0FDQ09VTlQ9JyRSUE1ETUFDQ09VTlQnCk1ETV9OQU1FU1BBQ0U9UG9ydGFsClBPUlRBTF9IT1NUTkFNRT0nJExPQ0FUSU9OLmFkbWluLiRSUFBBUkVOVERPTUFJTk5BTUUnClJQSU1BR0U9JyRSUElNQUdFJwpFT0YKCmNhdCA+L2V0Yy9zeXN0ZW1kL3N5c3RlbS9hcm8tcG9ydGFsLnNlcnZpY2UgPDwnRU9GJwpbVW5pdF0KQWZ0ZXI9bmV0d29yay1vbmxpbmUudGFyZ2V0CldhbnRzPW5ldHdvcmstb25saW5lLnRhcmdldApTdGFydExpbWl0SW50ZXJ2YWw9MAoKW1NlcnZpY2VdCkVudmlyb25tZW50RmlsZT0vZXRjL3N5c2NvbmZpZy9hcm8tcG9ydGFsCkV4ZWNTdGFydFByZT0tL3Vzci9iaW4vZG9ja2VyIHJtIC1mICVOCkV4ZWNTdGFydD0vdXNyL2Jpbi9kb2NrZXIgcnVuIFwKICAtLWhvc3RuYW1lICVIIFwKICAtLW5hbWUgJU4gXAogIC0tcm0gXAogIC0tY2FwLWRyb3AgbmV0X3JhdyBcCiAgLWUgQVpVUkVfUE9SVEFMX0FDQ0VTU19HUk9VUF9JRFMgXAogIC1lIEFaVVJFX1BPUlRBTF9DTElFTlRfSUQgXAogIC1lIEFaVVJFX1BPUlRBTF9FTEVWQVRFRF9HUk9VUF9JRFMgXAogIC1lIERBVEFCQVNFX0FDQ09VTlRfTkFNRSBcCiAgLWUgS0VZVkFVTFRfUFJFRklYIFwKICAtZSBNRE1fQUNDT1VOVCBcCiAgLWUgTURNX05BTUVTUEFDRSBcCiAgLWUgUE9SVEFMX0hPU1ROQU1FIFwKICAtbSAyZyBcCiAgLXAgNDQ0Ojg0NDQgXAogIC1wIDIyMjI6MjIyMiBcCiAgLXYgL3J1bi9zeXN0ZW1kL2pvdXJuYWw6L3J1bi9zeXN0ZW1kL2pvdXJuYWwgXAogIC12IC92YXIvZXR3Oi92YXIvZXR3OnogXAogICRSUElNQUdFIFwKICBwb3J0YWwKUmVzdGFydD1hbHdheXMKUmVzdGFydFNlYz0xCgpbSW5zdGFsbF0KV2FudGVkQnk9bXVsdGktdXNlci50YXJnZXQKRU9GCgplY2hvICJjb25maWd1cmluZyBtZHNkIGFuZCBtZG0gc2VydmljZXMiCmNoY29uIC1SIHN5c3RlbV91Om9iamVjdF9yOnZhcl9sb2dfdDpzMCAvdmFyL29wdC9taWNyb3NvZnQvbGludXhtb25hZ2VudAoKbWtkaXIgLXAgL3Zhci9saWIvd2FhZ2VudC9NaWNyb3NvZnQuQXp1cmUuS2V5VmF1bHQuU3RvcmUKCmZvciB2YXIgaW4gIm1kc2QiICJtZG0iOyBkbwpjYXQgPi9ldGMvc3lzdGVtZC9zeXN0ZW0vZG93bmxvYWQtJHZhci1jcmVkZW50aWFscy5zZXJ2aWNlIDw8RU9GCltVbml0XQpEZXNjcmlwdGlvbj1QZXJpb2RpYyAkdmFyIGNyZWRlbnRpYWxzIHJlZnJlc2gKCltTZXJ2aWNlXQpUeXBlPW9uZXNob3QKRXhlY1N0YXJ0PS91c3IvbG9jYWwvYmluL2Rvd25sb2FkLWNyZWRlbnRpYWxzLnNoICR2YXIKRU9GCgpjYXQgPi9ldGMvc3lzdGVtZC9zeXN0ZW0vZG93bmxvYWQtJHZhci1jcmVkZW50aWFscy50aW1lciA8PEVPRgpbVW5pdF0KRGVzY3JpcHRpb249UGVyaW9kaWMgJHZhciBjcmVkZW50aWFscyByZWZyZXNoCkFmdGVyPW5ldHdvcmstb25saW5lLnRhcmdldApXYW50cz1uZXR3b3JrLW9ubGluZS50YXJnZXQKCltUaW1lcl0KT25Cb290U2VjPTBtaW4KT25DYWxlbmRhcj0wLzEyOjAwOjAwCkFjY3VyYWN5U2VjPTVzCgpbSW5zdGFsbF0KV2FudGVkQnk9dGltZXJzLnRhcmdldApFT0YKZG9uZQoKY2F0ID4vdXNyL2xvY2FsL2Jpbi9kb3dubG9hZC1jcmVkZW50aWFscy5zaCA8PEVPRgojIS9iaW4vYmFzaApzZXQgLWV1CgpDT01QT05FTlQ9IlwkMSIKZWNobyAiRG93bmxvYWQgXCRDT01QT05FTlQgY3JlZGVudGlhbHMiCgpURU1QX0RJUj1cJChta3RlbXAgLWQpCmV4cG9ydCBBWlVSRV9DT05GSUdfRElSPVwkKG1rdGVtcCAtZCkKCmVjaG8gIkxvZ2dpbmcgaW50byBBenVyZS4uLiIKUkVUUklFUz0zCndoaWxlIFsgIlwkUkVUUklFUyIgLWd0IDAgXTsgZG8KICAgIGlmIGF6IGxvZ2luIC1pIC0tYWxsb3ctbm8tc3Vic2NyaXB0aW9ucwogICAgdGhlbgogICAgICAgIGVjaG8gImF6IGxvZ2luIHN1Y2Nlc3NmdWwiCiAgICAgICAgYnJlYWsKICAgIGVsc2UKICAgICAgICBlY2hvICJheiBsb2dpbiBmYWlsZWQuIFJldHJ5aW5nLi4uIgogICAgICAgIGxldCBSRVRSSUVTLT0xCiAgICAgICAgc2xlZXAgNQogICAgZmkKZG9uZQoKdHJhcCAiY2xlYW51cCIgRVhJVAoKY2xlYW51cCgpIHsKICBheiBsb2dvdXQKICBbWyAiXCRURU1QX0RJUiIgPX4gL3RtcC8uKyBdXSAmJiBybSAtcmYgXCRURU1QX0RJUgogIFtbICJcJEFaVVJFX0NPTkZJR19ESVIiID1+IC90bXAvLisgXV0gJiYgcm0gLXJmIFwkQVpVUkVfQ09ORklHX0RJUgp9CgppZiBbICJcJENPTVBPTkVOVCIgPSAibWRtIiBdOyB0aGVuCiAgQ1VSUkVOVF9DRVJUX0ZJTEU9Ii9ldGMvbWRtLnBlbSIKZWxpZiBbICJcJENPTVBPTkVOVCIgPSAibWRzZCIgXTsgdGhlbgogIENVUlJFTlRfQ0VSVF9GSUxFPSIvdmFyL2xpYi93YWFnZW50L01pY3Jvc29mdC5BenVyZS5LZXlWYXVsdC5TdG9yZS9tZHNkLnBlbSIKZWxzZQogIGVjaG8gSW52YWxpZCB1c2FnZSAmJiBleGl0IDEKZmkKClNFQ1JFVF9OQU1FPSJycC1cJHtDT01QT05FTlR9IgpORVdfQ0VSVF9GSUxFPSJcJFRFTVBfRElSL1wkQ09NUE9ORU5ULnBlbSIKZm9yIGF0dGVtcHQgaW4gezEuLjV9OyBkbwogIGF6IGtleXZhdWx0IHNlY3JldCBkb3dubG9hZCAtLWZpbGUgXCRORVdfQ0VSVF9GSUxFIC0taWQgImh0dHBzOi8vJEtFWVZBVUxUUFJFRklYLXN2Yy4kS0VZVkFVTFRETlNTVUZGSVgvc2VjcmV0cy9cJFNFQ1JFVF9OQU1FIiAmJiBicmVhawogIGlmIFtbIFwkYXR0ZW1wdCAtbHQgNSBdXTsgdGhlbiBzbGVlcCAxMDsgZWxzZSBleGl0IDE7IGZpCmRvbmUKCmlmIFsgLWYgXCRORVdfQ0VSVF9GSUxFIF07IHRoZW4KICBpZiBbICJcJENPTVBPTkVOVCIgPSAibWRzZCIgXTsgdGhlbgogICAgY2hvd24gc3lzbG9nOnN5c2xvZyBcJE5FV19DRVJUX0ZJTEUKICBlbHNlCiAgICBzZWQgLWkgLW5lICcxLC9FTkQgQ0VSVElGSUNBVEUvIHAnIFwkTkVXX0NFUlRfRklMRQogIGZpCgogIG5ld19jZXJ0X3NuPSJcJChvcGVuc3NsIHg1MDkgLWluICJcJE5FV19DRVJUX0ZJTEUiIC1ub291dCAtc2VyaWFsIHwgYXdrIC1GPSAne3ByaW50IFwkMn0nKSIKICBjdXJyZW50X2NlcnRfc249IlwkKG9wZW5zc2wgeDUwOSAtaW4gIlwkQ1VSUkVOVF9DRVJUX0ZJTEUiIC1ub291dCAtc2VyaWFsIHwgYXdrIC1GPSAne3ByaW50IFwkMn0nKSIKICBpZiBbWyAhIC16IFwkbmV3X2NlcnRfc24gXV0gJiYgW1sgXCRuZXdfY2VydF9zbiAhPSAiXCRjdXJyZW50X2NlcnRfc24iIF1dOyB0aGVuCiAgICBlY2hvIHVwZGF0aW5nIGNlcnRpZmljYXRlIGZvciBcJENPTVBPTkVOVAogICAgY2htb2QgMDYwMCBcJE5FV19DRVJUX0ZJTEUKICAgIG12IFwkTkVXX0NFUlRfRklMRSBcJENVUlJFTlRfQ0VSVF9GSUxFCiAgZmkKZWxzZQogIGVjaG8gRmFpbGVkIHRvIHJlZnJlc2ggY2VydGlmaWNhdGUgZm9yIFwkQ09NUE9ORU5UICYmIGV4aXQgMQpmaQpFT0YKCmNobW9kIHUreCAvdXNyL2xvY2FsL2Jpbi9kb3dubG9hZC1jcmVkZW50aWFscy5zaAoKc3lzdGVtY3RsIGVuYWJsZSBkb3dubG9hZC1tZHNkLWNyZWRlbnRpYWxzLnRpbWVyCnN5c3RlbWN0bCBlbmFibGUgZG93bmxvYWQtbWRtLWNyZWRlbnRpYWxzLnRpbWVyCgovdXNyL2xvY2FsL2Jpbi9kb3dubG9hZC1jcmVkZW50aWFscy5zaCBtZHNkCi91c3IvbG9jYWwvYmluL2Rvd25sb2FkLWNyZWRlbnRpYWxzLnNoIG1kbQpNRFNEQ0VSVElGSUNBVEVTQU49JChvcGVuc3NsIHg1MDkgLWluIC92YXIvbGliL3dhYWdlbnQvTWljcm9zb2Z0LkF6dXJlLktleVZhdWx0LlN0b3JlL21kc2QucGVtIC1ub291dCAtc3ViamVjdCB8IHNlZCAtZSAncy8uKkNOID0gLy8nKQoKY2F0ID4vZXRjL3N5c3RlbWQvc3lzdGVtL3dhdGNoLW1kbS1jcmVkZW50aWFscy5zZXJ2aWNlIDw8RU9GCltVbml0XQpEZXNjcmlwdGlvbj1XYXRjaCBmb3IgY2hhbmdlcyBpbiBtZG0ucGVtIGFuZCByZXN0YXJ0cyB0aGUgbWRtIHNlcnZpY2UKCltTZXJ2aWNlXQpUeXBlPW9uZXNob3QKRXhlY1N0YXJ0PS91c3IvYmluL3N5c3RlbWN0bCByZXN0YXJ0IG1kbS5zZXJ2aWNlCgpbSW5zdGFsbF0KV2FudGVkQnk9bXVsdGktdXNlci50YXJnZXQKRU9GCgpjYXQgPi9ldGMvc3lzdGVtZC9zeXN0ZW0vd2F0Y2gtbWRtLWNyZWRlbnRpYWxzLnBhdGggPDxFT0YKW1BhdGhdClBhdGhNb2RpZmllZD0vZXRjL21kbS5wZW0KCltJbnN0YWxsXQpXYW50ZWRCeT1tdWx0aS11c2VyLnRhcmdldApFT0YKCnN5c3RlbWN0bCBlbmFibGUgd2F0Y2gtbWRtLWNyZWRlbnRpYWxzLnBhdGgKc3lzdGVtY3RsIHN0YXJ0IHdhdGNoLW1kbS1jcmVkZW50aWFscy5wYXRoCgpta2RpciAvZXRjL3N5c3RlbWQvc3lzdGVtL21kc2Quc2VydmljZS5kCmNhdCA+L2V0Yy9zeXN0ZW1kL3N5c3RlbS9tZHNkLnNlcnZpY2UuZC9vdmVycmlkZS5jb25mIDw8J0VPRicKW1VuaXRdCkFmdGVyPW5ldHdvcmstb25saW5lLnRhcmdldApFT0YKCmNhdCA+L2V0Yy9kZWZhdWx0L21kc2QgPDxFT0YKTURTRF9ST0xFX1BSRUZJWD0vdmFyL3J1bi9tZHNkL2RlZmF1bHQKTURTRF9PUFRJT05TPSItQSAtZCAtciBcJE1EU0RfUk9MRV9QUkVGSVgiCgpleHBvcnQgTU9OSVRPUklOR19HQ1NfRU5WSVJPTk1FTlQ9JyRNRFNERU5WSVJPTk1FTlQnCmV4cG9ydCBNT05JVE9SSU5HX0dDU19BQ0NPVU5UPSckUlBNRFNEQUNDT1VOVCcKZXhwb3J0IE1PTklUT1JJTkdfR0NTX1JFR0lPTj0nJExPQ0FUSU9OJwpleHBvcnQgTU9OSVRPUklOR19HQ1NfQVVUSF9JRF9UWVBFPUF1dGhLZXlWYXVsdApleHBvcnQgTU9OSVRPUklOR19HQ1NfQVVUSF9JRD0nJE1EU0RDRVJUSUZJQ0FURVNBTicKZXhwb3J0IE1PTklUT1JJTkdfR0NTX05BTUVTUEFDRT0nJFJQTURTRE5BTUVTUEFDRScKZXhwb3J0IE1PTklUT1JJTkdfQ09ORklHX1ZFUlNJT049JyRSUE1EU0RDT05GSUdWRVJTSU9OJwpleHBvcnQgTU9OSVRPUklOR19VU0VfR0VORVZBX0NPTkZJR19TRVJWSUNFPXRydWUKCmV4cG9ydCBNT05JVE9SSU5HX1RFTkFOVD0nJExPQ0FUSU9OJwpleHBvcnQgTU9OSVRPUklOR19ST0xFPXJwCmV4cG9ydCBNT05JVE9SSU5HX1JPTEVfSU5TVEFOQ0U9JyQoaG9zdG5hbWUpJwoKZXhwb3J0IE1EU0RfTVNHUEFDS19TT1JUX0NPTFVNTlM9MQpFT0YKCiMgc2V0dGluZyBNT05JVE9SSU5HX0dDU19BVVRIX0lEX1RZUEU9QXV0aEtleVZhdWx0IHNlZW1zIHRvIGhhdmUgY2F1c2VkIG1kc2Qgbm90CiMgdG8gaG9ub3VyIFNTTF9DRVJUX0ZJTEUgYW55IG1vcmUsIGhlYXZlbiBvbmx5IGtub3dzIHdoeS4KbWtkaXIgLXAgL3Vzci9saWIvc3NsL2NlcnRzCmNzcGxpdCAtZiAvdXNyL2xpYi9zc2wvY2VydHMvY2VydC0gLWIgJTAzZC5wZW0gL2V0Yy9wa2kvdGxzL2NlcnRzL2NhLWJ1bmRsZS5jcnQgL14kLzEgeyp9ID4vZGV2L251bGwKY19yZWhhc2ggL3Vzci9saWIvc3NsL2NlcnRzCgojIHdlIGxlYXZlIGNsaWVudElkIGJsYW5rIGFzIGxvbmcgYXMgb25seSAxIG1hbmFnZWQgaWRlbnRpdHkgYXNzaWduZWQgdG8gdm1zcwojIGlmIHdlIGhhdmUgbW9yZSB0aGFuIDEsIHdlIHdpbGwgbmVlZCB0byBwb3B1bGF0ZSB3aXRoIGNsaWVudElkIHVzZWQgZm9yIG9mZi1ub2RlIHNjYW5uaW5nCmNhdCA+L2V0Yy9kZWZhdWx0L3ZzYS1ub2Rlc2Nhbi1hZ2VudC5jb25maWcgPDxFT0YKewogICAgIk5pY2UiOiAxOSwKICAgICJUaW1lb3V0IjogMTA4MDAsCiAgICAiQ2xpZW50SWQiOiAiIiwKICAgICJUZW5hbnRJZCI6ICIkQVpVUkVTRUNQQUNLVlNBVEVOQU5USUQiLAogICAgIlF1YWx5c1N0b3JlQmFzZVVybCI6ICIkQVpVUkVTRUNQQUNLUVVBTFlTVVJMIiwKICAgICJQcm9jZXNzVGltZW91dCI6IDMwMCwKICAgICJDb21tYW5kRGVsYXkiOiAwCiAgfQpFT0YKCmVjaG8gImVuYWJsaW5nIGFybyBzZXJ2aWNlcyIKZm9yIHNlcnZpY2UgaW4gYXJvLWRidG9rZW4gYXJvLW1vbml0b3IgYXJvLXBvcnRhbCBhcm8tcnAgYXVvbXMgYXpzZWNkIGF6c2VjbW9uZCBtZHNkIG1kbSBjaHJvbnlkIGZsdWVudGJpdDsgZG8KICBzeXN0ZW1jdGwgZW5hYmxlICRzZXJ2aWNlLnNlcnZpY2UKZG9uZQoKZm9yIHNjYW4gaW4gYmFzZWxpbmUgY2xhbWF2IHNvZnR3YXJlOyBkbwogIC91c3IvbG9jYWwvYmluL2F6c2VjZCBjb25maWcgLXMgJHNjYW4gLWQgUDFECmRvbmUKCmVjaG8gInJlYm9vdGluZyIKcmVzdG9yZWNvbiAtUkYgL3Zhci9sb2cvKgooc2xlZXAgMzA7IHJlYm9vdCkgJgo=')))]" + "script": "[base64(concat(base64ToString('c2V0IC1leAoK'),'ACRRESOURCEID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('acrResourceId')),''')\n','ADMINAPICLIENTCERTCOMMONNAME=$(base64 -d \u003c\u003c\u003c''',base64(parameters('adminApiClientCertCommonName')),''')\n','ARMAPICLIENTCERTCOMMONNAME=$(base64 -d \u003c\u003c\u003c''',base64(parameters('armApiClientCertCommonName')),''')\n','ARMCLIENTID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('armClientId')),''')\n','AZURECLOUDNAME=$(base64 -d \u003c\u003c\u003c''',base64(parameters('azureCloudName')),''')\n','AZURESECPACKQUALYSURL=$(base64 -d \u003c\u003c\u003c''',base64(parameters('azureSecPackQualysUrl')),''')\n','AZURESECPACKVSATENANTID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('azureSecPackVSATenantId')),''')\n','BILLINGE2ESTORAGEACCOUNTID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('billingE2EStorageAccountId')),''')\n','CLUSTERMDMACCOUNT=$(base64 -d \u003c\u003c\u003c''',base64(parameters('clusterMdmAccount')),''')\n','CLUSTERMDSDACCOUNT=$(base64 -d \u003c\u003c\u003c''',base64(parameters('clusterMdsdAccount')),''')\n','CLUSTERMDSDCONFIGVERSION=$(base64 -d \u003c\u003c\u003c''',base64(parameters('clusterMdsdConfigVersion')),''')\n','CLUSTERMDSDNAMESPACE=$(base64 -d \u003c\u003c\u003c''',base64(parameters('clusterMdsdNamespace')),''')\n','CLUSTERPARENTDOMAINNAME=$(base64 -d \u003c\u003c\u003c''',base64(parameters('clusterParentDomainName')),''')\n','DATABASEACCOUNTNAME=$(base64 -d \u003c\u003c\u003c''',base64(parameters('databaseAccountName')),''')\n','DBTOKENCLIENTID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('dbtokenClientId')),''')\n','FLUENTBITIMAGE=$(base64 -d \u003c\u003c\u003c''',base64(parameters('fluentbitImage')),''')\n','FPCLIENTID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('fpClientId')),''')\n','FPSERVICEPRINCIPALID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('fpServicePrincipalId')),''')\n','GATEWAYDOMAINS=$(base64 -d \u003c\u003c\u003c''',base64(parameters('gatewayDomains')),''')\n','GATEWAYRESOURCEGROUPNAME=$(base64 -d \u003c\u003c\u003c''',base64(parameters('gatewayResourceGroupName')),''')\n','GATEWAYSERVICEPRINCIPALID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('gatewayServicePrincipalId')),''')\n','KEYVAULTDNSSUFFIX=$(base64 -d \u003c\u003c\u003c''',base64(parameters('keyvaultDNSSuffix')),''')\n','KEYVAULTPREFIX=$(base64 -d \u003c\u003c\u003c''',base64(parameters('keyvaultPrefix')),''')\n','MDMFRONTENDURL=$(base64 -d \u003c\u003c\u003c''',base64(parameters('mdmFrontendUrl')),''')\n','MDSDENVIRONMENT=$(base64 -d \u003c\u003c\u003c''',base64(parameters('mdsdEnvironment')),''')\n','PORTALACCESSGROUPIDS=$(base64 -d \u003c\u003c\u003c''',base64(parameters('portalAccessGroupIds')),''')\n','PORTALCLIENTID=$(base64 -d \u003c\u003c\u003c''',base64(parameters('portalClientId')),''')\n','PORTALELEVATEDGROUPIDS=$(base64 -d \u003c\u003c\u003c''',base64(parameters('portalElevatedGroupIds')),''')\n','RPFEATURES=$(base64 -d \u003c\u003c\u003c''',base64(parameters('rpFeatures')),''')\n','RPIMAGE=$(base64 -d \u003c\u003c\u003c''',base64(parameters('rpImage')),''')\n','RPMDMACCOUNT=$(base64 -d \u003c\u003c\u003c''',base64(parameters('rpMdmAccount')),''')\n','RPMDSDACCOUNT=$(base64 -d \u003c\u003c\u003c''',base64(parameters('rpMdsdAccount')),''')\n','RPMDSDCONFIGVERSION=$(base64 -d \u003c\u003c\u003c''',base64(parameters('rpMdsdConfigVersion')),''')\n','RPMDSDNAMESPACE=$(base64 -d \u003c\u003c\u003c''',base64(parameters('rpMdsdNamespace')),''')\n','RPPARENTDOMAINNAME=$(base64 -d \u003c\u003c\u003c''',base64(parameters('rpParentDomainName')),''')\n','CLUSTERSINSTALLVIAHIVE=$(base64 -d \u003c\u003c\u003c''',base64(parameters('clustersInstallViaHive')),''')\n','CLUSTERSADOPTBYHIVE=$(base64 -d \u003c\u003c\u003c''',base64(parameters('clustersAdoptByHive')),''')\n','CLUSTERDEFAULTINSTALLERPULLSPEC=$(base64 -d \u003c\u003c\u003c''',base64(parameters('clusterDefaultInstallerPullspec')),''')\n','USECHECKACCESS=$(base64 -d \u003c\u003c\u003c''',base64(parameters('useCheckAccess')),''')\n','ADMINAPICABUNDLE=''',parameters('adminApiCaBundle'),'''\n','ARMAPICABUNDLE=''',parameters('armApiCaBundle'),'''\n','MDMIMAGE=''/genevamdm:2.2024.328.1744-c5fb79-20240328t1935''\n','LOCATION=$(base64 -d \u003c\u003c\u003c''',base64(resourceGroup().location),''')\n','SUBSCRIPTIONID=$(base64 -d \u003c\u003c\u003c''',base64(subscription().subscriptionId),''')\n','RESOURCEGROUPNAME=$(base64 -d \u003c\u003c\u003c''',base64(resourceGroup().name),''')\n','\n',base64ToString('IyEvYmluL2Jhc2gKCnNldCAtbyBlcnJleGl0IFwKICAgIC1vIG5vdW5zZXQKCmlmIFsgIiR7REVCVUc6LWZhbHNlfSIgPT0gdHJ1ZSBdOyB0aGVuCiAgICBzZXQgLXgKZmkKCm1haW4oKSB7CiAgICBwYXJzZV9ydW5fb3B0aW9ucyAiJEAiCgoKICAgIGNvbmZpZ3VyZV9zc2hkCiAgICBjb25maWd1cmVfYW5kX2luc3RhbGxfZG5mX3BrZ3NfcmVwb3MKICAgIGNvbmZpZ3VyZV9kaXNrX3BhcnRpdGlvbnMKICAgIGNvbmZpZ3VyZV9sb2dyb3RhdGUKICAgIGNvbmZpZ3VyZV9zZWxpbnV4CgogICAgbWtkaXIgLXAgL3Zhci9sb2cvam91cm5hbAogICAgbWtkaXIgLXAgL3Zhci9saWIvd2FhZ2VudC9NaWNyb3NvZnQuQXp1cmUuS2V5VmF1bHQuU3RvcmUKCiAgICBjb25maWd1cmVfZmlyZXdhbGxkX3J1bGVzCiAgICBwdWxsX2NvbnRhaW5lcl9pbWFnZXMKICAgIGNvbmZpZ3VyZV9zeXN0ZW1fc2VydmljZXMKICAgIHJlYm9vdF92bQp9Cgp1c2FnZSgpIHsKICAgIGxvY2FsIC1uIG9wdGlvbnM9IiQxIgogICAgbG9nICIkKGJhc2VuYW1lICIkMCIpIFskb3B0aW9uc10KICAgICAgICAtZCBDb25maWd1cmUgRGlzayBQYXJ0aXRpb25zCiAgICAgICAgLXAgQ29uZmlndXJlIHJwbSByZXBvc2l0b3JpZXMsIGltcG9ydCByZXF1aXJlZCBycG0ga2V5cywgdXBkYXRlICYgaW5zdGFsbCBwYWNrYWdlcyB3aXRoIGRuZgogICAgICAgIC1sIENvbmZpZ3VyZSBsb2dyb3RhdGUuY29uZgogICAgICAgIC1zIE1ha2Ugc2VsaW51eCBtb2RpZmljYXRpb25zIHJlcXVpcmVkIGZvciBBUk8gUlAKICAgICAgICAtciBDb25maWd1cmUgc3NoZCAtIEFsbG93IHBhc3N3b3JkIGF1dGhlbnRpY2FpdG9uCiAgICAgICAgLWYgQ29uZmlndXJlIGZpcmV3YWxsZCBkZWZhdWx0IHpvbmUgcnVsZXMKICAgICAgICAtdSBDb25maWd1cmUgc3lzdGVtZCB1bml0IGZpbGVzIGZvciBBUk8gUlAKICAgICAgICAtaSBQdWxsIGNvbnRhaW5lciBpbWFnZXMKCiAgICAgICAgTm90ZTogc3RlcHMgd2lsbCBiZSBleGVjdXRlZCBpbiB0aGUgb3JkZXIgdGhhdCBmbGFncyBhcmUgcHJvdmlkZWQKICAgICIKfQoKIyBwYXJzZV9ydW5fb3B0aW9ucyB0YWtlcyBhbGwgYXJndWVtZW50cyBwYXNzZWQgdG8gbWFpbiBhbmQgcGFyc2VzIHRoZW0KIyBhbGxvd2luZyBpbmRpdmlkdWFsIHN0ZXAocykgdG8gYmUgcmFuLCByYXRoZXIgdGhhbiBhbGwgc3RlcHMKIwojIFRoaXMgaXMgdXNlZnVsIGZvciBsb2NhbCB0ZXN0aW5nLCBvciBwb3NzaWJseSBtb2RpZnlpbmcgdGhlIGJvb3RzdHJhcCBleGVjdXRpb24gdmlhIGVudmlyb25tZW50IHZhcmlhYmxlcyBpbiB0aGUgZGVwbG95bWVudCBwaXBlbGluZQpwYXJzZV9ydW5fb3B0aW9ucygpIHsKICAgICMgc2hlbGxjaGVjayBkaXNhYmxlPVNDMjIwNgogICAgbG9jYWwgLWEgb3B0aW9ucz0oJHsxOi19KQogICAgaWYgWyAiJHsjb3B0aW9uc1tAXX0iIC1lcSAwIF07IHRoZW4KICAgICAgICBsb2cgIlJ1bm5pbmcgYWxsIHN0ZXBzIgogICAgICAgIHJldHVybiAwCiAgICBmaQoKICAgIGxvY2FsIE9QVElORAogICAgbG9jYWwgLXIgYWxsb3dlZF9vcHRpb25zPSJkcGxzcmZ1aSIKICAgIHdoaWxlIGdldG9wdHMgJHthbGxvd2VkX29wdGlvbnN9IG9wdGlvbnM7IGRvCiAgICAgICAgY2FzZSAiJHtvcHRpb25zfSIgaW4KICAgICAgICAgICAgZCkKICAgICAgICAgICAgICAgIGxvZyAiUnVubmluZyBzdGVwIGNvbmZpZ3VyZV9kaXNrX3BhcnRpdGlvbnMiCiAgICAgICAgICAgICAgICBjb25maWd1cmVfZGlza19wYXJ0aXRpb25zCiAgICAgICAgICAgICAgICA7OwogICAgICAgICAgICBwKQogICAgICAgICAgICAgICAgbG9nICJSdW5uaW5nIHN0ZXAgY29uZmlndXJlX2FuZF9pbnN0YWxsX2RuZl9wa2dzX3JlcG9zIgogICAgICAgICAgICAgICAgY29uZmlndXJlX2FuZF9pbnN0YWxsX2RuZl9wa2dzX3JlcG9zCiAgICAgICAgICAgICAgICA7OwogICAgICAgICAgICBsKQogICAgICAgICAgICAgICAgbG9nICJSdW5uaW5nIGNvbmZpZ3VyZV9sb2dyb3RhdGUiCiAgICAgICAgICAgICAgICBjb25maWd1cmVfbG9ncm90YXRlCiAgICAgICAgICAgICAgICA7OwogICAgICAgICAgICBzKQogICAgICAgICAgICAgICAgbG9nICJSdW5uaW5nIGNvbmZpZ3VyZV9zZWxpbnV4IgogICAgICAgICAgICAgICAgY29uZmlndXJlX3NlbGludXgKICAgICAgICAgICAgICAgIDs7CiAgICAgICAgICAgIHIpCiAgICAgICAgICAgICAgICBsb2cgIlJ1bm5pbmcgY29uZmlndXJlX3NzaGQiCiAgICAgICAgICAgICAgICBjb25maWd1cmVfc3NoZAogICAgICAgICAgICAgICAgOzsKICAgICAgICAgICAgZikKICAgICAgICAgICAgICAgIGxvZyAiUnVubmluZyBjb25maWd1cmVfZmlyZXdhbGxkX3J1bGVzIgogICAgICAgICAgICAgICAgY29uZmlndXJlX2ZpcmV3YWxsZF9ydWxlcwogICAgICAgICAgICAgICAgOzsKICAgICAgICAgICAgdSkKICAgICAgICAgICAgICAgIGxvZyAiUnVubmluZyBwdWxsX2NvbnRhaW5lcl9pbWFnZXMgJiBjb25maWd1cmVfc3lzdGVtX3NlcnZpY2VzIgogICAgICAgICAgICAgICAgY29uZmlndXJlX3N5c3RlbV9zZXJ2aWNlcwogICAgICAgICAgICAgICAgOzsKICAgICAgICAgICAgaSkKICAgICAgICAgICAgICAgIGxvZyAiUnVubmluZyBwdWxsX2NvbnRhaW5lcl9pbWFnZXMiCiAgICAgICAgICAgICAgICBwdWxsX2NvbnRhaW5lcl9pbWFnZXMgCiAgICAgICAgICAgICAgICA7OwogICAgICAgICAgICAqKQogICAgICAgICAgICAgICAgdXNhZ2UgYWxsb3dlZF9vcHRpb25zCiAgICAgICAgICAgICAgICBhYm9ydCAiVW5rb3duIG9wdGlvbiBwcm92aWRlZCIKICAgICAgICAgICAgICAgIDs7CiAgICAgICAgZXNhYwogICAgZG9uZQogICAgCiAgICBleGl0IDAKfQoKIyBXZSBuZWVkIHRvIGNvbmZpZ3VyZSBQYXNzd29yZEF1dGhlbnRpY2F0aW9uIHRvIHllcyBpbiBvcmRlciBmb3IgdGhlIFZNU1MgQWNjZXNzIEpJVCB0byB3b3JrCmNvbmZpZ3VyZV9zc2hkKCkgewogICAgbG9nICJzdGFydGluZyIKICAgIGxvZyAic2V0dGluZyBzc2ggcGFzc3dvcmQgYXV0aGVudGljYXRpb24iCiAgICBzZWQgLWkgJ3MvUGFzc3dvcmRBdXRoZW50aWNhdGlvbiBuby9QYXNzd29yZEF1dGhlbnRpY2F0aW9uIHllcy9nJyAvZXRjL3NzaC9zc2hkX2NvbmZpZwoKICAgIHN5c3RlbWN0bCByZWxvYWQgc3NoZC5zZXJ2aWNlCiAgICBzeXN0ZW1jdGwgaXMtYWN0aXZlIC0tcXVpZXQgc3NoZCB8fCBhYm9ydCAic3NoZCBmYWlsZWQgdG8gcmVsb2FkIgp9CgojIGNvbmZpZ3VyZV9hbmRfaW5zdGFsbF9kbmZfcGtnc19yZXBvcwpjb25maWd1cmVfYW5kX2luc3RhbGxfZG5mX3BrZ3NfcmVwb3MoKSB7CiAgICBsb2cgInN0YXJ0aW5nIgoKICAgICMgdHJhbnNhY3Rpb24gYXR0ZW1wdCByZXRyeSB0aW1lIGluIHNlY29uZHMKICAgIGxvY2FsIC1yaSByZXRyeV93YWl0X3RpbWU9NjAKICAgIGNvbmZpZ3VyZV9yaHVpX3JlcG8gcmV0cnlfd2FpdF90aW1lCiAgICBjcmVhdGVfYXp1cmVfcnBtX3JlcG9zIHJldHJ5X3dhaXRfdGltZQoKICAgIGxvY2FsIC1hciBleGNsdWRlX3BrZ3M9KAogICAgICAgICIteCBXQUxpbnV4QWdlbnQiCiAgICAgICAgIi14IFdBTGludXhBZ2VudC11ZGV2IgogICAgKQoKICAgIGRuZl91cGRhdGVfcGtncyBleGNsdWRlX3BrZ3MgcmV0cnlfd2FpdF90aW1lCgogICAgbG9jYWwgLXJhIHJwbV9rZXlzPSgKICAgICAgICBodHRwczovL2RsLmZlZG9yYXByb2plY3Qub3JnL3B1Yi9lcGVsL1JQTS1HUEctS0VZLUVQRUwtOAogICAgICAgIGh0dHBzOi8vcGFja2FnZXMubWljcm9zb2Z0LmNvbS9rZXlzL21pY3Jvc29mdC5hc2MKICAgICkKCiAgICBycG1faW1wb3J0X2tleXMgcnBtX2tleXMgcmV0cnlfd2FpdF90aW1lCgogICAgbG9jYWwgLXJhIHJlcG9fcnBtX3BrZ3M9KAogICAgICAgIGh0dHBzOi8vZGwuZmVkb3JhcHJvamVjdC5vcmcvcHViL2VwZWwvZXBlbC1yZWxlYXNlLWxhdGVzdC04Lm5vYXJjaC5ycG0KICAgICkKCiAgICBsb2NhbCAtcmEgaW5zdGFsbF9wa2dzPSgKICAgICAgICBjbGFtYXYKICAgICAgICBhenNlYy1jbGFtYXYKICAgICAgICBhenNlYy1tb25pdG9yCiAgICAgICAgYXp1cmUtY2xpCiAgICAgICAgYXp1cmUtbWRzZAogICAgICAgIGF6dXJlLXNlY3VyaXR5CiAgICAgICAgcG9kbWFuCiAgICAgICAgcG9kbWFuLWRvY2tlcgogICAgICAgIG9wZW5zc2wtcGVybAogICAgICAgICMgaGFjayAtIHdlIGFyZSBpbnN0YWxsaW5nIHB5dGhvbjMgb24gaG9zdHMgZHVlIHRvIGFuIGlzc3VlIHdpdGggQXp1cmUgTGludXggRXh0ZW5zaW9ucyBodHRwczovL2dpdGh1Yi5jb20vQXp1cmUvYXp1cmUtbGludXgtZXh0ZW5zaW9ucy9wdWxsLzE1MDUKICAgICAgICBweXRob24zCiAgICApCgogICAgZG5mX2luc3RhbGxfcGtncyByZXBvX3JwbV9wa2dzIHJldHJ5X3dhaXRfdGltZQogICAgZG5mX2luc3RhbGxfcGtncyBpbnN0YWxsX3BrZ3MgcmV0cnlfd2FpdF90aW1lCn0KCiMgY29uZmlndXJlX3JodWlfcmVwbwpjb25maWd1cmVfcmh1aV9yZXBvKCkgewogICAgbG9nICJzdGFydGluZyIKCiAgICBsb2NhbCAtcmEgY21kPSgKICAgICAgICBkbmYKICAgICAgICB1cGRhdGUKICAgICAgICAteQogICAgICAgIC0tZGlzYWJsZXJlcG89JyonCiAgICAgICAgLS1lbmFibGVyZXBvPSdyaHVpLW1pY3Jvc29mdC1henVyZSonCiAgICApCgogICAgbG9nICJydW5uaW5nIFJIVUkgcGFja2FnZSB1cGRhdGVzIgogICAgcmV0cnkgY21kICIkMSIKfQoKIyByZXRyeSBBZGRpbmcgcmV0cnkgbG9naWMgdG8geXVtIGNvbW1hbmRzIGluIG9yZGVyIHRvIGF2b2lkIHN0YWxsaW5nIG91dCBvbiByZXNvdXJjZSBsb2NrcwpyZXRyeSgpIHsKICAgIGxvY2FsIC1uIGNtZF9yZXRyeT0iJDEiCiAgICBsb2NhbCAtbiB3YWl0X3RpbWU9IiQyIgoKICAgIGZvciBhdHRlbXB0IGluIHsxLi41fTsgZG8KICAgICAgICBsb2cgImF0dGVtcHQgIyR7YXR0ZW1wdH0gLSAke0ZVTkNOQU1FWzJdfSIKICAgICAgICAke2NtZF9yZXRyeVtAXX0gJgoKICAgICAgICB3YWl0ICQhICYmIGJyZWFrCiAgICAgICAgaWYgW1sgJHthdHRlbXB0fSAtbHQgNSBdXTsgdGhlbgogICAgICAgICAgICBzbGVlcCAiJHdhaXRfdGltZSIKICAgICAgICBlbHNlCiAgICAgICAgICAgIGFib3J0ICJhdHRlbXB0ICMke2F0dGVtcHR9IC0gRmFpbGVkIHRvIHVwZGF0ZSBwYWNrYWdlcyIKICAgICAgICBmaQogICAgZG9uZQp9CgojIGRuZl91cGRhdGVfcGtncwpkbmZfdXBkYXRlX3BrZ3MoKSB7CiAgICBsb2NhbCAtbiBleGNsdWRlcz0iJDEiCiAgICBsb2cgInN0YXJ0aW5nIgoKICAgIGxvY2FsIC1yYSBjbWQ9KAogICAgICAgIGRuZgogICAgICAgIC15CiAgICAgICAgJHtleGNsdWRlc1tAXX0KICAgICAgICB1cGRhdGUKICAgICAgICAtLWFsbG93ZXJhc2luZwogICAgKQoKICAgIGxvZyAiVXBkYXRpbmcgYWxsIHBhY2thZ2VzIgogICAgcmV0cnkgY21kICIkMiIKfQoKIyBkbmZfaW5zdGFsbF9wa2dzCmRuZl9pbnN0YWxsX3BrZ3MoKSB7CiAgICBsb2NhbCAtbiBwa2dzPSIkMSIKICAgIGxvZyAic3RhcnRpbmciCgogICAgbG9jYWwgLXJhIGNtZD0oCiAgICAgICAgZG5mCiAgICAgICAgLXkKICAgICAgICBpbnN0YWxsCiAgICAgICAgJHtwa2dzW0BdfQogICAgKQoKICAgIGxvZyAiQXR0ZW1wdGluZyB0byBpbnN0YWxsIHBhY2thZ2VzOiAke3BrZ3NbKl19IgogICAgcmV0cnkgY21kICIkMiIKfQoKIyBycG1faW1wb3J0X2tleXMKcnBtX2ltcG9ydF9rZXlzKCkgewogICAgbG9jYWwgLW4ga2V5cz0iJDEiCiAgICBsb2cgInN0YXJ0aW5nIgoKCiAgICAjIHNoZWxsY2hlY2sgZGlzYWJsZT1TQzIwNjgKICAgIGZvciBrZXkgaW4gJHtrZXlzW0BdfTsgZG8KICAgICAgICBpZiBbICR7I2tleXNbQF19IC1lcSAwIF07IHRoZW4KICAgICAgICAgICAgYnJlYWsKICAgICAgICBmaQogICAgICAgICAgICBsb2NhbCAtYSBjbWQ9KAogICAgICAgICAgICAgICAgcnBtCiAgICAgICAgICAgICAgICAtLWltcG9ydAogICAgICAgICAgICAgICAgLXYKICAgICAgICAgICAgICAgICIka2V5IgogICAgICAgICAgICApCgogICAgICAgICAgICBsb2cgImF0dGVtcHQgIyRhdHRlbXB0IC0gaW1wb3J0aW5nIHJwbSByZXBvc2l0b3J5IGtleSAka2V5IgogICAgICAgICAgICByZXRyeSBjbWQgIiQyIiAmJiB1bnNldCBrZXkKICAgIGRvbmUKfQoKIyBjb25maWd1cmVfZGlza19wYXJ0aXRpb25zCmNvbmZpZ3VyZV9kaXNrX3BhcnRpdGlvbnMoKSB7CiAgICBsb2cgInN0YXJ0aW5nIgogICAgbG9nICJleHRlbmRpbmcgcGFydGl0aW9uIHRhYmxlIgoKICAgICMgTGludXggYmxvY2sgZGV2aWNlcyBhcmUgaW5jb25zaXN0ZW50bHkgbmFtZWQKICAgICMgaXQncyBkaWZmaWN1bHQgdG8gdGllIHRoZSBsdm0gcHYgdG8gdGhlIHBoeXNpY2FsIGRpc2sgdXNpbmcgL2Rldi9kaXNrIGZpbGVzLCB3aGljaCBpcyB3aHkgbHZzIGlzIHVzZWQgaGVyZQogICAgcGh5c2ljYWxfZGlzaz0iJChsdnMgLW8gZGV2aWNlcyAtYSB8IGhlYWQgLW4yIHwgdGFpbCAtbjEgfCBjdXQgLWQgJyAnIC1mIDMgfCBjdXQgLWQgXCggLWYgMSB8IHRyIC1kICdbOmRpZ2l0Ol0nKSIKICAgIGdyb3dwYXJ0ICIkcGh5c2ljYWxfZGlzayIgMgoKICAgIGxvZyAiZXh0ZW5kaW5nIGZpbGVzeXN0ZW1zIgogICAgbG9nICJleHRlbmRpbmcgcm9vdCBsdm0iCiAgICBsdmV4dGVuZCAtbCArMjAlRlJFRSAvZGV2L3Jvb3R2Zy9yb290bHYKICAgIGxvZyAiZ3Jvd2luZyByb290IGZpbGVzeXN0ZW0iCiAgICB4ZnNfZ3Jvd2ZzIC8KCiAgICBsb2cgImV4dGVuZGluZyB2YXIgbHZtIgogICAgbHZleHRlbmQgLWwgKzEwMCVGUkVFIC9kZXYvcm9vdHZnL3Zhcmx2CiAgICBsb2cgImdyb3dpbmcgdmFyIGZpbGVzeXN0ZW0iCiAgICB4ZnNfZ3Jvd2ZzIC92YXIKfQoKIyBjb25maWd1cmVfbG9ncm90YXRlIGNsb2JiZXJzIC9ldGMvbG9ncm90YXRlLmNvbmYKY29uZmlndXJlX2xvZ3JvdGF0ZSgpIHsKICAgIGxvZyAic3RhcnRpbmciCgogICAgbG9jYWwgLXIgbG9ncm90YXRlX2NvbmZfZmlsZW5hbWU9Jy9ldGMvbG9ncm90YXRlLmNvbmYnCiAgICBsb2NhbCAtciBsb2dyb3RhdGVfY29uZl9maWxlPScjIHNlZSAibWFuIGxvZ3JvdGF0ZSIgZm9yIGRldGFpbHMKIyByb3RhdGUgbG9nIGZpbGVzIHdlZWtseQp3ZWVrbHkKCiMga2VlcCAyIHdlZWtzIHdvcnRoIG9mIGJhY2tsb2dzCnJvdGF0ZSAyCgojIGNyZWF0ZSBuZXcgKGVtcHR5KSBsb2cgZmlsZXMgYWZ0ZXIgcm90YXRpbmcgb2xkIG9uZXMKY3JlYXRlCgojIHVzZSBkYXRlIGFzIGEgc3VmZml4IG9mIHRoZSByb3RhdGVkIGZpbGUKZGF0ZWV4dAoKIyB1bmNvbW1lbnQgdGhpcyBpZiB5b3Ugd2FudCB5b3VyIGxvZyBmaWxlcyBjb21wcmVzc2VkCmNvbXByZXNzCgojIFJQTSBwYWNrYWdlcyBkcm9wIGxvZyByb3RhdGlvbiBpbmZvcm1hdGlvbiBpbnRvIHRoaXMgZGlyZWN0b3J5CmluY2x1ZGUgL2V0Yy9sb2dyb3RhdGUuZAoKIyBubyBwYWNrYWdlcyBvd24gd3RtcCBhbmQgYnRtcCAtLSB3ZSB3aWxsIHJvdGF0ZSB0aGVtIGhlcmUKL3Zhci9sb2cvd3RtcCB7CiAgICBtb250aGx5CiAgICBjcmVhdGUgMDY2NCByb290IHV0bXAKICAgICAgICBtaW5zaXplIDFNCiAgICByb3RhdGUgMQp9CgovdmFyL2xvZy9idG1wIHsKICAgIG1pc3NpbmdvawogICAgbW9udGhseQogICAgY3JlYXRlIDA2MDAgcm9vdCB1dG1wCiAgICByb3RhdGUgMQp9JwoKICAgIHdyaXRlX2ZpbGUgbG9ncm90YXRlX2NvbmZfZmlsZW5hbWUgbG9ncm90YXRlX2NvbmZfZmlsZSB0cnVlCn0KCiMgY3JlYXRlX2F6dXJlX3JwbV9yZXBvcyBjcmVhdGVzIC9ldGMveXVtLnJlcG9zLmQvYXp1cmUucmVwbyByZXBvc2l0b3J5IGZpbGUKY3JlYXRlX2F6dXJlX3JwbV9yZXBvcygpIHsKICAgIGxvZyAic3RhcnRpbmciCgogICAgbG9jYWwgLXIgYXp1cmVfcmVwb19maWxlbmFtZT0nL2V0Yy95dW0ucmVwb3MuZC9henVyZS5yZXBvJwogICAgbG9jYWwgLXIgYXp1cmVfcmVwb19maWxlPSdbYXp1cmUtY2xpXQpuYW1lPWF6dXJlLWNsaQpiYXNldXJsPWh0dHBzOi8vcGFja2FnZXMubWljcm9zb2Z0LmNvbS95dW1yZXBvcy9henVyZS1jbGkKZW5hYmxlZD15ZXMKZ3BnY2hlY2s9eWVzCgpbYXp1cmVjb3JlXQpuYW1lPWF6dXJlY29yZQpiYXNldXJsPWh0dHBzOi8vcGFja2FnZXMubWljcm9zb2Z0LmNvbS95dW1yZXBvcy9henVyZWNvcmUKZW5hYmxlZD15ZXMKZ3BnY2hlY2s9bm8nCgogICAgd3JpdGVfZmlsZSBhenVyZV9yZXBvX2ZpbGVuYW1lIGF6dXJlX3JlcG9fZmlsZSB0cnVlCn0KCiMgY29uZmlndXJlX3NlbGludXgKY29uZmlndXJlX3NlbGludXgoKSB7CiAgICBsb2cgInN0YXJ0aW5nIgoKICAgIGxvY2FsIC1yIHJlbGFiZWw9IiR7MTotZmFsc2V9IgoKICAgIGFscmVhZHlfZGVmaW5lZF9pZ25vcmVfZXJyb3I9IkZpbGUgY29udGV4dCBmb3IgL3Zhci9sb2cvam91cm5hbCgvLiopPyBhbHJlYWR5IGRlZmluZWQiCiAgICBzZW1hbmFnZSBmY29udGV4dCAtYSAtdCB2YXJfbG9nX3QgIi92YXIvbG9nL2pvdXJuYWwoLy4qKT8iIHx8IGxvZyAiJGFscmVhZHlfZGVmaW5lZF9pZ25vcmVfZXJyb3IiCiAgICBjaGNvbiAtUiBzeXN0ZW1fdTpvYmplY3Rfcjp2YXJfbG9nX3Q6czAgL3Zhci9vcHQvbWljcm9zb2Z0L2xpbnV4bW9uYWdlbnQKCiAgICBpZiAiJHJlbGFiZWwiOyB0aGVuCiAgICAgICAgcmVzdG9yZWNvbiAtUkYgL3Zhci9sb2cvKiB8fCBsb2cgIiRhbHJlYWR5X2RlZmluZWRfaWdub3JlX2Vycm9yIgogICAgZmkKfQoKIyBjb25maWd1cmVfZmlyZXdhbGxkX3J1bGVzCmNvbmZpZ3VyZV9maXJld2FsbGRfcnVsZXMoKSB7CiAgICBsb2cgInN0YXJ0aW5nIgoKICAgICMgaHR0cHM6Ly9hY2Nlc3MucmVkaGF0LmNvbS9zZWN1cml0eS9jdmUvY3ZlLTIwMjAtMTM0MDEKICAgIGxvY2FsIC1yIHByZWZpeD0iL2V0Yy9zeXNjdGwuZCIKICAgIGxvY2FsIC1yIGRpc2FibGVfYWNjZXB0X3JhX2NvbmZfZmlsZW5hbWU9IiRwcmVmaXgvMDItZGlzYWJsZS1hY2NlcHQtcmEuY29uZiIKICAgIGxvY2FsIC1yIGRpc2FibGVfYWNjZXB0X3JhX2NvbmZfZmlsZT0ibmV0LmlwdjYuY29uZi5hbGwuYWNjZXB0X3JhPTAiCgogICAgd3JpdGVfZmlsZSBkaXNhYmxlX2FjY2VwdF9yYV9jb25mX2ZpbGVuYW1lIGRpc2FibGVfYWNjZXB0X3JhX2NvbmZfZmlsZSB0cnVlCgogICAgbG9jYWwgLXIgZGlzYWJsZV9jb3JlX2ZpbGVuYW1lPSIkcHJlZml4LzAxLWRpc2FibGUtY29yZS5jb25mIgogICAgbG9jYWwgLXIgZGlzYWJsZV9jb3JlX2ZpbGU9Imtlcm5lbC5jb3JlX3BhdHRlcm4gPSB8L2Jpbi90cnVlCiAgICAiCiAgICB3cml0ZV9maWxlIGRpc2FibGVfY29yZV9maWxlbmFtZSBkaXNhYmxlX2NvcmVfZmlsZSB0cnVlCgogICAgc3lzY3RsIC0tc3lzdGVtCgogICAgbG9jYWwgLXJhIGVuYWJsZV9wb3J0cz0oCiAgICAgICAgIjQ0My90Y3AiCiAgICAgICAgIjQ0NC90Y3AiCiAgICAgICAgIjQ0NS90Y3AiCiAgICAgICAgIjIyMjIvdGNwIgogICAgKQoKICAgIGxvZyAiRW5hYmxpbmcgcG9ydHMgJHtlbmFibGVfcG9ydHNbKl19IG9uIGRlZmF1bHQgZmlyZXdhbGxkIHpvbmUiCiAgICAjIHNoZWxsY2hlY2sgZGlzYWJsZT1TQzIwNjgKICAgIGZvciBwb3J0IGluICR7ZW5hYmxlX3BvcnRzW0BdfTsgZG8KICAgICAgICBsb2cgIkVuYWJsaW5nIHBvcnQgJHBvcnQgbm93IgogICAgICAgIGZpcmV3YWxsLWNtZCAiLS1hZGQtcG9ydD0kcG9ydCIKICAgIGRvbmUKCiAgICBmaXJld2FsbC1jbWQgLS1ydW50aW1lLXRvLXBlcm1hbmVudAp9CgojIHB1bGxfY29udGFpbmVyX2ltYWdlcwpwdWxsX2NvbnRhaW5lcl9pbWFnZXMoKSB7CiAgICBsb2cgInN0YXJ0aW5nIgoKICAgICMgVGhlIG1hbmFnZWQgaWRlbnRpdHkgdGhhdCB0aGUgVk0gcnVucyBhcyBvbmx5IGhhcyBhIHNpbmdsZSByb2xlYXNzaWdubWVudC4KICAgICMgVGhpcyByb2xlIGFzc2lnbm1lbnQgaXMgQUNSUHVsbCB3aGljaCBpcyBub3QgbmVjZXNzYXJpbHkgcHJlc2VudCBpbiB0aGUKICAgICMgc3Vic2NyaXB0aW9uIHdlJ3JlIGRlcGxveWluZyBpbnRvLiAgSWYgdGhlIGlkZW50aXR5IGRvZXMgbm90IGhhdmUgYW55CiAgICAjIHJvbGUgYXNzaWdubWVudHMgc2NvcGVkIG9uIHRoZSBzdWJzY3JpcHRpb24gd2UncmUgZGVwbG95aW5nIGludG8sIGl0IHdpbGwKICAgICMgbm90IHNob3cgb24gYXogbG9naW4gLWksIHdoaWNoIGlzIHdoeSB0aGUgYmVsb3cgbGluZSBpcyBjb21tZW50ZWQuCiAgICAjIGF6IGFjY291bnQgc2V0IC1zICIkU1VCU0NSSVBUSU9OSUQiCiAgICBheiBsb2dpbiAtaSAtLWFsbG93LW5vLXN1YnNjcmlwdGlvbnMKCiAgICAjIFN1cHByZXNzIGVtdWxhdGlvbiBvdXRwdXQgZm9yIHBvZG1hbiBpbnN0ZWFkIG9mIGRvY2tlciBmb3IgYXogYWNyIGNvbXBhdGFiaWxpdHkKICAgIG1rZGlyIC1wIC9ldGMvY29udGFpbmVycy8KICAgIG1rZGlyIC1wIC9yb290Ly5kb2NrZXIKICAgIHRvdWNoIC9ldGMvY29udGFpbmVycy9ub2RvY2tlcgoKCSMgVGhpcyBuYW1lIGlzIHVzZWQgaW4gdGhlIGNhc2UgdGhhdCBheiBhY3IgbG9naW4gc2VhcmNoZXMgZm9yIHRoaXMgaW4gaXQncyBlbnZpcm9ubWVudAogICAgbG9jYWwgLXIgUkVHSVNUUllfQVVUSF9GSUxFPSIvcm9vdC8uZG9ja2VyL2NvbmZpZy5qc29uIgogICAgCiAgICBsb2cgImxvZ2dpbmcgaW50byBwcm9kIGFjciIKICAgIGF6IGFjciBsb2dpbiAtLW5hbWUgIiQoc2VkIC1lICdzfC4qL3x8JyA8PDwiJEFDUlJFU09VUkNFSUQiKSIKCiAgICBNRE1JTUFHRT0iJHtSUElNQUdFJSUvKn0vJHtNRE1JTUFHRSMjKi99IgogICAgZG9ja2VyIHB1bGwgIiRNRE1JTUFHRSIKICAgIGRvY2tlciBwdWxsICIkUlBJTUFHRSIKICAgIGRvY2tlciBwdWxsICIkRkxVRU5UQklUSU1BR0UiCgogICAgYXogbG9nb3V0Cn0KCiMgY29uZmlndXJlX3N5c3RlbV9zZXJ2aWNlcyBjcmVhdGVzLCBjb25maWd1cmVzLCBhbmQgZW5hYmxlcyB0aGUgZm9sbG93aW5nIHN5c3RlbWQgc2VydmljZXMgYW5kIHRpbWVycwojIHNlcnZpY2VzCiMgICBmbHVlbnRiaXQKIyAgIG1kbQojICAgbWRzZAojICAgYXJwLXJwCiMgICBhcm8tZGJ0b2tlbgojICAgYXJvLW1vbml0b3IKIyAgIGFyby1wb3J0YWwKY29uZmlndXJlX3N5c3RlbV9zZXJ2aWNlcygpIHsKICAgIGNvbmZpZ3VyZV9zZXJ2aWNlX2ZsdWVudGJpdAogICAgY29uZmlndXJlX3NlcnZpY2VfbWRtCiAgICBjb25maWd1cmVfdGltZXJzX21kbV9tZHNkCiAgICBjb25maWd1cmVfc2VydmljZV9hcm9fcnAKICAgIGNvbmZpZ3VyZV9zZXJ2aWNlX2Fyb19kYnRva2VuCiAgICBjb25maWd1cmVfc2VydmljZV9hcm9fbW9uaXRvcgogICAgY29uZmlndXJlX3NlcnZpY2VfYXJvX3BvcnRhbAogICAgY29uZmlndXJlX3NlcnZpY2VfbWRzZAp9CgojIGVuYWJsZV9hcm9fc2VydmljZXMgZW5hYmxlcyBhbGwgc2VydmljZXMgcmVxdWlyZWQgZm9yIGFybyBycAplbmFibGVfYXJvX3NlcnZpY2VzKCkgewogICAgbG9nICJzdGFydGluZyIKCiAgICBsb2NhbCAtcmEgYXJvX3NlcnZpY2VzPSgKICAgICAgICAiYXJvLWRidG9rZW4iCiAgICAgICAgImFyby1tb25pdG9yIgogICAgICAgICJhcm8tcG9ydGFsIgogICAgICAgICJhcm8tcnAiCiAgICAgICAgImF1b21zIgogICAgICAgICJhenNlY2QiCiAgICAgICAgImF6c2VjbW9uZCIKICAgICAgICAibWRzZCIKICAgICAgICAibWRtIgogICAgICAgICJjaHJvbnlkIgogICAgICAgICJmbHVlbnRiaXQiCiAgICApCiAgICBsb2cgImVuYWJsaW5nIGFybyBzZXJ2aWNlcyAke2Fyb19zZXJ2aWNlc1sqXX0iCiAgICAjIHNoZWxsY2hlY2sgZGlzYWJsZT1TQzIwNjgKICAgIGZvciBzZXJ2aWNlIGluICR7YXJvX3NlcnZpY2VzW0BdfTsgZG8KICAgICAgICBsb2cgIkVuYWJsaW5nICRzZXJ2aWNlIG5vdyIKICAgICAgICBzeXN0ZW1jdGwgZW5hYmxlICIkc2VydmljZS5zZXJ2aWNlIgogICAgZG9uZQp9CgojIGNvbmZpZ3VyZV9zZXJ2aWNlX2ZsdWVudGJpdApjb25maWd1cmVfc2VydmljZV9mbHVlbnRiaXQoKSB7CiAgICBsb2cgInN0YXJ0aW5nIgogICAgbG9nICJjb25maWd1cmluZyBmbHVlbnRiaXQgc2VydmljZSIKCiAgICBta2RpciAtcCAvZXRjL2ZsdWVudGJpdC8KICAgIG1rZGlyIC1wIC92YXIvbGliL2ZsdWVudAoKICAgIGxvY2FsIC1yIGZsdWVudGJpdF9jb25mX2ZpbGVuYW1lPScvZXRjL2ZsdWVudGJpdC9mbHVlbnRiaXQuY29uZicKICAgIGxvY2FsIC1yIGZsdWVudGJpdF9jb25mX2ZpbGU9IltJTlBVVF0KTmFtZSBzeXN0ZW1kClRhZyBqb3VybmFsZApTeXN0ZW1kX0ZpbHRlciBfQ09NTT1hcm8KREIgL3Zhci9saWIvZmx1ZW50L2pvdXJuYWxkYgoKW0ZJTFRFUl0KCU5hbWUgbW9kaWZ5CglNYXRjaCBqb3VybmFsZAoJUmVtb3ZlX3dpbGRjYXJkIF8KCVJlbW92ZSBUSU1FU1RBTVAKCltGSUxURVJdCglOYW1lIHJld3JpdGVfdGFnCglNYXRjaCBqb3VybmFsZAoJUnVsZSAkTE9HS0lORCBhc3luY3FvcyBhc3luY3FvcyB0cnVlCgpbRklMVEVSXQoJTmFtZSBtb2RpZnkKCU1hdGNoIGFzeW5jcW9zCglSZW1vdmUgQ0xJRU5UX1BSSU5DSVBBTF9OQU1FCglSZW1vdmUgRklMRQoJUmVtb3ZlIENPTVBPTkVOVAoKW0ZJTFRFUl0KCU5hbWUgcmV3cml0ZV90YWcKCU1hdGNoIGpvdXJuYWxkCglSdWxlICRMT0dLSU5EIGlmeGF1ZGl0IGlmeGF1ZGl0IGZhbHNlCgpbT1VUUFVUXQoJTmFtZSBmb3J3YXJkCglNYXRjaCAqCglQb3J0IDI5MjMwIgoKICAgIHdyaXRlX2ZpbGUgZmx1ZW50Yml0X2NvbmZfZmlsZW5hbWUgZmx1ZW50Yml0X2NvbmZfZmlsZSB0cnVlCgogICAgbG9jYWwgLXIgc3lzY29uZmlnX2ZsdWVudGJpdF9maWxlbmFtZT0nL2V0Yy9zeXNjb25maWcvZmx1ZW50Yml0JwogICAgbG9jYWwgLXIgc3lzY29uZmlnX2ZsdWVudGJpdF9maWxlPSJGTFVFTlRCSVRJTUFHRT0kRkxVRU5UQklUSU1BR0UiCgogICAgd3JpdGVfZmlsZSBzeXNjb25maWdfZmx1ZW50Yml0X2ZpbGVuYW1lIHN5c2NvbmZpZ19mbHVlbnRiaXRfZmlsZSB0cnVlCgogICAgbG9jYWwgLXIgZmx1ZW50Yml0X3NlcnZpY2VfZmlsZW5hbWU9Jy9ldGMvc3lzdGVtZC9zeXN0ZW0vZmx1ZW50Yml0LnNlcnZpY2UnCgogICAgbG9jYWwgLXIgZmx1ZW50Yml0X3NlcnZpY2VfZmlsZT0iW1VuaXRdCkFmdGVyPW5ldHdvcmstb25saW5lLnRhcmdldApXYW50cz1uZXR3b3JrLW9ubGluZS50YXJnZXQKU3RhcnRMaW1pdEludGVydmFsU2VjPTAKCltTZXJ2aWNlXQpSZXN0YXJ0U2VjPTFzCkVudmlyb25tZW50RmlsZT0vZXRjL3N5c2NvbmZpZy9mbHVlbnRiaXQKRXhlY1N0YXJ0UHJlPS0vdXNyL2Jpbi9kb2NrZXIgcm0gLWYgJU4KRXhlY1N0YXJ0PS91c3IvYmluL2RvY2tlciBydW4gXAogIC0tc2VjdXJpdHktb3B0IGxhYmVsPWRpc2FibGUgXAogIC0tZW50cnlwb2ludCAvb3B0L3RkLWFnZW50LWJpdC9iaW4vdGQtYWdlbnQtYml0IFwKICAtLW5ldD1ob3N0IFwKICAtLWhvc3RuYW1lICVIIFwKICAtLW5hbWUgJU4gXAogIC0tcm0gXAogIC0tY2FwLWRyb3AgbmV0X3JhdyBcCiAgLXYgL2V0Yy9mbHVlbnRiaXQvZmx1ZW50Yml0LmNvbmY6L2V0Yy9mbHVlbnRiaXQvZmx1ZW50Yml0LmNvbmYgXAogIC12IC92YXIvbGliL2ZsdWVudDovdmFyL2xpYi9mbHVlbnQ6eiBcCiAgLXYgL3Zhci9sb2cvam91cm5hbDovdmFyL2xvZy9qb3VybmFsOnJvIFwKICAtdiAvZXRjL21hY2hpbmUtaWQ6L2V0Yy9tYWNoaW5lLWlkOnJvIFwKICAkRkxVRU5UQklUSU1BR0UgXAogIC1jIC9ldGMvZmx1ZW50Yml0L2ZsdWVudGJpdC5jb25mCgpFeGVjU3RvcD0vdXNyL2Jpbi9kb2NrZXIgc3RvcCAlTgpSZXN0YXJ0PWFsd2F5cwpSZXN0YXJ0U2VjPTUKU3RhcnRMaW1pdEludGVydmFsPTAKCltJbnN0YWxsXQpXYW50ZWRCeT1tdWx0aS11c2VyLnRhcmdldCIKCiAgICB3cml0ZV9maWxlIGZsdWVudGJpdF9jb25mX2ZpbGVuYW1lIGZsdWVudGJpdF9jb25mX2ZpbGUgdHJ1ZQp9CgojIGNvbmZpZ3VyZV9jZXJ0cwpjb25maWd1cmVfY2VydHMoKSB7CiAgICBsb2cgInN0YXJ0aW5nIgoKICAgIG1rZGlyIC9ldGMvYXJvLXJwCiAgICBiYXNlNjQgLWQgPDw8IiRBRE1JTkFQSUNBQlVORExFIiA+L2V0Yy9hcm8tcnAvYWRtaW4tY2EtYnVuZGxlLnBlbQogICAgaWYgW1sgLW4gIiRBUk1BUElDQUJVTkRMRSIgXV07IHRoZW4KICAgIGJhc2U2NCAtZCA8PDwiJEFSTUFQSUNBQlVORExFIiA+L2V0Yy9hcm8tcnAvYXJtLWNhLWJ1bmRsZS5wZW0KICAgIGZpCiAgICBjaG93biAtUiAxMDAwOjEwMDAgL2V0Yy9hcm8tcnAKCiAgICAjIHNldHRpbmcgTU9OSVRPUklOR19HQ1NfQVVUSF9JRF9UWVBFPUF1dGhLZXlWYXVsdCBzZWVtcyB0byBoYXZlIGNhdXNlZCBtZHNkIG5vdAogICAgIyB0byBob25vdXIgU1NMX0NFUlRfRklMRSBhbnkgbW9yZSwgaGVhdmVuIG9ubHkga25vd3Mgd2h5LgogICAgbWtkaXIgLXAgL3Vzci9saWIvc3NsL2NlcnRzCiAgICBjc3BsaXQgLWYgL3Vzci9saWIvc3NsL2NlcnRzL2NlcnQtIC1iICUwM2QucGVtIC9ldGMvcGtpL3Rscy9jZXJ0cy9jYS1idW5kbGUuY3J0IC9eJC8xICJ7Kn0iID4vZGV2L251bGwKICAgIGNfcmVoYXNoIC91c3IvbGliL3NzbC9jZXJ0cwoKIyB3ZSBsZWF2ZSBjbGllbnRJZCBibGFuayBhcyBsb25nIGFzIG9ubHkgMSBtYW5hZ2VkIGlkZW50aXR5IGFzc2lnbmVkIHRvIHZtc3MKIyBpZiB3ZSBoYXZlIG1vcmUgdGhhbiAxLCB3ZSB3aWxsIG5lZWQgdG8gcG9wdWxhdGUgd2l0aCBjbGllbnRJZCB1c2VkIGZvciBvZmYtbm9kZSBzY2FubmluZwogICAgbG9jYWwgLXIgbm9kZXNjYW5fYWdlbnRfZmlsZW5hbWU9Ii9ldGMvZGVmYXVsdC92c2Etbm9kZXNjYW4tYWdlbnQuY29uZmlnIgogICAgbG9jYWwgLXIgbm9kZXNjYW5fYWdlbnRfZmlsZT0iewogICAgXCJOaWNlXCI6IDE5LAogICAgXCJUaW1lb3V0XCI6IDEwODAwLAogICAgXCJDbGllbnRJZFwiOiBcIlwiLAogICAgXCJUZW5hbnRJZFwiOiAkQVpVUkVTRUNQQUNLVlNBVEVOQU5USUQsCiAgICBcIlF1YWx5c1N0b3JlQmFzZVVybFwiOiAkQVpVUkVTRUNQQUNLUVVBTFlTVVJMLAogICAgXCJQcm9jZXNzVGltZW91dFwiOiAzMDAsCiAgICBcIkNvbW1hbmREZWxheVwiOiAwCiAgfSIKCiAgICB3cml0ZV9maWxlIG5vZGVzY2FuX2FnZW50X2ZpbGVuYW1lIG5vZGVzY2FuX2FnZW50X2ZpbGUgdHJ1ZQp9CgojIGNvbmZpZ3VyZV9zZXJ2aWNlX21kbQpjb25maWd1cmVfc2VydmljZV9tZG0oKSB7CiAgICBsb2cgInN0YXJ0aW5nIgogICAgbG9nICJjb25maWd1cmluZyBtZG0gc2VydmljZSIKCiAgICBsb2NhbCAtciBzeXNjb25maWdfbWRtX2ZpbGVuYW1lPSIvZXRjL3N5c2NvbmZpZy9tZG0iCiAgICBsb2NhbCAtciBzeXNjb25maWdfbWRtX2ZpbGU9Ik1ETUZST05URU5EVVJMPSckTURNRlJPTlRFTkRVUkwnCk1ETUlNQUdFPSckTURNSU1BR0UnCk1ETVNPVVJDRUVOVklST05NRU5UPSckTE9DQVRJT04nCk1ETVNPVVJDRVJPTEU9cnAKTURNU09VUkNFUk9MRUlOU1RBTkNFPVwiJChob3N0bmFtZSlcIiIKCiAgICB3cml0ZV9maWxlIHN5c2NvbmZpZ19tZG1fZmlsZW5hbWUgc3lzY29uZmlnX21kbV9maWxlIHRydWUKCiAgICBta2RpciAtcCAvdmFyL2V0dwogICAgbG9jYWwgLXIgbWRtX3NlcnZpY2VfZmlsZW5hbWU9Ii9ldGMvc3lzdGVtZC9zeXN0ZW0vbWRtLnNlcnZpY2UiCiAgICBsb2NhbCAtciBtZG1fc2VydmljZV9maWxlPSJbVW5pdF0KQWZ0ZXI9bmV0d29yay1vbmxpbmUudGFyZ2V0CldhbnRzPW5ldHdvcmstb25saW5lLnRhcmdldAoKW1NlcnZpY2VdCkVudmlyb25tZW50RmlsZT0vZXRjL3N5c2NvbmZpZy9tZG0KRXhlY1N0YXJ0UHJlPS0vdXNyL2Jpbi9kb2NrZXIgcm0gLWYgJU4KRXhlY1N0YXJ0PS91c3IvYmluL2RvY2tlciBydW4gXAogIC0tZW50cnlwb2ludCAvdXNyL3NiaW4vTWV0cmljc0V4dGVuc2lvbiBcCiAgLS1ob3N0bmFtZSAlSCBcCiAgLS1uYW1lICVOIFwKICAtLXJtIFwKICAtLWNhcC1kcm9wIG5ldF9yYXcgXAogIC1tIDJnIFwKICAtdiAvZXRjL21kbS5wZW06L2V0Yy9tZG0ucGVtIFwKICAtdiAvdmFyL2V0dzovdmFyL2V0dzp6IFwKICAkTURNSU1BR0UgXAogIC1DZXJ0RmlsZSAvZXRjL21kbS5wZW0gXAogIC1Gcm9udEVuZFVybCAkTURNRlJPTlRFTkRVUkwgXAogIC1Mb2dnZXIgQ29uc29sZSBcCiAgLUxvZ0xldmVsIFdhcm5pbmcgXAogIC1Qcml2YXRlS2V5RmlsZSAvZXRjL21kbS5wZW0gXAogIC1Tb3VyY2VFbnZpcm9ubWVudCAkTURNU09VUkNFRU5WSVJPTk1FTlQgXAogIC1Tb3VyY2VSb2xlICRNRE1TT1VSQ0VST0xFIFwKICAtU291cmNlUm9sZUluc3RhbmNlICRNRE1TT1VSQ0VST0xFSU5TVEFOQ0UKRXhlY1N0b3A9L3Vzci9iaW4vZG9ja2VyIHN0b3AgJU4KUmVzdGFydD1hbHdheXMKUmVzdGFydFNlYz0xClN0YXJ0TGltaXRJbnRlcnZhbD0wCgpbSW5zdGFsbF0KV2FudGVkQnk9bXVsdGktdXNlci50YXJnZXQiCgogICAgd3JpdGVfZmlsZSBtZG1fc2VydmljZV9maWxlbmFtZSBtZG1fc2VydmljZV9maWxlIHRydWUKfQoKIyBjb25maWd1cmVfdGltZXJzX21kbV9tZHNkCmNvbmZpZ3VyZV90aW1lcnNfbWRtX21kc2QoKSB7CiAgICBsb2cgInN0YXJ0aW5nIgoKICAgIGZvciB2YXIgaW4gIm1kc2QiICJtZG0iOyBkbwogICAgICAgIGxvY2FsIGRvd25sb2FkX2NyZWRzX3NlcnZpY2VfZmlsZW5hbWU9Ii9ldGMvc3lzdGVtZC9zeXN0ZW0vZG93bmxvYWQtJHZhci1jcmVkZW50aWFscy5zZXJ2aWNlIgogICAgICAgIGxvY2FsIGRvd25sb2FkX2NyZWRzX3NlcnZpY2VfZmlsZT0iW1VuaXRdCkRlc2NyaXB0aW9uPVBlcmlvZGljICR2YXIgY3JlZGVudGlhbHMgcmVmcmVzaAoKW1NlcnZpY2VdClR5cGU9b25lc2hvdApFeGVjU3RhcnQ9L3Vzci9sb2NhbC9iaW4vZG93bmxvYWQtY3JlZGVudGlhbHMuc2ggJHZhciIKCiAgICAgICAgd3JpdGVfZmlsZSBkb3dubG9hZF9jcmVkc19zZXJ2aWNlX2ZpbGVuYW1lIGRvd25sb2FkX2NyZWRzX3NlcnZpY2VfZmlsZSB0cnVlCgogICAgICAgIGxvY2FsIGRvd25sb2FkX2NyZWRzX3RpbWVyX2ZpbGVuYW1lPSIvZXRjL3N5c3RlbWQvc3lzdGVtL2Rvd25sb2FkLSR2YXItY3JlZGVudGlhbHMudGltZXIiCiAgICAgICAgbG9jYWwgZG93bmxvYWRfY3JlZHNfdGltZXJfZmlsZT0iW1VuaXRdCkRlc2NyaXB0aW9uPVBlcmlvZGljICR2YXIgY3JlZGVudGlhbHMgcmVmcmVzaApBZnRlcj1uZXR3b3JrLW9ubGluZS50YXJnZXQKV2FudHM9bmV0d29yay1vbmxpbmUudGFyZ2V0CgpbVGltZXJdCk9uQm9vdFNlYz0wbWluCk9uQ2FsZW5kYXI9MC8xMjowMDowMApBY2N1cmFjeVNlYz01cwoKW0luc3RhbGxdCldhbnRlZEJ5PXRpbWVycy50YXJnZXQiCgogICAgICAgIHdyaXRlX2ZpbGUgZG93bmxvYWRfY3JlZHNfdGltZXJfZmlsZW5hbWUgZG93bmxvYWRfY3JlZHNfdGltZXJfZmlsZSB0cnVlCiAgICBkb25lCgogICAgbG9jYWwgLXIgZG93bmxvYWRfY3JlZHNfc2NyaXB0X2ZpbGVuYW1lPSIvdXNyL2xvY2FsL2Jpbi9kb3dubG9hZC1jcmVkZW50aWFscy5zaCIKICAgIGxvY2FsIC1yIGRvd25sb2FkX2NyZWRzX3NjcmlwdF9maWxlPSIjIS9iaW4vYmFzaApzZXQgLWV1CgpDT01QT05FTlQ9XCQxCmVjaG8gXCJEb3dubG9hZCBcJENPTVBPTkVOVCBjcmVkZW50aWFsc1wiCgpURU1QX0RJUj1cIlwkKG1rdGVtcCAtZClcIgpleHBvcnQgQVpVUkVfQ09ORklHX0RJUj1cIlwkKG1rdGVtcCAtZClcIgoKZWNobyBcIkxvZ2dpbmcgaW50byBBenVyZS4uLlwiClJFVFJJRVM9Mwp3aGlsZSBbWyBcJFJFVFJJRVMgLWd0IDAgXV07IGRvCiAgICBpZiBheiBsb2dpbiAtaSAtLWFsbG93LW5vLXN1YnNjcmlwdGlvbnMKICAgIHRoZW4KICAgICAgICBlY2hvIFwiYXogbG9naW4gc3VjY2Vzc2Z1bFwiCiAgICAgICAgYnJlYWsKICAgIGVsc2UKICAgICAgICBlY2hvIFwiYXogbG9naW4gZmFpbGVkLiBSZXRyeWluZy4uLlwiCiAgICAgICAgbGV0IFJFVFJJRVMtPTEKICAgICAgICBzbGVlcCA1CiAgICBmaQpkb25lCgp0cmFwIFwiY2xlYW51cFwiIEVYSVQKCmNsZWFudXAoKSB7CiAgYXogbG9nb3V0CiAgW1sgXCRURU1QX0RJUiA9fiAvdG1wLy4rIF1dICYmIHJtIC1yZiBcJFRFTVBfRElSCiAgW1sgXCRBWlVSRV9DT05GSUdfRElSID1+IC90bXAvLisgXV0gJiYgcm0gLXJmIFwkQVpVUkVfQ09ORklHX0RJUgp9CgppZiBbWyBcJENPTVBPTkVOVCA9IFwibWRtXCIgXV07IHRoZW4KICBDVVJSRU5UX0NFUlRfRklMRT1cIi9ldGMvbWRtLnBlbVwiCmVsaWYgW1sgXCRDT01QT05FTlRcID0gXCJtZHNkXCIgXV07IHRoZW4KICBDVVJSRU5UX0NFUlRfRklMRT1cIi92YXIvbGliL3dhYWdlbnQvTWljcm9zb2Z0LkF6dXJlLktleVZhdWx0LlN0b3JlL21kc2QucGVtXCIKZWxzZQogIGVjaG8gSW52YWxpZCB1c2FnZSAmJiBleGl0IDEKZmkKClNFQ1JFVF9OQU1FPVwicnAtXCR7Q09NUE9ORU5UfVwiCk5FV19DRVJUX0ZJTEU9XCJcJFRFTVBfRElSL1wkQ09NUE9ORU5ULnBlbVwiCmZvciBhdHRlbXB0IGluIHsxLi41fTsgZG8KICBheiBrZXl2YXVsdCBcCiAgICBzZWNyZXQgXAogICAgZG93bmxvYWQgXAogICAgLS1maWxlIFwiXCRORVdfQ0VSVF9GSUxFXCIgXAogICAgLS1pZCBcImh0dHBzOi8vJEtFWVZBVUxUUFJFRklYLXN2Yy4kS0VZVkFVTFRETlNTVUZGSVgvc2VjcmV0cy9cJFNFQ1JFVF9OQU1FXCIgXAogICAgJiYgYnJlYWsKICBpZiBbWyBcJGF0dGVtcHQgLWx0IDUgXV07IHRoZW4gc2xlZXAgMTA7IGVsc2UgZXhpdCAxOyBmaQpkb25lCgppZiBbIC1mIFwkTkVXX0NFUlRfRklMRSBdOyB0aGVuCiAgaWYgW1sgXCRDT01QT05FTlQgPSBcIm1kc2RcIiBdXTsgdGhlbgogICAgY2hvd24gc3lzbG9nOnN5c2xvZyBcJE5FV19DRVJUX0ZJTEUKICBlbHNlCiAgICBzZWQgLWkgLW5lICcxLC9FTkQgQ0VSVElGSUNBVEUvIHAnIFwkTkVXX0NFUlRfRklMRQogIGZpCgogIG5ld19jZXJ0X3NuPVwiXCQob3BlbnNzbCB4NTA5IC1pbiBcIlwkTkVXX0NFUlRfRklMRVwiIC1ub291dCAtc2VyaWFsIHwgYXdrIC1GPSAne3ByaW50IFwkMn0nKVwiCiAgY3VycmVudF9jZXJ0X3NuPVwiXCQob3BlbnNzbCB4NTA5IC1pbiBcIlwkQ1VSUkVOVF9DRVJUX0ZJTEVcIiAtbm9vdXQgLXNlcmlhbCB8IGF3ayAtRj0gJ3twcmludCBcJDJ9JylcIgogIGlmIFtbICEgLXogXCRuZXdfY2VydF9zbiBdXSAmJiBbWyBcJG5ld19jZXJ0X3NuICE9IFwiXCRjdXJyZW50X2NlcnRfc25cIiBdXTsgdGhlbgogICAgZWNobyB1cGRhdGluZyBjZXJ0aWZpY2F0ZSBmb3IgXCRDT01QT05FTlQKICAgIGNobW9kIDA2MDAgXCRORVdfQ0VSVF9GSUxFCiAgICBtdiBcJE5FV19DRVJUX0ZJTEUgXCRDVVJSRU5UX0NFUlRfRklMRQogIGZpCmVsc2UKICBlY2hvIEZhaWxlZCB0byByZWZyZXNoIGNlcnRpZmljYXRlIGZvciBcJENPTVBPTkVOVCAmJiBleGl0IDEKZmkiCgogICAgd3JpdGVfZmlsZSBkb3dubG9hZF9jcmVkc19zY3JpcHRfZmlsZW5hbWUgZG93bmxvYWRfY3JlZHNfc2NyaXB0X2ZpbGUgdHJ1ZQoKICAgIGNobW9kIHUreCAvdXNyL2xvY2FsL2Jpbi9kb3dubG9hZC1jcmVkZW50aWFscy5zaAoKICAgIHN5c3RlbWN0bCBlbmFibGUgZG93bmxvYWQtbWRzZC1jcmVkZW50aWFscy50aW1lcgogICAgc3lzdGVtY3RsIGVuYWJsZSBkb3dubG9hZC1tZG0tY3JlZGVudGlhbHMudGltZXIKCiAgICAvdXNyL2xvY2FsL2Jpbi9kb3dubG9hZC1jcmVkZW50aWFscy5zaCBtZHNkCiAgICAvdXNyL2xvY2FsL2Jpbi9kb3dubG9hZC1jcmVkZW50aWFscy5zaCBtZG0KCiAgICBsb2NhbCAtciBNRFNEQ0VSVElGSUNBVEVTQU49IiQob3BlbnNzbCB4NTA5IC1pbiAvdmFyL2xpYi93YWFnZW50L01pY3Jvc29mdC5BenVyZS5LZXlWYXVsdC5TdG9yZS9tZHNkLnBlbSAtbm9vdXQgLXN1YmplY3QgfCBzZWQgLWUgJ3MvLipDTiA9IC8vJykiCiAgICBsb2NhbCAtciB3YXRjaF9tZG1fY3JlZHNfc2VydmljZV9maWxlbmFtZT0iL2V0Yy9zeXN0ZW1kL3N5c3RlbS93YXRjaC1tZG0tY3JlZGVudGlhbHMuc2VydmljZSIKICAgIGxvY2FsIC1yIHdhdGNoX21kbV9jcmVkc19zZXJ2aWNlX2ZpbGU9IltVbml0XQpEZXNjcmlwdGlvbj1XYXRjaCBmb3IgY2hhbmdlcyBpbiBtZG0ucGVtIGFuZCByZXN0YXJ0cyB0aGUgbWRtIHNlcnZpY2UKCltTZXJ2aWNlXQpUeXBlPW9uZXNob3QKRXhlY1N0YXJ0PS91c3IvYmluL3N5c3RlbWN0bCByZXN0YXJ0IG1kbS5zZXJ2aWNlCgpbSW5zdGFsbF0KV2FudGVkQnk9bXVsdGktdXNlci50YXJnZXQiCgogICAgd3JpdGVfZmlsZSB3YXRjaF9tZG1fY3JlZHNfc2VydmljZV9maWxlbmFtZSB3YXRjaF9tZG1fY3JlZHNfc2VydmljZV9maWxlIHRydWUKCiAgICBsb2NhbCAtciB3YXRjaF9tZG1fY3JlZHNfcGF0aF9maWxlbmFtZT0nL2V0Yy9zeXN0ZW1kL3N5c3RlbS93YXRjaC1tZG0tY3JlZGVudGlhbHMucGF0aCcKICAgIGxvY2FsIC1yIHdhdGNoX21kbV9jcmVkc19wYXRoX2ZpbGU9J1tQYXRoXQpQYXRoTW9kaWZpZWQ9L2V0Yy9tZG0ucGVtCgpbSW5zdGFsbF0KV2FudGVkQnk9bXVsdGktdXNlci50YXJnZXQnCgogICAgd3JpdGVfZmlsZSB3YXRjaF9tZG1fY3JlZHNfcGF0aF9maWxlbmFtZSB3YXRjaF9tZG1fY3JlZHNfcGF0aF9maWxlIHRydWUKCiAgICBsb2NhbCAtciB3YXRjaF9tZG1fY3JlZHM9J3dhdGNoLW1kbS1jcmVkZW50aWFscy5wYXRoJwogICAgc3lzdGVtY3RsIGVuYWJsZSAiJHdhdGNoX21kbV9jcmVkcyIgfHwgYWJvcnQgImZhaWxlZCB0byBlbmFibGUgJHdhdGNoX21kbV9jcmVkcyIKICAgIHN5c3RlbWN0bCBzdGFydCAiJHdhdGNoX21kbV9jcmVkcyIgfHwgYWJvcnQgImZhaWxlZCB0byBzdGFydCAkd2F0Y2hfbWRtX2NyZWRzIgp9CgojIGNvbmZpZ3VyZV9zZXJ2aWNlX2Fyb19ycApjb25maWd1cmVfc2VydmljZV9hcm9fcnAoKSB7CiAgICBsb2cgInN0YXJ0aW5nIgoKICAgIGxvY2FsIC1yIGFyb19ycF9jb25mX2ZpbGVuYW1lPScvZXRjL3N5c2NvbmZpZy9hcm8tcnAnCiAgICBsb2NhbCAtciBhcm9fcnBfY29uZl9maWxlPSJBQ1JfUkVTT1VSQ0VfSUQ9JyRBQ1JSRVNPVVJDRUlEJwpBRE1JTl9BUElfQ0xJRU5UX0NFUlRfQ09NTU9OX05BTUU9JyRBRE1JTkFQSUNMSUVOVENFUlRDT01NT05OQU1FJwpBUk1fQVBJX0NMSUVOVF9DRVJUX0NPTU1PTl9OQU1FPSckQVJNQVBJQ0xJRU5UQ0VSVENPTU1PTk5BTUUnCkFaVVJFX0FSTV9DTElFTlRfSUQ9JyRBUk1DTElFTlRJRCcKQVpVUkVfRlBfQ0xJRU5UX0lEPSckRlBDTElFTlRJRCcKQVpVUkVfRlBfU0VSVklDRV9QUklOQ0lQQUxfSUQ9JyRGUFNFUlZJQ0VQUklOQ0lQQUxJRCcKQklMTElOR19FMkVfU1RPUkFHRV9BQ0NPVU5UX0lEPSckQklMTElOR0UyRVNUT1JBR0VBQ0NPVU5USUQnCkNMVVNURVJfTURNX0FDQ09VTlQ9JyRDTFVTVEVSTURNQUNDT1VOVCcKQ0xVU1RFUl9NRE1fTkFNRVNQQUNFPVJQCkNMVVNURVJfTURTRF9BQ0NPVU5UPSckQ0xVU1RFUk1EU0RBQ0NPVU5UJwpDTFVTVEVSX01EU0RfQ09ORklHX1ZFUlNJT049JyRDTFVTVEVSTURTRENPTkZJR1ZFUlNJT04nCkNMVVNURVJfTURTRF9OQU1FU1BBQ0U9JyRDTFVTVEVSTURTRE5BTUVTUEFDRScKREFUQUJBU0VfQUNDT1VOVF9OQU1FPSckREFUQUJBU0VBQ0NPVU5UTkFNRScKRE9NQUlOX05BTUU9JyRMT0NBVElPTi4kQ0xVU1RFUlBBUkVOVERPTUFJTk5BTUUnCkdBVEVXQVlfRE9NQUlOUz0nJEdBVEVXQVlET01BSU5TJwpHQVRFV0FZX1JFU09VUkNFR1JPVVA9JyRHQVRFV0FZUkVTT1VSQ0VHUk9VUE5BTUUnCktFWVZBVUxUX1BSRUZJWD0nJEtFWVZBVUxUUFJFRklYJwpNRE1fQUNDT1VOVD0nJFJQTURNQUNDT1VOVCcKTURNX05BTUVTUEFDRT1SUApNRFNEX0VOVklST05NRU5UPSckTURTREVOVklST05NRU5UJwpSUF9GRUFUVVJFUz0nJFJQRkVBVFVSRVMnClJQSU1BR0U9JyRSUElNQUdFJwpBUk9fSU5TVEFMTF9WSUFfSElWRT0nJENMVVNURVJTSU5TVEFMTFZJQUhJVkUnCkFST19ISVZFX0RFRkFVTFRfSU5TVEFMTEVSX1BVTExTUEVDPSckQ0xVU1RFUkRFRkFVTFRJTlNUQUxMRVJQVUxMU1BFQycKQVJPX0FET1BUX0JZX0hJVkU9JyRDTFVTVEVSU0FET1BUQllISVZFJwpVU0VfQ0hFQ0tBQ0NFU1M9JyRVU0VDSEVDS0FDQ0VTUyciCgogICAgd3JpdGVfZmlsZSBhcm9fcnBfY29uZl9maWxlbmFtZSBhcm9fcnBfY29uZl9maWxlIHRydWUKCiAgICBsb2NhbCAtciBhcm9fcnBfc2VydmljZV9maWxlbmFtZT0nL2V0Yy9zeXN0ZW1kL3N5c3RlbS9hcm8tcnAuc2VydmljZScKICAgIGxvY2FsIC1yIGFyb19ycF9zZXJ2aWNlX2ZpbGU9IltVbml0XQpBZnRlcj1uZXR3b3JrLW9ubGluZS50YXJnZXQKV2FudHM9bmV0d29yay1vbmxpbmUudGFyZ2V0CgpbU2VydmljZV0KRW52aXJvbm1lbnRGaWxlPS9ldGMvc3lzY29uZmlnL2Fyby1ycApFeGVjU3RhcnRQcmU9LS91c3IvYmluL2RvY2tlciBybSAtZiAlTgpFeGVjU3RhcnQ9L3Vzci9iaW4vZG9ja2VyIHJ1biBcCiAgLS1ob3N0bmFtZSAlSCBcCiAgLS1uYW1lICVOIFwKICAtLXJtIFwKICAtLWNhcC1kcm9wIG5ldF9yYXcgXAogIC1lIEFDUl9SRVNPVVJDRV9JRCBcCiAgLWUgQURNSU5fQVBJX0NMSUVOVF9DRVJUX0NPTU1PTl9OQU1FIFwKICAtZSBBUk1fQVBJX0NMSUVOVF9DRVJUX0NPTU1PTl9OQU1FIFwKICAtZSBBWlVSRV9BUk1fQ0xJRU5UX0lEIFwKICAtZSBBWlVSRV9GUF9DTElFTlRfSUQgXAogIC1lIEJJTExJTkdfRTJFX1NUT1JBR0VfQUNDT1VOVF9JRCBcCiAgLWUgQ0xVU1RFUl9NRE1fQUNDT1VOVCBcCiAgLWUgQ0xVU1RFUl9NRE1fTkFNRVNQQUNFIFwKICAtZSBDTFVTVEVSX01EU0RfQUNDT1VOVCBcCiAgLWUgQ0xVU1RFUl9NRFNEX0NPTkZJR19WRVJTSU9OIFwKICAtZSBDTFVTVEVSX01EU0RfTkFNRVNQQUNFIFwKICAtZSBEQVRBQkFTRV9BQ0NPVU5UX05BTUUgXAogIC1lIERPTUFJTl9OQU1FIFwKICAtZSBHQVRFV0FZX0RPTUFJTlMgXAogIC1lIEdBVEVXQVlfUkVTT1VSQ0VHUk9VUCBcCiAgLWUgS0VZVkFVTFRfUFJFRklYIFwKICAtZSBNRE1fQUNDT1VOVCBcCiAgLWUgTURNX05BTUVTUEFDRSBcCiAgLWUgTURTRF9FTlZJUk9OTUVOVCBcCiAgLWUgUlBfRkVBVFVSRVMgXAogIC1lIEFST19JTlNUQUxMX1ZJQV9ISVZFIFwKICAtZSBBUk9fSElWRV9ERUZBVUxUX0lOU1RBTExFUl9QVUxMU1BFQyBcCiAgLWUgQVJPX0FET1BUX0JZX0hJVkUgXAogIC1lIFVTRV9DSEVDS0FDQ0VTUyBcCiAgLW0gMmcgXAogIC1wIDQ0Mzo4NDQzIFwKICAtdiAvZXRjL2Fyby1ycDovZXRjL2Fyby1ycCBcCiAgLXYgL3J1bi9zeXN0ZW1kL2pvdXJuYWw6L3J1bi9zeXN0ZW1kL2pvdXJuYWwgXAogIC12IC92YXIvZXR3Oi92YXIvZXR3OnogXAogICRSUElNQUdFIFwKICBycApFeGVjU3RvcD0vdXNyL2Jpbi9kb2NrZXIgc3RvcCAtdCAzNjAwICVOClRpbWVvdXRTdG9wU2VjPTM2MDAKUmVzdGFydD1hbHdheXMKUmVzdGFydFNlYz0xClN0YXJ0TGltaXRJbnRlcnZhbD0wCgpbSW5zdGFsbF0KV2FudGVkQnk9bXVsdGktdXNlci50YXJnZXQiCgogICAgd3JpdGVfZmlsZSBhcm9fcnBfc2VydmljZV9maWxlbmFtZSBhcm9fcnBfY29uZl9maWxlIHRydWUKfQoKIyBjb25maWd1cmVfc2VydmljZV9hcm9fZGJ0b2tlbgpjb25maWd1cmVfc2VydmljZV9hcm9fZGJ0b2tlbigpIHsKICAgIGxvZyAic3RhcnRpbmciCgogICAgbG9jYWwgLXIgYXJvX2RidG9rZW5fc2VydmljZV9jb25mX2ZpbGVuYW1lPScvZXRjL3N5c2NvbmZpZy9hcm8tZGJ0b2tlbicKICAgIGxvY2FsIC1yIGFyb19kYnRva2VuX3NlcnZpY2VfY29uZl9maWxlPSJEQVRBQkFTRV9BQ0NPVU5UX05BTUU9JyREQVRBQkFTRUFDQ09VTlROQU1FJwpBWlVSRV9EQlRPS0VOX0NMSUVOVF9JRD0nJERCVE9LRU5DTElFTlRJRCcKQVpVUkVfR0FURVdBWV9TRVJWSUNFX1BSSU5DSVBBTF9JRD0nJEdBVEVXQVlTRVJWSUNFUFJJTkNJUEFMSUQnCktFWVZBVUxUX1BSRUZJWD0nJEtFWVZBVUxUUFJFRklYJwpNRE1fQUNDT1VOVD0nJFJQTURNQUNDT1VOVCcKTURNX05BTUVTUEFDRT1EQlRva2VuClJQSU1BR0U9JyRSUElNQUdFJyIKCiAgICB3cml0ZV9maWxlIGFyb19kYnRva2VuX3NlcnZpY2VfY29uZl9maWxlbmFtZSBhcm9fZGJ0b2tlbl9zZXJ2aWNlX2NvbmZfZmlsZSB0cnVlCgogICAgbG9jYWwgLXIgYXJvX2RidG9rZW5fc2VydmljZV9maWxlbmFtZT0nL2V0Yy9zeXN0ZW1kL3N5c3RlbS9hcm8tZGJ0b2tlbi5zZXJ2aWNlJwogICAgbG9jYWwgLXIgYXJvX2RidG9rZW5fc2VydmljZV9maWxlPSJbVW5pdF0KQWZ0ZXI9bmV0d29yay1vbmxpbmUudGFyZ2V0CldhbnRzPW5ldHdvcmstb25saW5lLnRhcmdldAoKW1NlcnZpY2VdCkVudmlyb25tZW50RmlsZT0vZXRjL3N5c2NvbmZpZy9hcm8tZGJ0b2tlbgpFeGVjU3RhcnRQcmU9LS91c3IvYmluL2RvY2tlciBybSAtZiAlTgpFeGVjU3RhcnQ9L3Vzci9iaW4vZG9ja2VyIHJ1biBcCiAgLS1ob3N0bmFtZSAlSCBcCiAgLS1uYW1lICVOIFwKICAtLXJtIFwKICAtLWNhcC1kcm9wIG5ldF9yYXcgXAogIC1lIEFaVVJFX0dBVEVXQVlfU0VSVklDRV9QUklOQ0lQQUxfSUQgXAogIC1lIERBVEFCQVNFX0FDQ09VTlRfTkFNRSBcCiAgLWUgQVpVUkVfREJUT0tFTl9DTElFTlRfSUQgXAogIC1lIEtFWVZBVUxUX1BSRUZJWCBcCiAgLWUgTURNX0FDQ09VTlQgXAogIC1lIE1ETV9OQU1FU1BBQ0UgXAogIC1tIDJnIFwKICAtcCA0NDU6ODQ0NSBcCiAgLXYgL3J1bi9zeXN0ZW1kL2pvdXJuYWw6L3J1bi9zeXN0ZW1kL2pvdXJuYWwgXAogIC12IC92YXIvZXR3Oi92YXIvZXR3OnogXAogICRSUElNQUdFIFwKICBkYnRva2VuCkV4ZWNTdG9wPS91c3IvYmluL2RvY2tlciBzdG9wIC10IDM2MDAgJU4KVGltZW91dFN0b3BTZWM9MzYwMApSZXN0YXJ0PWFsd2F5cwpSZXN0YXJ0U2VjPTEKU3RhcnRMaW1pdEludGVydmFsPTAKCltJbnN0YWxsXQpXYW50ZWRCeT1tdWx0aS11c2VyLnRhcmdldCIKCiAgICB3cml0ZV9maWxlIGFyb19kYnRva2VuX3NlcnZpY2VfZmlsZW5hbWUgYXJvX2RidG9rZW5fc2VydmljZV9maWxlIHRydWUKfQoKIyBjb25maWd1cmVfc2VydmljZV9hcm9fbW9uaXRvcgpjb25maWd1cmVfc2VydmljZV9hcm9fbW9uaXRvcigpIHsKICAgIGxvZyAic3RhcnRpbmciCiAgICBsb2cgImNvbmZpZ3VyaW5nIGFyby1tb25pdG9yIHNlcnZpY2UiCgogICAgIyBET01BSU5fTkFNRSwgQ0xVU1RFUl9NRFNEX0FDQ09VTlQsIENMVVNURVJfTURTRF9DT05GSUdfVkVSU0lPTiwgR0FURVdBWV9ET01BSU5TLCBHQVRFV0FZX1JFU09VUkNFR1JPVVAsIE1EU0RfRU5WSVJPTk1FTlQgQ0xVU1RFUl9NRFNEX05BTUVTUEFDRQogICAgIyBhcmUgbm90IHVzZWQsIGJ1dCBjYW4ndCBlYXNpbHkgYmUgcmVmYWN0b3JlZCBvdXQuIFNob3VsZCBiZSByZXZpc2l0ZWQgaW4gdGhlIGZ1dHVyZS4KICAgIGxvY2FsIC1yIGFyb19tb25pdG9yX3NlcnZpY2VfY29uZl9maWxlbmFtZT0nL2V0Yy9zeXNjb25maWcvYXJvLW1vbml0b3InCiAgICBsb2NhbCAtciBhcm9fbW9uaXRvcl9zZXJ2aWNlX2NvbmZfZmlsZT0iQVpVUkVfRlBfQ0xJRU5UX0lEPSckRlBDTElFTlRJRCcKRE9NQUlOX05BTUU9JyRMT0NBVElPTi4kQ0xVU1RFUlBBUkVOVERPTUFJTk5BTUUnCkNMVVNURVJfTURTRF9BQ0NPVU5UPSckQ0xVU1RFUk1EU0RBQ0NPVU5UJwpDTFVTVEVSX01EU0RfQ09ORklHX1ZFUlNJT049JyRDTFVTVEVSTURTRENPTkZJR1ZFUlNJT04nCkdBVEVXQVlfRE9NQUlOUz0nJEdBVEVXQVlET01BSU5TJwpHQVRFV0FZX1JFU09VUkNFR1JPVVA9JyRHQVRFV0FZUkVTT1VSQ0VHUk9VUE5BTUUnCk1EU0RfRU5WSVJPTk1FTlQ9JyRNRFNERU5WSVJPTk1FTlQnCkNMVVNURVJfTURTRF9OQU1FU1BBQ0U9JyRDTFVTVEVSTURTRE5BTUVTUEFDRScKQ0xVU1RFUl9NRE1fQUNDT1VOVD0nJENMVVNURVJNRE1BQ0NPVU5UJwpDTFVTVEVSX01ETV9OQU1FU1BBQ0U9QkJNCkRBVEFCQVNFX0FDQ09VTlRfTkFNRT0nJERBVEFCQVNFQUNDT1VOVE5BTUUnCktFWVZBVUxUX1BSRUZJWD0nJEtFWVZBVUxUUFJFRklYJwpNRE1fQUNDT1VOVD0nJFJQTURNQUNDT1VOVCcKTURNX05BTUVTUEFDRT1CQk0KUlBJTUFHRT0nJFJQSU1BR0UnIgoKICAgIHdyaXRlX2ZpbGUgYXJvX21vbml0b3Jfc2VydmljZV9jb25mX2ZpbGVuYW1lIGFyb19tb25pdG9yX3NlcnZpY2VfY29uZl9maWxlIHRydWUKCiAgICBsb2NhbCAtciBhcm9fbW9uaXRvcl9zZXJ2aWNlX2ZpbGVuYW1lPScvZXRjL3N5c3RlbWQvc3lzdGVtL2Fyby1tb25pdG9yLnNlcnZpY2UnCiAgICBsb2NhbCAtciBhcm9fbW9uaXRvcl9zZXJ2aWNlX2ZpbGU9IltVbml0XQpBZnRlcj1uZXR3b3JrLW9ubGluZS50YXJnZXQKV2FudHM9bmV0d29yay1vbmxpbmUudGFyZ2V0CgpbU2VydmljZV0KRW52aXJvbm1lbnRGaWxlPS9ldGMvc3lzY29uZmlnL2Fyby1tb25pdG9yCkV4ZWNTdGFydFByZT0tL3Vzci9iaW4vZG9ja2VyIHJtIC1mICVOCkV4ZWNTdGFydD0vdXNyL2Jpbi9kb2NrZXIgcnVuIFwKICAtLWhvc3RuYW1lICVIIFwKICAtLW5hbWUgJU4gXAogIC0tcm0gXAogIC0tY2FwLWRyb3AgbmV0X3JhdyBcCiAgLWUgQVpVUkVfRlBfQ0xJRU5UX0lEIFwKICAtZSBET01BSU5fTkFNRSBcCiAgLWUgQ0xVU1RFUl9NRFNEX0FDQ09VTlQgXAogIC1lIENMVVNURVJfTURTRF9DT05GSUdfVkVSU0lPTiBcCiAgLWUgR0FURVdBWV9ET01BSU5TIFwKICAtZSBHQVRFV0FZX1JFU09VUkNFR1JPVVAgXAogIC1lIE1EU0RfRU5WSVJPTk1FTlQgXAogIC1lIENMVVNURVJfTURTRF9OQU1FU1BBQ0UgXAogIC1lIENMVVNURVJfTURNX0FDQ09VTlQgXAogIC1lIENMVVNURVJfTURNX05BTUVTUEFDRSBcCiAgLWUgREFUQUJBU0VfQUNDT1VOVF9OQU1FIFwKICAtZSBLRVlWQVVMVF9QUkVGSVggXAogIC1lIE1ETV9BQ0NPVU5UIFwKICAtZSBNRE1fTkFNRVNQQUNFIFwKICAtbSAyLjVnIFwKICAtdiAvcnVuL3N5c3RlbWQvam91cm5hbDovcnVuL3N5c3RlbWQvam91cm5hbCBcCiAgLXYgL3Zhci9ldHc6L3Zhci9ldHc6eiBcCiAgJFJQSU1BR0UgXAogIG1vbml0b3IKUmVzdGFydD1hbHdheXMKUmVzdGFydFNlYz0xClN0YXJ0TGltaXRJbnRlcnZhbD0wCgpbSW5zdGFsbF0KV2FudGVkQnk9bXVsdGktdXNlci50YXJnZXQiCgogICAgd3JpdGVfZmlsZSBhcm9fbW9uaXRvcl9zZXJ2aWNlX2ZpbGVuYW1lIGFyb19tb25pdG9yX3NlcnZpY2VfZmlsZSB0cnVlCn0KCiMgY29uZmlndXJlX3NlcnZpY2VfYXJvX3BvcnRhbApjb25maWd1cmVfc2VydmljZV9hcm9fcG9ydGFsKCkgewogICAgbG9nICJzdGFydGluZyIKCiAgICBsb2NhbCAtciBhcm9fcG9ydGFsX3NlcnZpY2VfY29uZl9maWxlbmFtZT0nL2V0Yy9zeXNjb25maWcvYXJvLXBvcnRhbCcKICAgIGxvY2FsIC1yIGFyb19wb3J0YWxfc2VydmljZV9jb25mX2ZpbGU9IkFaVVJFX1BPUlRBTF9BQ0NFU1NfR1JPVVBfSURTPSckUE9SVEFMQUNDRVNTR1JPVVBJRFMnCkFaVVJFX1BPUlRBTF9DTElFTlRfSUQ9JyRQT1JUQUxDTElFTlRJRCcKQVpVUkVfUE9SVEFMX0VMRVZBVEVEX0dST1VQX0lEUz0nJFBPUlRBTEVMRVZBVEVER1JPVVBJRFMnCkRBVEFCQVNFX0FDQ09VTlRfTkFNRT0nJERBVEFCQVNFQUNDT1VOVE5BTUUnCktFWVZBVUxUX1BSRUZJWD0nJEtFWVZBVUxUUFJFRklYJwpNRE1fQUNDT1VOVD0nJFJQTURNQUNDT1VOVCcKTURNX05BTUVTUEFDRT1Qb3J0YWwKUE9SVEFMX0hPU1ROQU1FPSckTE9DQVRJT04uYWRtaW4uJFJQUEFSRU5URE9NQUlOTkFNRScKUlBJTUFHRT0nJFJQSU1BR0UnIgoKICAgIHdyaXRlX2ZpbGUgYXJvX3BvcnRhbF9zZXJ2aWNlX2NvbmZfZmlsZW5hbWUgYXJvX3BvcnRhbF9zZXJ2aWNlX2NvbmZfZmlsZSB0cnVlCgogICAgbG9jYWwgLXIgYXJvX3BvcnRhbF9zZXJ2aWNlX2ZpbGVuYW1lPScvZXRjL3N5c3RlbWQvc3lzdGVtL2Fyby1wb3J0YWwuc2VydmljZScKICAgIGxvY2FsIC1yIGFyb19wb3J0YWxfc2VydmljZV9maWxlPSJbVW5pdF0KQWZ0ZXI9bmV0d29yay1vbmxpbmUudGFyZ2V0CldhbnRzPW5ldHdvcmstb25saW5lLnRhcmdldApTdGFydExpbWl0SW50ZXJ2YWw9MAoKW1NlcnZpY2VdCkVudmlyb25tZW50RmlsZT0vZXRjL3N5c2NvbmZpZy9hcm8tcG9ydGFsCkV4ZWNTdGFydFByZT0tL3Vzci9iaW4vZG9ja2VyIHJtIC1mICVOCkV4ZWNTdGFydD0vdXNyL2Jpbi9kb2NrZXIgcnVuIFwKICAtLWhvc3RuYW1lICVIIFwKICAtLW5hbWUgJU4gXAogIC0tcm0gXAogIC0tY2FwLWRyb3AgbmV0X3JhdyBcCiAgLWUgQVpVUkVfUE9SVEFMX0FDQ0VTU19HUk9VUF9JRFMgXAogIC1lIEFaVVJFX1BPUlRBTF9DTElFTlRfSUQgXAogIC1lIEFaVVJFX1BPUlRBTF9FTEVWQVRFRF9HUk9VUF9JRFMgXAogIC1lIERBVEFCQVNFX0FDQ09VTlRfTkFNRSBcCiAgLWUgS0VZVkFVTFRfUFJFRklYIFwKICAtZSBNRE1fQUNDT1VOVCBcCiAgLWUgTURNX05BTUVTUEFDRSBcCiAgLWUgUE9SVEFMX0hPU1ROQU1FIFwKICAtbSAyZyBcCiAgLXAgNDQ0Ojg0NDQgXAogIC1wIDIyMjI6MjIyMiBcCiAgLXYgL3J1bi9zeXN0ZW1kL2pvdXJuYWw6L3J1bi9zeXN0ZW1kL2pvdXJuYWwgXAogIC12IC92YXIvZXR3Oi92YXIvZXR3OnogXAogICRSUElNQUdFIFwKICBwb3J0YWwKUmVzdGFydD1hbHdheXMKUmVzdGFydFNlYz0xCgpbSW5zdGFsbF0KV2FudGVkQnk9bXVsdGktdXNlci50YXJnZXQiCgogICAgd3JpdGVfZmlsZSBhcm9fcG9ydGFsX3NlcnZpY2VfY29uZl9maWxlbmFtZSBhcm9fcG9ydGFsX3NlcnZpY2VfY29uZl9maWxlIHRydWUKfQoKIyBjb25maWd1cmVfc2VydmljZV9tZHNkCmNvbmZpZ3VyZV9zZXJ2aWNlX21kc2QoKSB7CiAgICBsb2cgInN0YXJ0aW5nIgoKICAgIGxvY2FsIC1yIG1kc2Rfc2VydmljZV9kaXI9Ii9ldGMvc3lzdGVtZC9zeXN0ZW0vbWRzZC5zZXJ2aWNlLmQiCiAgICBta2RpciAiJG1kc2Rfc2VydmljZV9kaXIiCgogICAgbG9jYWwgLXIgbWRzZF9vdmVycmlkZV9jb25mX2ZpbGVuYW1lPSIkbWRzZF9zZXJ2aWNlX2Rpci9vdmVycmlkZS5jb25mIgogICAgbG9jYWwgLXIgbWRzZF9vdmVycmlkZV9jb25mX2ZpbGU9IltVbml0XQpBZnRlcj1uZXR3b3JrLW9ubGluZS50YXJnZXQiCgogICAgd3JpdGVfZmlsZSBtZHNkX292ZXJyaWRlX2NvbmZfZmlsZW5hbWUgbWRzZF9vdmVycmlkZV9jb25mX2ZpbGUgdHJ1ZQoKICAgIGxvY2FsIC1yIGRlZmF1bHRfbWRzZF9maWxlbmFtZT0iL2V0Yy9kZWZhdWx0L21kc2QiCiAgICBsb2NhbCAtciBkZWZhdWx0X21kc2RfZmlsZT0iTURTRF9ST0xFX1BSRUZJWD0vdmFyL3J1bi9tZHNkL2RlZmF1bHQKTURTRF9PUFRJT05TPVwiLUEgLWQgLXIgXCRNRFNEX1JPTEVfUFJFRklYXCIKCmV4cG9ydCBNT05JVE9SSU5HX0dDU19FTlZJUk9OTUVOVD0nJE1EU0RFTlZJUk9OTUVOVCcKZXhwb3J0IE1PTklUT1JJTkdfR0NTX0FDQ09VTlQ9JyRSUE1EU0RBQ0NPVU5UJwpleHBvcnQgTU9OSVRPUklOR19HQ1NfUkVHSU9OPSckTE9DQVRJT04nCmV4cG9ydCBNT05JVE9SSU5HX0dDU19BVVRIX0lEX1RZUEU9QXV0aEtleVZhdWx0CmV4cG9ydCBNT05JVE9SSU5HX0dDU19BVVRIX0lEPSckTURTRENFUlRJRklDQVRFU0FOJwpleHBvcnQgTU9OSVRPUklOR19HQ1NfTkFNRVNQQUNFPSckUlBNRFNETkFNRVNQQUNFJwpleHBvcnQgTU9OSVRPUklOR19DT05GSUdfVkVSU0lPTj0nJFJQTURTRENPTkZJR1ZFUlNJT04nCmV4cG9ydCBNT05JVE9SSU5HX1VTRV9HRU5FVkFfQ09ORklHX1NFUlZJQ0U9dHJ1ZQoKZXhwb3J0IE1PTklUT1JJTkdfVEVOQU5UPSckTE9DQVRJT04nCmV4cG9ydCBNT05JVE9SSU5HX1JPTEU9cnAKZXhwb3J0IE1PTklUT1JJTkdfUk9MRV9JTlNUQU5DRT1cIiQoaG9zdG5hbWUpXCIKCmV4cG9ydCBNRFNEX01TR1BBQ0tfU09SVF9DT0xVTU5TPTFcIiIKCiAgICB3cml0ZV9maWxlIGRlZmF1bHRfbWRzZF9maWxlbmFtZSBkZWZhdWx0X21kc2RfZmlsZSB0cnVlCgp9CgojIHJ1bl9henNlY2RfY29uZmlnX3NjYW4KcnVuX2F6c2VjZF9jb25maWdfc2NhbigpIHsKICAgIGxvZyAic3RhcnRpbmciCgogICAgbG9jYWwgLWFyIGNvbmZpZ3M9KAogICAgICAgICJiYXNlbGluZSIKICAgICAgICAiY2xhbWF2IgogICAgICAgICJzb2Z0d2FyZSIKICAgICkKCiAgICBsb2cgIlNjYW5uaW5nIGNvbmZpZ3VyYXRpb24gZmlsZXMgJHtjb25maWdzWypdfSIKICAgICMgc2hlbGxjaGVjayBkaXNhYmxlPVNDMjA2OAogICAgZm9yIHNjYW4gaW4gJHtjb25maWdzW0BdfTsgZG8KICAgICAgICBsb2cgIlNjYW5uaW5nIGNvbmZpZyBmaWxlICRzY2FuIG5vdyIKICAgICAgICAvdXNyL2xvY2FsL2Jpbi9henNlY2QgY29uZmlnIC1zICIkc2NhbiIgLWQgUDFECiAgICBkb25lCn0KCiMgd3JpdGVfZmlsZQojIEFyZ3MKIyAxKSBmaWxlbmFtZSAtIHN0cmluZwojIDIpIGZpbGVfY29udGVudHMgLSBzdHJpbmcKIyAzKSBjbG9iYmVyIC0gYm9vbGVhbjsgb3B0aW9uYWwgLSBkZWZhdWx0cyB0byBmYWxzZQp3cml0ZV9maWxlKCkgewogICAgbG9jYWwgLW4gZmlsZW5hbWU9IiQxIgogICAgbG9jYWwgLW4gZmlsZV9jb250ZW50cz0iJDIiCiAgICBsb2NhbCAtciBjbG9iYmVyPSIkezM6LWZhbHNlfSIKCiAgICBpZiAkY2xvYmJlcjsgdGhlbgogICAgICAgIGxvZyAiT3ZlcndyaXRpbmcgZmlsZSAkZmlsZW5hbWUiCiAgICAgICAgZWNobyAiJGZpbGVfY29udGVudHMiID4gIiRmaWxlbmFtZSIKICAgIGVsc2UKICAgICAgICBsb2cgIkFwcGVuZGluZyB0byAkZmlsZW5hbWUiCiAgICAgICAgZWNobyAiJGZpbGVfY29udGVudHMiID4+ICIkZmlsZW5hbWUiCiAgICBmaQp9CgojIHJlYm9vdF92bSByZXN0b3JlcyBhbGwgc2VsaW51eCBmaWxlIGNvbnRleHRzLCB3YWl0cyAzMCBzZWNvbmRzIHRoZW4gcmVib290cwpyZWJvb3Rfdm0oKSB7CiAgICBsb2cgInN0YXJ0aW5nIgoKICAgIGNvbmZpZ3VyZV9zZWxpbnV4ICJ0cnVlIgogICAgKHNsZWVwIDMwICYmIGxvZyAicmVib290aW5nIHZtIG5vdyI7IHJlYm9vdCkgJgp9CgojIGxvZyBpcyBhIHdyYXBwZXIgZm9yIGVjaG8gdGhhdCBpbmNsdWRlcyB0aGUgZnVuY3Rpb24gbmFtZQpsb2coKSB7CiAgICBsb2NhbCAtciBtc2c9IiR7MTotImxvZyBtZXNzYWdlIGlzIGVtcHR5In0iCiAgICBsb2NhbCAtciBzdGFja19sZXZlbD0iJHsyOi0xfSIKICAgIGVjaG8gIiR7RlVOQ05BTUVbJHtzdGFja19sZXZlbH1dfTogJHttc2d9Igp9CgojIGFib3J0IGlzIGEgd3JhcHBlciBmb3IgbG9nIHRoYXQgZXhpdHMgd2l0aCBhbiBlcnJvciBjb2RlCmFib3J0KCkgewogICAgbG9jYWwgLXJpIG9yaWdpbl9zdGFja2xldmVsPTIKICAgIGxvZyAiJHsxfSIgIiRvcmlnaW5fc3RhY2tsZXZlbCIKICAgIGxvZyAiRXhpdGluZyIKICAgIGV4aXQgMQp9CgpleHBvcnQgQVpVUkVfQ0xPVURfTkFNRT0iJHtBWlVSRUNMT1VETkFNRTo/IkZhaWxlZCB0byBjYXJyeSBvdmVyIHZhcmlhYmxlcyJ9IgoKbWFpbiAiJEAiCg==')))]" } } } diff --git a/pkg/deploy/generator/scripts/devProxyVMSS.sh b/pkg/deploy/generator/scripts/devProxyVMSS.sh index bdbb8fe35b3..2b405881bce 100644 --- a/pkg/deploy/generator/scripts/devProxyVMSS.sh +++ b/pkg/deploy/generator/scripts/devProxyVMSS.sh @@ -1,53 +1,331 @@ -#Adding retry logic to yum commands in order to avoid stalling out on resource locks -echo "running RHUI fix" -for attempt in {1..5}; do - yum update -y --disablerepo='*' --enablerepo='rhui-microsoft-azure*' && break - if [[ ${attempt} -lt 5 ]]; then sleep 10; else exit 1; fi -done - -echo "running yum update" -for attempt in {1..5}; do - yum -y -x WALinuxAgent -x WALinuxAgent-udev update --allowerasing && break - if [[ ${attempt} -lt 5 ]]; then sleep 10; else exit 1; fi -done - -echo "installing podman-docker" -for attempt in {1..5}; do - yum -y install podman-docker && break - if [[ ${attempt} -lt 5 ]]; then sleep 10; else exit 1; fi -done - -firewall-cmd --add-port=443/tcp --permanent - -mkdir /root/.docker -cat >/root/.docker/config.json </etc/proxy/proxy.crt -base64 -d <<<"$PROXYKEY" >/etc/proxy/proxy.key -base64 -d <<<"$PROXYCLIENTCERT" >/etc/proxy/proxy-client.crt -chown -R 1000:1000 /etc/proxy -chmod 0600 /etc/proxy/proxy.key + local -ra aro_services=( + proxy + ) + log "enabling aro services ${aro_services[*]}" + # shellcheck disable=SC2068 + for service in ${aro_services[@]}; do + log "Enabling $service now" + systemctl enable "$service.service" + done +} -cat >/etc/sysconfig/proxy </etc/systemd/system/proxy.service <<'EOF' -[Unit] + base64 -d <<<"$PROXYCERT" >/etc/proxy/proxy.crt + base64 -d <<<"$PROXYKEY" >/etc/proxy/proxy.key + base64 -d <<<"$PROXYCLIENTCERT" >/etc/proxy/proxy-client.crt + chown -R 1000:1000 /etc/proxy + chmod 0600 /etc/proxy/proxy.key +} + +configure_service_proxy() { + local -r sysconfig_proxy_filename='/etc/sysconfig/proxy' + local -r sysconfig_proxy_file="PROXY_IMAGE='$PROXYIMAGE'" + + write_file sysconfig_proxy_filename sysconfig_proxy_file true + + local -r proxy_service_filename='/etc/systemd/system/proxy.service' + local -r proxy_service_file="[Unit] After=network-online.target Wants=network-online.target @@ -61,34 +339,66 @@ RestartSec=1 StartLimitInterval=0 [Install] -WantedBy=multi-user.target -EOF +WantedBy=multi-user.target" -systemctl enable proxy.service + local -r cron_weekly_pull_image_filename='/etc/cron.weekly/pull-image' + local -r cron_weekly_pull_image_file="#!/bin/bash +docker pull $PROXYIMAGE +systemctl restart proxy.service" + + write_file cron_weekly_pull_image_filename cron_weekly_pull_image_file true + chmod +x "$cron_weekly_pull_image_filename" -cat >/etc/cron.weekly/pull-image <<'EOF' -#!/bin/bash + local -r cron_daily_restart_proxy_filename='/etc/cron.daily/restart-proxy' + local -r cron_daily_restart_proxy_file="#!/bin/bash +systemctl restart proxy.service" + + write_file cron_daily_restart_proxy_filename cron_daily_restart_proxy_file + chmod +x "$cron_daily_restart_proxy_filename" +} -docker pull $PROXYIMAGE -systemctl restart proxy.service -EOF -chmod +x /etc/cron.weekly/pull-image +# write_file +# Args +# 1) filename - string +# 2) file_contents - string +# 3) clobber - boolean; optional - defaults to false +write_file() { + local -n filename="$1" + local -n file_contents="$2" + local -r clobber="${3:-false}" -cat >/etc/cron.weekly/yumupdate <<'EOF' -#!/bin/bash + if $clobber; then + log "Overwriting file $filename" + echo "$file_contents" > "$filename" + else + log "Appending to $filename" + echo "$file_contents" >> "$filename" + fi +} -yum update -y -EOF -chmod +x /etc/cron.weekly/yumupdate +# reboot_vm restores all selinux file contexts, waits 30 seconds then reboots +reboot_vm() { + log "starting" -cat >/etc/cron.daily/restart-proxy <<'EOF' -#!/bin/bash + configure_selinux "true" + (sleep 30 && log "rebooting vm now"; reboot) & +} + +# log is a wrapper for echo that includes the function name +log() { + local -r msg="${1:-"log message is empty"}" + local -r stack_level="${2:-1}" + echo "${FUNCNAME[${stack_level}]}: ${msg}" +} + +# abort is a wrapper for log that exits with an error code +abort() { + local -ri origin_stacklevel=2 + log "${1}" "$origin_stacklevel" + log "Exiting" + exit 1 +} -systemctl restart proxy.service -EOF -chmod +x /etc/cron.daily/restart-proxy +export AZURE_CLOUD_NAME="${AZURECLOUDNAME:?"Failed to carry over variables"}" -( - sleep 30 - reboot -) & +main "$@" diff --git a/pkg/deploy/generator/scripts/gatewayVMSS.sh b/pkg/deploy/generator/scripts/gatewayVMSS.sh index 4034eed3675..64b4232309f 100644 --- a/pkg/deploy/generator/scripts/gatewayVMSS.sh +++ b/pkg/deploy/generator/scripts/gatewayVMSS.sh @@ -1,52 +1,280 @@ #!/bin/bash -echo "setting ssh password authentication" -# We need to manually set PasswordAuthentication to true in order for the VMSS Access JIT to work -sed -i 's/PasswordAuthentication no/PasswordAuthentication yes/g' /etc/ssh/sshd_config -systemctl reload sshd.service +set -o errexit \ + -o nounset -#Adding retry logic to yum commands in order to avoid stalling out on resource locks -echo "running RHUI fix" -for attempt in {1..5}; do - yum update -y --disablerepo='*' --enablerepo='rhui-microsoft-azure*' && break - if [[ ${attempt} -lt 5 ]]; then sleep 10; else exit 1; fi -done +if [ "${DEBUG:-false}" == true ]; then + set -x +fi -echo "running yum update" -for attempt in {1..5}; do - yum -y -x WALinuxAgent -x WALinuxAgent-udev update --allowerasing && break - if [[ ${attempt} -lt 5 ]]; then sleep 10; else exit 1; fi -done +main() { + local -r gateway_logdir='/var/log/aro-gateway' + parse_run_options "$@" gateway_logdir -echo "extending partition table" -# Linux block devices are inconsistently named -# it's difficult to tie the lvm pv to the physical disk using /dev/disk files, which is why lvs is used here -physical_disk="$(lvs -o devices -a | head -n2 | tail -n1 | cut -d ' ' -f 3 | cut -d \( -f 1 | tr -d '[:digit:]')" -growpart "$physical_disk" 2 -echo "extending filesystems" -lvextend -l +20%FREE /dev/rootvg/rootlv -xfs_growfs / + configure_sshd + configure_and_install_dnf_pkgs_repos + configure_disk_partitions + configure_logrotate gateway_logdir + configure_selinux -lvextend -l +100%FREE /dev/rootvg/varlv -xfs_growfs /var + mkdir -p /var/log/journal + mkdir -p /var/lib/waagent/Microsoft.Azure.KeyVault.Store -rpm --import https://dl.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-8 -rpm --import https://packages.microsoft.com/keys/microsoft.asc + configure_firewalld_rules + pull_container_images + configure_system_services gateway_logdir + reboot_vm +} -for attempt in {1..5}; do - yum -y install https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm && break - if [[ ${attempt} -lt 5 ]]; then sleep 10; else exit 1; fi -done +usage() { + local -n options="$1" + log "$(basename "$0") [$options] + -d Configure Disk Partitions + -p Configure rpm repositories, import required rpm keys, update & install packages with dnf + -l Configure logrotate.conf + -s Make selinux modifications required for ARO RP + -r Configure sshd - Allow password authenticaiton + -f Configure firewalld default zone rules + -u Configure systemd unit files for ARO RP + -i Pull container images + + Note: steps will be executed in the order that flags are provided + " +} + +# parse_run_options takes all arguements passed to main and parses them +# allowing individual step(s) to be ran, rather than all steps +# +# This is useful for local testing, or possibly modifying the bootstrap execution via environment variables in the deployment pipeline +parse_run_options() { + # shellcheck disable=SC2206 + local -a options=(${1:-}) + if [ "${#options[@]}" -eq 0 ]; then + log "Running all steps" + return 0 + fi + + local OPTIND + local -r allowed_options="dplsrfui" + while getopts ${allowed_options} options; do + case "${options}" in + d) + log "Running step configure_disk_partitions" + configure_disk_partitions + ;; + p) + log "Running step configure_and_install_dnf_pkgs_repos" + configure_and_install_dnf_pkgs_repos + ;; + l) + log "Running configure_logrotate" + configure_logrotate "$2" + ;; + s) + log "Running configure_selinux" + configure_selinux + ;; + r) + log "Running configure_sshd" + configure_sshd + ;; + f) + log "Running configure_firewalld_rules" + configure_firewalld_rules + ;; + u) + log "Running pull_container_images & configure_system_services" + configure_system_services "$2" + ;; + i) + log "Running pull_container_images" + pull_container_images + ;; + *) + usage allowed_options + abort "Unkown option provided" + ;; + esac + done + + exit 0 +} + +# We need to configure PasswordAuthentication to yes in order for the VMSS Access JIT to work +configure_sshd() { + log "starting" + log "setting ssh password authentication" + sed -i 's/PasswordAuthentication no/PasswordAuthentication yes/g' /etc/ssh/sshd_config + + systemctl reload sshd.service + systemctl is-active --quiet sshd || abort "sshd failed to reload" +} -echo "configuring logrotate" +# configure_and_install_dnf_pkgs_repos +configure_and_install_dnf_pkgs_repos() { + log "starting" + + # transaction attempt retry time in seconds + local -ri retry_wait_time=60 + configure_rhui_repo retry_wait_time + create_azure_rpm_repos retry_wait_time + + local -ar exclude_pkgs=( + "-x WALinuxAgent" + "-x WALinuxAgent-udev" + ) + + dnf_update_pkgs exclude_pkgs retry_wait_time + + local -ra rpm_keys=( + https://dl.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-8 + https://packages.microsoft.com/keys/microsoft.asc + ) + + rpm_import_keys rpm_keys retry_wait_time + + local -ra repo_rpm_pkgs=( + https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm + ) + + local -ra install_pkgs=( + clamav + azsec-clamav + azsec-monitor + azure-cli + azure-mdsd + azure-security + podman + podman-docker + openssl-perl + # hack - we are installing python3 on hosts due to an issue with Azure Linux Extensions https://github.com/Azure/azure-linux-extensions/pull/1505 + python3 + ) + + dnf_install_pkgs repo_rpm_pkgs retry_wait_time + dnf_install_pkgs install_pkgs retry_wait_time +} + +# configure_rhui_repo +configure_rhui_repo() { + log "starting" + + local -ra cmd=( + dnf + update + -y + --disablerepo='*' + --enablerepo='rhui-microsoft-azure*' + ) + + log "running RHUI package updates" + retry cmd "$1" +} + +# retry Adding retry logic to yum commands in order to avoid stalling out on resource locks +retry() { + local -n cmd_retry="$1" + local -n wait_time="$2" + + for attempt in {1..5}; do + log "attempt #${attempt} - ${FUNCNAME[2]}" + ${cmd_retry[@]} & + + wait $! && break + if [[ ${attempt} -lt 5 ]]; then + sleep "$wait_time" + else + abort "attempt #${attempt} - Failed to update packages" + fi + done +} + +# dnf_update_pkgs +dnf_update_pkgs() { + local -n excludes="$1" + log "starting" + + local -ra cmd=( + dnf + -y + ${excludes[@]} + update + --allowerasing + ) + + log "Updating all packages" + retry cmd "$2" +} + +# dnf_install_pkgs +dnf_install_pkgs() { + local -n pkgs="$1" + log "starting" + + local -ra cmd=( + dnf + -y + install + ${pkgs[@]} + ) + + log "Attempting to install packages: ${pkgs[*]}" + retry cmd "$2" +} + +# rpm_import_keys +rpm_import_keys() { + local -n keys="$1" + log "starting" + + + # shellcheck disable=SC2068 + for key in ${keys[@]}; do + if [ ${#keys[@]} -eq 0 ]; then + break + fi + local -a cmd=( + rpm + --import + -v + "$key" + ) + + log "attempt #$attempt - importing rpm repository key $key" + retry cmd "$2" && unset key + done +} -# gateway_logdir is a readonly variable that specifies the host path mount point for the gateway container log file -# for the purpose of rotating the gateway logs -declare -r gateway_logdir='/var/log/aro-gateway' +# configure_disk_partitions +configure_disk_partitions() { + log "starting" + log "extending partition table" + + # Linux block devices are inconsistently named + # it's difficult to tie the lvm pv to the physical disk using /dev/disk files, which is why lvs is used here + physical_disk="$(lvs -o devices -a | head -n2 | tail -n1 | cut -d ' ' -f 3 | cut -d \( -f 1 | tr -d '[:digit:]')" + growpart "$physical_disk" 2 + + log "extending filesystems" + log "extending root lvm" + lvextend -l +20%FREE /dev/rootvg/rootlv + log "growing root filesystem" + xfs_growfs / + + log "extending var lvm" + lvextend -l +100%FREE /dev/rootvg/varlv + log "growing var filesystem" + xfs_growfs /var +} -cat >/etc/logrotate.conf </etc/yum.repos.d/azure.repo <<'EOF' -[azure-cli] +# create_azure_rpm_repos creates /etc/yum.repos.d/azure.repo repository file +create_azure_rpm_repos() { + log "starting" + + local -r azure_repo_filename='/etc/yum.repos.d/azure.repo' + local -r azure_repo_file='[azure-cli] name=azure-cli baseurl=https://packages.microsoft.com/yumrepos/azure-cli enabled=yes @@ -105,68 +338,144 @@ gpgcheck=yes name=azurecore baseurl=https://packages.microsoft.com/yumrepos/azurecore enabled=yes -gpgcheck=no -EOF +gpgcheck=no' + + write_file azure_repo_filename azure_repo_file true +} -semanage fcontext -a -t var_log_t "/var/log/journal(/.*)?" -mkdir -p /var/log/journal +# configure_selinux +configure_selinux() { + log "starting" -for attempt in {1..5}; do - yum -y install clamav azsec-clamav azsec-monitor azure-cli azure-mdsd azure-security podman-docker openssl-perl python3 && break - # hack - we are installing python3 on hosts due to an issue with Azure Linux Extensions https://github.com/Azure/azure-linux-extensions/pull/1505 - if [[ ${attempt} -lt 5 ]]; then sleep 10; else exit 1; fi -done + local -r relabel="${1:-false}" + + already_defined_ignore_error="File context for /var/log/journal(/.*)? already defined" + semanage fcontext -a -t var_log_t "/var/log/journal(/.*)?" || log "$already_defined_ignore_error" + chcon -R system_u:object_r:var_log_t:s0 /var/opt/microsoft/linuxmonagent + + if "$relabel"; then + restorecon -RF /var/log/* || log "$already_defined_ignore_error" + fi +} + +# configure_firewalld_rules +configure_firewalld_rules() { + log "starting" + + # https://access.redhat.com/security/cve/cve-2020-13401 + local -r prefix="/etc/sysctl.d" + local -r disable_accept_ra_conf_filename="$prefix/02-disable-accept-ra.conf" + local -r disable_accept_ra_conf_file="net.ipv6.conf.all.accept_ra=0" + + write_file disable_accept_ra_conf_filename disable_accept_ra_conf_file true + + local -r disable_core_filename="$prefix/01-disable-core.conf" + local -r disable_core_file="kernel.core_pattern = |/bin/true + " + write_file disable_core_filename disable_core_file true + + sysctl --system -echo "applying firewall rules" -# https://access.redhat.com/security/cve/cve-2020-13401 -cat >/etc/sysctl.d/02-disable-accept-ra.conf <<'EOF' -net.ipv6.conf.all.accept_ra=0 -EOF - -cat >/etc/sysctl.d/01-disable-core.conf <<'EOF' -kernel.core_pattern = |/bin/true -EOF -sysctl --system - -firewall-cmd --add-port=80/tcp --permanent -firewall-cmd --add-port=8081/tcp --permanent -firewall-cmd --add-port=443/tcp --permanent - -echo "logging into prod acr" -export AZURE_CLOUD_NAME=$AZURECLOUDNAME -az login -i --allow-no-subscriptions - -# The managed identity that the VM runs as only has a single roleassignment. -# This role assignment is ACRPull which is not necessarily present in the -# subscription we're deploying into. If the identity does not have any -# role assignments scoped on the subscription we're deploying into, it will -# not show on az login -i, which is why the below line is commented. -# az account set -s "$SUBSCRIPTIONID" - -# Suppress emulation output for podman instead of docker for az acr compatability -mkdir -p /etc/containers/ -touch /etc/containers/nodocker - -mkdir -p /root/.docker -REGISTRY_AUTH_FILE=/root/.docker/config.json az acr login --name "$(sed -e 's|.*/||' <<<"$ACRRESOURCEID")" - -MDMIMAGE="${RPIMAGE%%/*}/${MDMIMAGE##*/}" -docker pull "$MDMIMAGE" -docker pull "$RPIMAGE" -docker pull "$FLUENTBITIMAGE" - -az logout - -echo "configuring fluentbit service" -mkdir -p /etc/fluentbit/ -mkdir -p /var/lib/fluent - -cat >/etc/fluentbit/fluentbit.conf <<'EOF' -[INPUT] - Name systemd - Tag journald - Systemd_Filter _COMM=aro - DB /var/lib/fluent/journaldb + local -ra enable_ports=( + "80/tcp" + "8081/tcp" + "443/tcp" + ) + + log "Enabling ports ${enable_ports[*]} on default firewalld zone" + # shellcheck disable=SC2068 + for port in ${enable_ports[@]}; do + log "Enabling port $port now" + firewall-cmd "--add-port=$port" + done + + firewall-cmd --runtime-to-permanent +} + +# pull_container_images +pull_container_images() { + log "starting" + + # The managed identity that the VM runs as only has a single roleassignment. + # This role assignment is ACRPull which is not necessarily present in the + # subscription we're deploying into. If the identity does not have any + # role assignments scoped on the subscription we're deploying into, it will + # not show on az login -i, which is why the below line is commented. + # az account set -s "$SUBSCRIPTIONID" + az login -i --allow-no-subscriptions + + # Suppress emulation output for podman instead of docker for az acr compatability + mkdir -p /etc/containers/ + mkdir -p /root/.docker + touch /etc/containers/nodocker + + # This name is used in the case that az acr login searches for this in it's environment + local -r REGISTRY_AUTH_FILE="/root/.docker/config.json" + + log "logging into prod acr" + az acr login --name "$(sed -e 's|.*/||' <<<"$ACRRESOURCEID")" + + MDMIMAGE="${RPIMAGE%%/*}/${MDMIMAGE##*/}" + docker pull "$MDMIMAGE" + docker pull "$RPIMAGE" + docker pull "$FLUENTBITIMAGE" + + az logout +} + +# configure_system_services creates, configures, and enables the following systemd services and timers +# services +# fluentbit +# mdm +# mdsd +# arp-rp +# aro-dbtoken +# aro-monitor +# aro-portal +configure_system_services() { + configure_service_fluentbit + configure_service_mdm + configure_timers_mdm_mdsd + configure_service_aro_gateway "$1" + configure_service_mdsd +} + +# enable_aro_services enables all services required for aro rp +enable_aro_services() { + log "starting" + + local -ra aro_services=( + aro-gateway + auoms + azsecd + azsecmond + mdsd + mdm + chronyd + fluentbit + ) + log "enabling gateway services ${aro_services[*]}" + # shellcheck disable=SC2068 + for service in ${aro_services[@]}; do + log "Enabling $service now" + systemctl enable "$service.service" + done +} + +# configure_service_fluentbit +configure_service_fluentbit() { + log "starting" + log "configuring fluentbit service" + + mkdir -p /etc/fluentbit/ + mkdir -p /var/lib/fluent + + local -r fluentbit_conf_filename='/etc/fluentbit/fluentbit.conf' + local -r fluentbit_conf_file="[INPUT] +Name systemd +Tag journald +Systemd_Filter _COMM=aro +DB /var/lib/fluent/journaldb [FILTER] Name modify @@ -177,13 +486,18 @@ cat >/etc/fluentbit/fluentbit.conf <<'EOF' [OUTPUT] Name forward Match * - Port 29230 -EOF + Port 29230" + + write_file fluentbit_conf_filename fluentbit_conf_file true + + local -r sysconfig_fluentbit_filename='/etc/sysconfig/fluentbit' + local -r sysconfig_fluentbit_file="FLUENTBITIMAGE=$FLUENTBITIMAGE" + + write_file sysconfig_fluentbit_filename sysconfig_fluentbit_file true -echo "FLUENTBITIMAGE=$FLUENTBITIMAGE" >/etc/sysconfig/fluentbit + local -r fluentbit_service_filename='/etc/systemd/system/fluentbit.service' -cat >/etc/systemd/system/fluentbit.service <<'EOF' -[Unit] + local -r fluentbit_service_file="[Unit] After=network-online.target Wants=network-online.target StartLimitIntervalSec=0 @@ -213,21 +527,61 @@ RestartSec=5 StartLimitInterval=0 [Install] -WantedBy=multi-user.target -EOF +WantedBy=multi-user.target" + + write_file fluentbit_conf_filename fluentbit_conf_file true +} + +# configure_certs +configure_certs() { + log "starting" + + mkdir /etc/aro-rp + base64 -d <<<"$ADMINAPICABUNDLE" >/etc/aro-rp/admin-ca-bundle.pem + if [[ -n "$ARMAPICABUNDLE" ]]; then + base64 -d <<<"$ARMAPICABUNDLE" >/etc/aro-rp/arm-ca-bundle.pem + fi + chown -R 1000:1000 /etc/aro-rp + + # setting MONITORING_GCS_AUTH_ID_TYPE=AuthKeyVault seems to have caused mdsd not + # to honour SSL_CERT_FILE any more, heaven only knows why. + mkdir -p /usr/lib/ssl/certs + csplit -f /usr/lib/ssl/certs/cert- -b %03d.pem /etc/pki/tls/certs/ca-bundle.crt /^$/1 "{*}" >/dev/null + c_rehash /usr/lib/ssl/certs + +# we leave clientId blank as long as only 1 managed identity assigned to vmss +# if we have more than 1, we will need to populate with clientId used for off-node scanning + local -r nodescan_agent_filename="/etc/default/vsa-nodescan-agent.config" + local -r nodescan_agent_file="{ + \"Nice\": 19, + \"Timeout\": 10800, + \"ClientId\": \"\", + \"TenantId\": $AZURESECPACKVSATENANTID, + \"QualysStoreBaseUrl\": $AZURESECPACKQUALYSURL, + \"ProcessTimeout\": 300, + \"CommandDelay\": 0 + }" + + write_file nodescan_agent_filename nodescan_agent_file true +} + +# configure_service_mdm +configure_service_mdm() { + log "starting" + log "configuring mdm service" -echo "configuring mdm service" -cat >/etc/sysconfig/mdm </etc/systemd/system/mdm.service <<'EOF' -[Unit] + write_file sysconfig_mdm_filename sysconfig_mdm_file true + + mkdir -p /var/etw + local -r mdm_service_filename="/etc/systemd/system/mdm.service" + local -r mdm_service_file="[Unit] After=network-online.target Wants=network-online.target @@ -258,80 +612,28 @@ RestartSec=1 StartLimitInterval=0 [Install] -WantedBy=multi-user.target -EOF - -echo "configuring aro-gateway service" -cat >/etc/sysconfig/aro-gateway </etc/systemd/system/aro-gateway.service </etc/systemd/system/download-$var-credentials.service </etc/systemd/system/download-$var-credentials.timer </usr/local/bin/download-credentials.sh </etc/systemd/system/watch-mdm-credentials.service </etc/systemd/system/watch-mdm-credentials.path </etc/systemd/system/mdsd.service.d/override.conf <<'EOF' -[Unit] + local -r aro_dbtoken_service_filename='/etc/systemd/system/aro-dbtoken.service' + local -r aro_dbtoken_service_file="[Unit] After=network-online.target -EOF +Wants=network-online.target + +[Service] +EnvironmentFile=/etc/sysconfig/aro-gateway +ExecStartPre=-/usr/bin/docker rm -f %N +ExecStartPre=/usr/bin/mkdir -p ${gateway_logdir} +ExecStart=/usr/bin/docker run \ + --hostname %H \ + --name %N \ + --rm \ + --cap-drop net_raw \ + -e ACR_RESOURCE_ID \ + -e DATABASE_ACCOUNT_NAME \ + -e AZURE_DBTOKEN_CLIENT_ID \ + -e DBTOKEN_URL \ + -e GATEWAY_DOMAINS \ + -e GATEWAY_FEATURES \ + -e MDM_ACCOUNT \ + -e MDM_NAMESPACE \ + -m 2g \ + -p 80:8080 \ + -p 8081:8081 \ + -p 443:8443 \ + -v /run/systemd/journal:/run/systemd/journal \ + -v /var/etw:/var/etw:z \ + -v ${gateway_logdir}:/ctr.log:z \ + \$RPIMAGE \ + gateway +ExecStop=/usr/bin/docker stop -t 3600 %N +TimeoutStopSec=3600 +Restart=always +RestartSec=1 +StartLimitInterval=0 + +[Install] +WantedBy=multi-user.target" + + write_file aro_dbtoken_service_filename aro_dbtoken_service_file true +} + +# configure_service_mdsd +configure_service_mdsd() { + log "starting" + + local -r mdsd_service_dir="/etc/systemd/system/mdsd.service.d" + mkdir "$mdsd_service_dir" + + local -r mdsd_override_conf_filename="$mdsd_service_dir/override.conf" + local -r mdsd_override_conf_file="[Unit] +After=network-online.target" -cat >/etc/default/mdsd </dev/null -c_rehash /usr/lib/ssl/certs + write_file default_mdsd_filename default_mdsd_file true -# we leave clientId blank as long as only 1 managed identity assigned to vmss -# if we have more than 1, we will need to populate with clientId used for off-node scanning -cat >/etc/default/vsa-nodescan-agent.config < "$filename" + else + log "Appending to $filename" + echo "$file_contents" >> "$filename" + fi +} + +# reboot_vm restores all selinux file contexts, waits 30 seconds then reboots +reboot_vm() { + log "starting" + + configure_selinux "true" + (sleep 30 && log "rebooting vm now"; reboot) & +} + +# log is a wrapper for echo that includes the function name +log() { + local -r msg="${1:-"log message is empty"}" + local -r stack_level="${2:-1}" + echo "${FUNCNAME[${stack_level}]}: ${msg}" +} + +# abort is a wrapper for log that exits with an error code +abort() { + local -ri origin_stacklevel=2 + log "${1}" "$origin_stacklevel" + log "Exiting" + exit 1 +} + +export AZURE_CLOUD_NAME="${AZURECLOUDNAME:?"Failed to carry over variables"}" -echo "rebooting" -restorecon -RF /var/log/* -(sleep 30; reboot) & +main "$@" diff --git a/pkg/deploy/generator/scripts/rpVMSS.sh b/pkg/deploy/generator/scripts/rpVMSS.sh index 290b534c1c9..3c00da1185c 100644 --- a/pkg/deploy/generator/scripts/rpVMSS.sh +++ b/pkg/deploy/generator/scripts/rpVMSS.sh @@ -1,48 +1,278 @@ #!/bin/bash -echo "setting ssh password authentication" -# We need to manually set PasswordAuthentication to true in order for the VMSS Access JIT to work -sed -i 's/PasswordAuthentication no/PasswordAuthentication yes/g' /etc/ssh/sshd_config -systemctl reload sshd.service +set -o errexit \ + -o nounset -#Adding retry logic to yum commands in order to avoid stalling out on resource locks -echo "running RHUI fix" -for attempt in {1..5}; do - yum update -y --disablerepo='*' --enablerepo='rhui-microsoft-azure*' && break - if [[ ${attempt} -lt 5 ]]; then sleep 10; else exit 1; fi -done +if [ "${DEBUG:-false}" == true ]; then + set -x +fi -echo "running yum update" -for attempt in {1..5}; do - yum -y -x WALinuxAgent -x WALinuxAgent-udev update --allowerasing && break - if [[ ${attempt} -lt 5 ]]; then sleep 10; else exit 1; fi -done +main() { + parse_run_options "$@" -echo "extending partition table" -# Linux block devices are inconsistently named -# it's difficult to tie the lvm pv to the physical disk using /dev/disk files, which is why lvs is used here -physicalDisk="$(lvs -o devices -a | head -n2 | tail -n1 | cut -d ' ' -f 3 | cut -d \( -f 1 | tr -d '[:digit:]')" -growpart "$physicalDisk" 2 -echo "extending filesystems" -lvextend -l +20%FREE /dev/rootvg/rootlv -xfs_growfs / + configure_sshd + configure_and_install_dnf_pkgs_repos + configure_disk_partitions + configure_logrotate + configure_selinux -lvextend -l +100%FREE /dev/rootvg/varlv -xfs_growfs /var + mkdir -p /var/log/journal + mkdir -p /var/lib/waagent/Microsoft.Azure.KeyVault.Store -echo "importing rpm repositories" -rpm --import https://dl.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-8 -rpm --import https://packages.microsoft.com/keys/microsoft.asc + configure_firewalld_rules + pull_container_images + configure_system_services + reboot_vm +} -for attempt in {1..5}; do - yum -y install https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm && break - if [[ ${attempt} -lt 5 ]]; then sleep 10; else exit 1; fi -done +usage() { + local -n options="$1" + log "$(basename "$0") [$options] + -d Configure Disk Partitions + -p Configure rpm repositories, import required rpm keys, update & install packages with dnf + -l Configure logrotate.conf + -s Make selinux modifications required for ARO RP + -r Configure sshd - Allow password authenticaiton + -f Configure firewalld default zone rules + -u Configure systemd unit files for ARO RP + -i Pull container images + + Note: steps will be executed in the order that flags are provided + " +} -echo "configuring logrotate" -cat >/etc/logrotate.conf <<'EOF' -# see "man logrotate" for details +# parse_run_options takes all arguements passed to main and parses them +# allowing individual step(s) to be ran, rather than all steps +# +# This is useful for local testing, or possibly modifying the bootstrap execution via environment variables in the deployment pipeline +parse_run_options() { + # shellcheck disable=SC2206 + local -a options=(${1:-}) + if [ "${#options[@]}" -eq 0 ]; then + log "Running all steps" + return 0 + fi + + local OPTIND + local -r allowed_options="dplsrfui" + while getopts ${allowed_options} options; do + case "${options}" in + d) + log "Running step configure_disk_partitions" + configure_disk_partitions + ;; + p) + log "Running step configure_and_install_dnf_pkgs_repos" + configure_and_install_dnf_pkgs_repos + ;; + l) + log "Running configure_logrotate" + configure_logrotate + ;; + s) + log "Running configure_selinux" + configure_selinux + ;; + r) + log "Running configure_sshd" + configure_sshd + ;; + f) + log "Running configure_firewalld_rules" + configure_firewalld_rules + ;; + u) + log "Running pull_container_images & configure_system_services" + configure_system_services + ;; + i) + log "Running pull_container_images" + pull_container_images + ;; + *) + usage allowed_options + abort "Unkown option provided" + ;; + esac + done + + exit 0 +} + +# We need to configure PasswordAuthentication to yes in order for the VMSS Access JIT to work +configure_sshd() { + log "starting" + log "setting ssh password authentication" + sed -i 's/PasswordAuthentication no/PasswordAuthentication yes/g' /etc/ssh/sshd_config + + systemctl reload sshd.service + systemctl is-active --quiet sshd || abort "sshd failed to reload" +} + +# configure_and_install_dnf_pkgs_repos +configure_and_install_dnf_pkgs_repos() { + log "starting" + + # transaction attempt retry time in seconds + local -ri retry_wait_time=60 + configure_rhui_repo retry_wait_time + create_azure_rpm_repos retry_wait_time + + local -ar exclude_pkgs=( + "-x WALinuxAgent" + "-x WALinuxAgent-udev" + ) + + dnf_update_pkgs exclude_pkgs retry_wait_time + + local -ra rpm_keys=( + https://dl.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-8 + https://packages.microsoft.com/keys/microsoft.asc + ) + + rpm_import_keys rpm_keys retry_wait_time + + local -ra repo_rpm_pkgs=( + https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm + ) + + local -ra install_pkgs=( + clamav + azsec-clamav + azsec-monitor + azure-cli + azure-mdsd + azure-security + podman + podman-docker + openssl-perl + # hack - we are installing python3 on hosts due to an issue with Azure Linux Extensions https://github.com/Azure/azure-linux-extensions/pull/1505 + python3 + ) + + dnf_install_pkgs repo_rpm_pkgs retry_wait_time + dnf_install_pkgs install_pkgs retry_wait_time +} + +# configure_rhui_repo +configure_rhui_repo() { + log "starting" + + local -ra cmd=( + dnf + update + -y + --disablerepo='*' + --enablerepo='rhui-microsoft-azure*' + ) + + log "running RHUI package updates" + retry cmd "$1" +} + +# retry Adding retry logic to yum commands in order to avoid stalling out on resource locks +retry() { + local -n cmd_retry="$1" + local -n wait_time="$2" + + for attempt in {1..5}; do + log "attempt #${attempt} - ${FUNCNAME[2]}" + ${cmd_retry[@]} & + + wait $! && break + if [[ ${attempt} -lt 5 ]]; then + sleep "$wait_time" + else + abort "attempt #${attempt} - Failed to update packages" + fi + done +} + +# dnf_update_pkgs +dnf_update_pkgs() { + local -n excludes="$1" + log "starting" + + local -ra cmd=( + dnf + -y + ${excludes[@]} + update + --allowerasing + ) + + log "Updating all packages" + retry cmd "$2" +} + +# dnf_install_pkgs +dnf_install_pkgs() { + local -n pkgs="$1" + log "starting" + + local -ra cmd=( + dnf + -y + install + ${pkgs[@]} + ) + + log "Attempting to install packages: ${pkgs[*]}" + retry cmd "$2" +} + +# rpm_import_keys +rpm_import_keys() { + local -n keys="$1" + log "starting" + + + # shellcheck disable=SC2068 + for key in ${keys[@]}; do + if [ ${#keys[@]} -eq 0 ]; then + break + fi + local -a cmd=( + rpm + --import + -v + "$key" + ) + + log "attempt #$attempt - importing rpm repository key $key" + retry cmd "$2" && unset key + done +} + +# configure_disk_partitions +configure_disk_partitions() { + log "starting" + log "extending partition table" + + # Linux block devices are inconsistently named + # it's difficult to tie the lvm pv to the physical disk using /dev/disk files, which is why lvs is used here + physical_disk="$(lvs -o devices -a | head -n2 | tail -n1 | cut -d ' ' -f 3 | cut -d \( -f 1 | tr -d '[:digit:]')" + growpart "$physical_disk" 2 + + log "extending filesystems" + log "extending root lvm" + lvextend -l +20%FREE /dev/rootvg/rootlv + log "growing root filesystem" + xfs_growfs / + + log "extending var lvm" + lvextend -l +100%FREE /dev/rootvg/varlv + log "growing var filesystem" + xfs_growfs /var +} + +# configure_logrotate clobbers /etc/logrotate.conf +configure_logrotate() { + log "starting" + + local -r logrotate_conf_filename='/etc/logrotate.conf' + local -r logrotate_conf_file='# see "man logrotate" for details # rotate log files weekly weekly @@ -61,7 +291,7 @@ compress # RPM packages drop log rotation information into this directory include /etc/logrotate.d -# no packages own wtmp and btmp -- we'll rotate them here +# no packages own wtmp and btmp -- we will rotate them here /var/log/wtmp { monthly create 0664 root utmp @@ -74,12 +304,17 @@ include /etc/logrotate.d monthly create 0600 root utmp rotate 1 +}' + + write_file logrotate_conf_filename logrotate_conf_file true } -EOF -echo "configuring yum repository and running yum update" -cat >/etc/yum.repos.d/azure.repo <<'EOF' -[azure-cli] +# create_azure_rpm_repos creates /etc/yum.repos.d/azure.repo repository file +create_azure_rpm_repos() { + log "starting" + + local -r azure_repo_filename='/etc/yum.repos.d/azure.repo' + local -r azure_repo_file='[azure-cli] name=azure-cli baseurl=https://packages.microsoft.com/yumrepos/azure-cli enabled=yes @@ -89,63 +324,151 @@ gpgcheck=yes name=azurecore baseurl=https://packages.microsoft.com/yumrepos/azurecore enabled=yes -gpgcheck=no -EOF +gpgcheck=no' -semanage fcontext -a -t var_log_t "/var/log/journal(/.*)?" -mkdir -p /var/log/journal + write_file azure_repo_filename azure_repo_file true +} -for attempt in {1..5}; do -yum -y install clamav azsec-clamav azsec-monitor azure-cli azure-mdsd azure-security podman podman-docker openssl-perl python3 && break - # hack - we are installing python3 on hosts due to an issue with Azure Linux Extensions https://github.com/Azure/azure-linux-extensions/pull/1505 - if [[ ${attempt} -lt 5 ]]; then sleep 10; else exit 1; fi -done +# configure_selinux +configure_selinux() { + log "starting" + + local -r relabel="${1:-false}" -# https://access.redhat.com/security/cve/cve-2020-13401 -echo "applying firewall rules" -cat >/etc/sysctl.d/02-disable-accept-ra.conf <<'EOF' -net.ipv6.conf.all.accept_ra=0 -EOF + already_defined_ignore_error="File context for /var/log/journal(/.*)? already defined" + semanage fcontext -a -t var_log_t "/var/log/journal(/.*)?" || log "$already_defined_ignore_error" + chcon -R system_u:object_r:var_log_t:s0 /var/opt/microsoft/linuxmonagent -cat >/etc/sysctl.d/01-disable-core.conf <<'EOF' -kernel.core_pattern = |/bin/true -EOF -sysctl --system + if "$relabel"; then + restorecon -RF /var/log/* || log "$already_defined_ignore_error" + fi +} + +# configure_firewalld_rules +configure_firewalld_rules() { + log "starting" + + # https://access.redhat.com/security/cve/cve-2020-13401 + local -r prefix="/etc/sysctl.d" + local -r disable_accept_ra_conf_filename="$prefix/02-disable-accept-ra.conf" + local -r disable_accept_ra_conf_file="net.ipv6.conf.all.accept_ra=0" -firewall-cmd --add-port=443/tcp --permanent -firewall-cmd --add-port=444/tcp --permanent -firewall-cmd --add-port=445/tcp --permanent -firewall-cmd --add-port=2222/tcp --permanent + write_file disable_accept_ra_conf_filename disable_accept_ra_conf_file true -export AZURE_CLOUD_NAME=$AZURECLOUDNAME + local -r disable_core_filename="$prefix/01-disable-core.conf" + local -r disable_core_file="kernel.core_pattern = |/bin/true + " + write_file disable_core_filename disable_core_file true -echo "logging into prod acr" -az login -i --allow-no-subscriptions + sysctl --system + + local -ra enable_ports=( + "443/tcp" + "444/tcp" + "445/tcp" + "2222/tcp" + ) + + log "Enabling ports ${enable_ports[*]} on default firewalld zone" + # shellcheck disable=SC2068 + for port in ${enable_ports[@]}; do + log "Enabling port $port now" + firewall-cmd "--add-port=$port" + done + + firewall-cmd --runtime-to-permanent +} -# Suppress emulation output for podman instead of docker for az acr compatability -mkdir -p /etc/containers/ -touch /etc/containers/nodocker +# pull_container_images +pull_container_images() { + log "starting" + + # The managed identity that the VM runs as only has a single roleassignment. + # This role assignment is ACRPull which is not necessarily present in the + # subscription we're deploying into. If the identity does not have any + # role assignments scoped on the subscription we're deploying into, it will + # not show on az login -i, which is why the below line is commented. + # az account set -s "$SUBSCRIPTIONID" + az login -i --allow-no-subscriptions + + # Suppress emulation output for podman instead of docker for az acr compatability + mkdir -p /etc/containers/ + mkdir -p /root/.docker + touch /etc/containers/nodocker + + # This name is used in the case that az acr login searches for this in it's environment + local -r REGISTRY_AUTH_FILE="/root/.docker/config.json" + + log "logging into prod acr" + az acr login --name "$(sed -e 's|.*/||' <<<"$ACRRESOURCEID")" + + MDMIMAGE="${RPIMAGE%%/*}/${MDMIMAGE##*/}" + docker pull "$MDMIMAGE" + docker pull "$RPIMAGE" + docker pull "$FLUENTBITIMAGE" + + az logout +} -mkdir -p /root/.docker -REGISTRY_AUTH_FILE=/root/.docker/config.json az acr login --name "$(sed -e 's|.*/||' <<<"$ACRRESOURCEID")" +# configure_system_services creates, configures, and enables the following systemd services and timers +# services +# fluentbit +# mdm +# mdsd +# arp-rp +# aro-dbtoken +# aro-monitor +# aro-portal +configure_system_services() { + configure_service_fluentbit + configure_service_mdm + configure_timers_mdm_mdsd + configure_service_aro_rp + configure_service_aro_dbtoken + configure_service_aro_monitor + configure_service_aro_portal + configure_service_mdsd +} -MDMIMAGE="${RPIMAGE%%/*}/${MDMIMAGE##*/}" -docker pull "$MDMIMAGE" -docker pull "$RPIMAGE" -docker pull "$FLUENTBITIMAGE" +# enable_aro_services enables all services required for aro rp +enable_aro_services() { + log "starting" + + local -ra aro_services=( + "aro-dbtoken" + "aro-monitor" + "aro-portal" + "aro-rp" + "auoms" + "azsecd" + "azsecmond" + "mdsd" + "mdm" + "chronyd" + "fluentbit" + ) + log "enabling aro services ${aro_services[*]}" + # shellcheck disable=SC2068 + for service in ${aro_services[@]}; do + log "Enabling $service now" + systemctl enable "$service.service" + done +} -az logout +# configure_service_fluentbit +configure_service_fluentbit() { + log "starting" + log "configuring fluentbit service" -echo "configuring fluentbit service" -mkdir -p /etc/fluentbit/ -mkdir -p /var/lib/fluent + mkdir -p /etc/fluentbit/ + mkdir -p /var/lib/fluent -cat >/etc/fluentbit/fluentbit.conf <<'EOF' -[INPUT] - Name systemd - Tag journald - Systemd_Filter _COMM=aro - DB /var/lib/fluent/journaldb + local -r fluentbit_conf_filename='/etc/fluentbit/fluentbit.conf' + local -r fluentbit_conf_file="[INPUT] +Name systemd +Tag journald +Systemd_Filter _COMM=aro +DB /var/lib/fluent/journaldb [FILTER] Name modify @@ -173,13 +496,18 @@ cat >/etc/fluentbit/fluentbit.conf <<'EOF' [OUTPUT] Name forward Match * - Port 29230 -EOF + Port 29230" + + write_file fluentbit_conf_filename fluentbit_conf_file true -echo "FLUENTBITIMAGE=$FLUENTBITIMAGE" >/etc/sysconfig/fluentbit + local -r sysconfig_fluentbit_filename='/etc/sysconfig/fluentbit' + local -r sysconfig_fluentbit_file="FLUENTBITIMAGE=$FLUENTBITIMAGE" -cat >/etc/systemd/system/fluentbit.service <<'EOF' -[Unit] + write_file sysconfig_fluentbit_filename sysconfig_fluentbit_file true + + local -r fluentbit_service_filename='/etc/systemd/system/fluentbit.service' + + local -r fluentbit_service_file="[Unit] After=network-online.target Wants=network-online.target StartLimitIntervalSec=0 @@ -209,28 +537,61 @@ RestartSec=5 StartLimitInterval=0 [Install] -WantedBy=multi-user.target -EOF +WantedBy=multi-user.target" -mkdir /etc/aro-rp -base64 -d <<<"$ADMINAPICABUNDLE" >/etc/aro-rp/admin-ca-bundle.pem -if [[ -n "$ARMAPICABUNDLE" ]]; then - base64 -d <<<"$ARMAPICABUNDLE" >/etc/aro-rp/arm-ca-bundle.pem -fi -chown -R 1000:1000 /etc/aro-rp + write_file fluentbit_conf_filename fluentbit_conf_file true +} + +# configure_certs +configure_certs() { + log "starting" + + mkdir /etc/aro-rp + base64 -d <<<"$ADMINAPICABUNDLE" >/etc/aro-rp/admin-ca-bundle.pem + if [[ -n "$ARMAPICABUNDLE" ]]; then + base64 -d <<<"$ARMAPICABUNDLE" >/etc/aro-rp/arm-ca-bundle.pem + fi + chown -R 1000:1000 /etc/aro-rp + + # setting MONITORING_GCS_AUTH_ID_TYPE=AuthKeyVault seems to have caused mdsd not + # to honour SSL_CERT_FILE any more, heaven only knows why. + mkdir -p /usr/lib/ssl/certs + csplit -f /usr/lib/ssl/certs/cert- -b %03d.pem /etc/pki/tls/certs/ca-bundle.crt /^$/1 "{*}" >/dev/null + c_rehash /usr/lib/ssl/certs + +# we leave clientId blank as long as only 1 managed identity assigned to vmss +# if we have more than 1, we will need to populate with clientId used for off-node scanning + local -r nodescan_agent_filename="/etc/default/vsa-nodescan-agent.config" + local -r nodescan_agent_file="{ + \"Nice\": 19, + \"Timeout\": 10800, + \"ClientId\": \"\", + \"TenantId\": $AZURESECPACKVSATENANTID, + \"QualysStoreBaseUrl\": $AZURESECPACKQUALYSURL, + \"ProcessTimeout\": 300, + \"CommandDelay\": 0 + }" + + write_file nodescan_agent_filename nodescan_agent_file true +} -echo "configuring mdm service" -cat >/etc/sysconfig/mdm </etc/systemd/system/mdm.service <<'EOF' -[Unit] + mkdir -p /var/etw + local -r mdm_service_filename="/etc/systemd/system/mdm.service" + local -r mdm_service_file="[Unit] After=network-online.target Wants=network-online.target @@ -261,12 +622,157 @@ RestartSec=1 StartLimitInterval=0 [Install] -WantedBy=multi-user.target -EOF +WantedBy=multi-user.target" + + write_file mdm_service_filename mdm_service_file true +} + +# configure_timers_mdm_mdsd +configure_timers_mdm_mdsd() { + log "starting" + + for var in "mdsd" "mdm"; do + local download_creds_service_filename="/etc/systemd/system/download-$var-credentials.service" + local download_creds_service_file="[Unit] +Description=Periodic $var credentials refresh + +[Service] +Type=oneshot +ExecStart=/usr/local/bin/download-credentials.sh $var" + + write_file download_creds_service_filename download_creds_service_file true + + local download_creds_timer_filename="/etc/systemd/system/download-$var-credentials.timer" + local download_creds_timer_file="[Unit] +Description=Periodic $var credentials refresh +After=network-online.target +Wants=network-online.target + +[Timer] +OnBootSec=0min +OnCalendar=0/12:00:00 +AccuracySec=5s + +[Install] +WantedBy=timers.target" + + write_file download_creds_timer_filename download_creds_timer_file true + done + + local -r download_creds_script_filename="/usr/local/bin/download-credentials.sh" + local -r download_creds_script_file="#!/bin/bash +set -eu + +COMPONENT=\$1 +echo \"Download \$COMPONENT credentials\" + +TEMP_DIR=\"\$(mktemp -d)\" +export AZURE_CONFIG_DIR=\"\$(mktemp -d)\" + +echo \"Logging into Azure...\" +RETRIES=3 +while [[ \$RETRIES -gt 0 ]]; do + if az login -i --allow-no-subscriptions + then + echo \"az login successful\" + break + else + echo \"az login failed. Retrying...\" + let RETRIES-=1 + sleep 5 + fi +done + +trap \"cleanup\" EXIT + +cleanup() { + az logout + [[ \$TEMP_DIR =~ /tmp/.+ ]] && rm -rf \$TEMP_DIR + [[ \$AZURE_CONFIG_DIR =~ /tmp/.+ ]] && rm -rf \$AZURE_CONFIG_DIR +} + +if [[ \$COMPONENT = \"mdm\" ]]; then + CURRENT_CERT_FILE=\"/etc/mdm.pem\" +elif [[ \$COMPONENT\ = \"mdsd\" ]]; then + CURRENT_CERT_FILE=\"/var/lib/waagent/Microsoft.Azure.KeyVault.Store/mdsd.pem\" +else + echo Invalid usage && exit 1 +fi + +SECRET_NAME=\"rp-\${COMPONENT}\" +NEW_CERT_FILE=\"\$TEMP_DIR/\$COMPONENT.pem\" +for attempt in {1..5}; do + az keyvault \ + secret \ + download \ + --file \"\$NEW_CERT_FILE\" \ + --id \"https://$KEYVAULTPREFIX-svc.$KEYVAULTDNSSUFFIX/secrets/\$SECRET_NAME\" \ + && break + if [[ \$attempt -lt 5 ]]; then sleep 10; else exit 1; fi +done + +if [ -f \$NEW_CERT_FILE ]; then + if [[ \$COMPONENT = \"mdsd\" ]]; then + chown syslog:syslog \$NEW_CERT_FILE + else + sed -i -ne '1,/END CERTIFICATE/ p' \$NEW_CERT_FILE + fi + + new_cert_sn=\"\$(openssl x509 -in \"\$NEW_CERT_FILE\" -noout -serial | awk -F= '{print \$2}')\" + current_cert_sn=\"\$(openssl x509 -in \"\$CURRENT_CERT_FILE\" -noout -serial | awk -F= '{print \$2}')\" + if [[ ! -z \$new_cert_sn ]] && [[ \$new_cert_sn != \"\$current_cert_sn\" ]]; then + echo updating certificate for \$COMPONENT + chmod 0600 \$NEW_CERT_FILE + mv \$NEW_CERT_FILE \$CURRENT_CERT_FILE + fi +else + echo Failed to refresh certificate for \$COMPONENT && exit 1 +fi" + + write_file download_creds_script_filename download_creds_script_file true + + chmod u+x /usr/local/bin/download-credentials.sh + + systemctl enable download-mdsd-credentials.timer + systemctl enable download-mdm-credentials.timer + + /usr/local/bin/download-credentials.sh mdsd + /usr/local/bin/download-credentials.sh mdm + + local -r MDSDCERTIFICATESAN="$(openssl x509 -in /var/lib/waagent/Microsoft.Azure.KeyVault.Store/mdsd.pem -noout -subject | sed -e 's/.*CN = //')" + local -r watch_mdm_creds_service_filename="/etc/systemd/system/watch-mdm-credentials.service" + local -r watch_mdm_creds_service_file="[Unit] +Description=Watch for changes in mdm.pem and restarts the mdm service + +[Service] +Type=oneshot +ExecStart=/usr/bin/systemctl restart mdm.service + +[Install] +WantedBy=multi-user.target" + + write_file watch_mdm_creds_service_filename watch_mdm_creds_service_file true + + local -r watch_mdm_creds_path_filename='/etc/systemd/system/watch-mdm-credentials.path' + local -r watch_mdm_creds_path_file='[Path] +PathModified=/etc/mdm.pem + +[Install] +WantedBy=multi-user.target' + + write_file watch_mdm_creds_path_filename watch_mdm_creds_path_file true -echo "configuring aro-rp service" -cat >/etc/sysconfig/aro-rp </etc/systemd/system/aro-rp.service <<'EOF' -[Unit] + local -r aro_rp_service_filename='/etc/systemd/system/aro-rp.service' + local -r aro_rp_service_file="[Unit] After=network-online.target Wants=network-online.target @@ -345,22 +852,28 @@ RestartSec=1 StartLimitInterval=0 [Install] -WantedBy=multi-user.target -EOF +WantedBy=multi-user.target" -echo "configuring aro-dbtoken service" -cat >/etc/sysconfig/aro-dbtoken </etc/systemd/system/aro-dbtoken.service <<'EOF' -[Unit] + local -r aro_dbtoken_service_filename='/etc/systemd/system/aro-dbtoken.service' + local -r aro_dbtoken_service_file="[Unit] After=network-online.target Wants=network-online.target @@ -391,14 +904,20 @@ RestartSec=1 StartLimitInterval=0 [Install] -WantedBy=multi-user.target -EOF +WantedBy=multi-user.target" -# DOMAIN_NAME, CLUSTER_MDSD_ACCOUNT, CLUSTER_MDSD_CONFIG_VERSION, GATEWAY_DOMAINS, GATEWAY_RESOURCEGROUP, MDSD_ENVIRONMENT CLUSTER_MDSD_NAMESPACE -# are not used, but can't easily be refactored out. Should be revisited in the future. -echo "configuring aro-monitor service" -cat >/etc/sysconfig/aro-monitor </etc/systemd/system/aro-monitor.service <<'EOF' -[Unit] + local -r aro_monitor_service_filename='/etc/systemd/system/aro-monitor.service' + local -r aro_monitor_service_file="[Unit] After=network-online.target Wants=network-online.target @@ -452,12 +972,17 @@ RestartSec=1 StartLimitInterval=0 [Install] -WantedBy=multi-user.target -EOF +WantedBy=multi-user.target" -echo "configuring aro-portal service" -cat >/etc/sysconfig/aro-portal </etc/systemd/system/aro-portal.service <<'EOF' -[Unit] + write_file aro_portal_service_conf_filename aro_portal_service_conf_file true + + local -r aro_portal_service_filename='/etc/systemd/system/aro-portal.service' + local -r aro_portal_service_file="[Unit] After=network-online.target Wants=network-online.target StartLimitInterval=0 @@ -501,147 +1027,27 @@ Restart=always RestartSec=1 [Install] -WantedBy=multi-user.target -EOF - -echo "configuring mdsd and mdm services" -chcon -R system_u:object_r:var_log_t:s0 /var/opt/microsoft/linuxmonagent - -mkdir -p /var/lib/waagent/Microsoft.Azure.KeyVault.Store - -for var in "mdsd" "mdm"; do -cat >/etc/systemd/system/download-$var-credentials.service </etc/systemd/system/download-$var-credentials.timer </usr/local/bin/download-credentials.sh </etc/systemd/system/watch-mdm-credentials.service </etc/systemd/system/watch-mdm-credentials.path </etc/systemd/system/mdsd.service.d/override.conf <<'EOF' -[Unit] -After=network-online.target -EOF - -cat >/etc/default/mdsd </dev/null -c_rehash /usr/lib/ssl/certs + write_file default_mdsd_filename default_mdsd_file true -# we leave clientId blank as long as only 1 managed identity assigned to vmss -# if we have more than 1, we will need to populate with clientId used for off-node scanning -cat >/etc/default/vsa-nodescan-agent.config < "$filename" + else + log "Appending to $filename" + echo "$file_contents" >> "$filename" + fi +} + +# reboot_vm restores all selinux file contexts, waits 30 seconds then reboots +reboot_vm() { + log "starting" + + configure_selinux "true" + (sleep 30 && log "rebooting vm now"; reboot) & +} + +# log is a wrapper for echo that includes the function name +log() { + local -r msg="${1:-"log message is empty"}" + local -r stack_level="${2:-1}" + echo "${FUNCNAME[${stack_level}]}: ${msg}" +} + +# abort is a wrapper for log that exits with an error code +abort() { + local -ri origin_stacklevel=2 + log "${1}" "$origin_stacklevel" + log "Exiting" + exit 1 +} + +export AZURE_CLOUD_NAME="${AZURECLOUDNAME:?"Failed to carry over variables"}" -echo "rebooting" -restorecon -RF /var/log/* -(sleep 30; reboot) & +main "$@"