Skip to content

chore(ci): add manual ARO disconnected scripts - #5313

Merged
openshift-merge-bot[bot] merged 4 commits into
redhat-developer:mainfrom
zdrapela:azure-disconnected-scripts
Aug 31, 2026
Merged

chore(ci): add manual ARO disconnected scripts#5313
openshift-merge-bot[bot] merged 4 commits into
redhat-developer:mainfrom
zdrapela:azure-disconnected-scripts

Conversation

@zdrapela

@zdrapela zdrapela commented Aug 31, 2026

Copy link
Copy Markdown
Member

Summary

  • Move the manual-only ARO disconnected cluster workflow from a private repo in RH GitLab to .ci/manual/aro-disconnected/.
  • Iterate Azure Firewall rules and protect generated credentials and SSH keys.
  • Document the workflow, source guide, pinned tool downloads, and cleanup.

Testing

  • bash .ci/manual/aro-disconnected/test-firewall-rules.sh
  • bash .ci/manual/aro-disconnected/test-install-configuration.sh
  • bash -n .ci/manual/aro-disconnected/*.sh
  • yarn shellcheck and yarn prettier:check from .ci
  • No live Azure provisioning was performed.

@openshift-ci

openshift-ci Bot commented Aug 31, 2026

Copy link
Copy Markdown

Skipping CI for Draft Pull Request.
If you want CI signal for your change, please convert it to an actual PR.
You can still manually trigger a test run with /test all

@sonarqubecloud

Copy link
Copy Markdown

@codecov

codecov Bot commented Aug 31, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 59.69%. Comparing base (10310a5) to head (5906de7).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #5313      +/-   ##
==========================================
- Coverage   63.68%   59.69%   -3.99%     
==========================================
  Files         121      109      -12     
  Lines        2288     2062     -226     
  Branches      503      500       -3     
==========================================
- Hits         1457     1231     -226     
+ Misses        830      829       -1     
- Partials        1        2       +1     
Flag Coverage Δ
rhdh 59.69% <ø> (-3.99%) ⬇️
Components Coverage Δ
Backend plugins ∅ <ø> (∅)
Backend app 69.69% <ø> (ø)
Frontend app 58.82% <ø> (ø)
Plugin utils ∅ <ø> (∅)

Continue to review full report in Codecov by Harness.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 10310a5...5906de7. Read the comment docs.

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@zdrapela zdrapela changed the title ci: add manual ARO disconnected scripts chore(ci): add manual ARO disconnected scripts Aug 31, 2026
@zdrapela
zdrapela marked this pull request as ready for review August 31, 2026 11:14
@rhdh-qodo-merge

rhdh-qodo-merge Bot commented Aug 31, 2026

Copy link
Copy Markdown

PR Summary by Qodo

Add hardened manual ARO disconnected provisioning workflow

✨ Enhancement 🧪 Tests 📝 Documentation ⚙️ Configuration changes 🕐 40+ Minutes

Grey Divider

AI Description

• Add scripts provisioning disconnected ARO networking, firewall, cluster, and bastion resources.
• Secure generated credentials, restrict bastion SSH, and verify pinned tooling downloads.
• Document configuration and cleanup, with mocked tests for firewall and setup safeguards.
Diagram

graph TD
  CONFIG["Local Config"] --> INSTALL["Provision Script"] --> NETWORK["Azure Network"] --> CLUSTER["Private ARO"]
  INSTALL --> BASTION["Bastion VM"] --> SETUP["Tool Setup"] --> CLUSTER
  RULES["Firewall Script"] --> NETWORK
  TESTS["Shell Tests"] --> INSTALL
  TESTS --> RULES
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Declarative Azure IaC
  • ➕ Provides idempotent plans, dependency tracking, and clearer teardown semantics.
  • ➕ Enables policy validation and reusable environment modules.
  • ➖ Adds Terraform or Bicep state and tooling overhead for a manual-only workflow.
  • ➖ May diverge from the command-oriented upstream ARO disconnected installation guide.

Recommendation: The shell-based approach is appropriate for migrating a manual, guide-aligned workflow with limited CI integration. If provisioning becomes frequent or shared across environments, migrate the Azure resource layer to Bicep or Terraform while retaining the bastion setup and verification scripts.

Files changed (9) +856 / -1

Tests (2) +126 / -0
test-firewall-rules.shTest firewall rule iteration and replacement +100/-0

Test firewall rule iteration and replacement

• Uses a mocked Azure CLI to verify every configured rule is created, collection action and priority are applied once, and confirmed replacement deletes then recreates the collection.

.ci/manual/aro-disconnected/test-firewall-rules.sh

test-install-configuration.shTest provisioning hardening markers +26/-0

Test provisioning hardening markers

• Checks the example configuration and scripts for valid bastion naming, source-address restrictions, explicit NSG use, protected key storage, extension upgrades, pinned versions, checksum verification, and documented file transfer.

.ci/manual/aro-disconnected/test-install-configuration.sh

Documentation (1) +94 / -0
README.mdDocument the manual disconnected ARO workflow +94/-0

Document the manual disconnected ARO workflow

• Explains prerequisites, configuration, provisioning, firewall updates, bastion setup, security expectations, upstream guidance, and resource-group cleanup. It also warns that restricted outbound traffic can conflict with ARO support policy.

.ci/manual/aro-disconnected/README.md

Other (6) +636 / -1
.env.exampleDefine disconnected ARO deployment defaults +21/-0

Define disconnected ARO deployment defaults

• Adds a copyable environment template for Azure naming, location, firewall allow-lists, OpenShift version, bastion restrictions, and local secret paths. Sensitive values remain outside the template.

.ci/manual/aro-disconnected/.env.example

.gitignoreExclude generated secrets and local deployment artifacts +8/-0

Exclude generated secrets and local deployment artifacts

• Ignores local environment files, pull secrets, access information, generated SSH keys, and certificate-style key files.

.ci/manual/aro-disconnected/.gitignore

create-azure-firewall-rules.shCreate ordered workload firewall rules +162/-0

Create ordered workload firewall rules

• Adds a local Azure CLI workflow that validates prerequisites and the target firewall, prompts before replacing an existing collection, and iterates synchronized rule names and FQDN lists. Collection action and priority are set only when creating the first rule.

.ci/manual/aro-disconnected/create-azure-firewall-rules.sh

install-aro-disconnected.shProvision a secured disconnected ARO environment +312/-0

Provision a secured disconnected ARO environment

• Creates the resource group, segmented VNet, Azure Firewall, routes, private ARO cluster, restricted bastion NSG, and bastion VM. It validates configuration, removes temporary installer egress, stores SSH keys under an ignored local directory, and writes credentials to a [mode-0600](https://redhat.atlassian.net/browse/mode-0600) access file.

.ci/manual/aro-disconnected/install-aro-disconnected.sh

setup-bastion.shInstall verified cluster tooling on the bastion +133/-0

Install verified cluster tooling on the bastion

• Installs pinned oc, Helm, opm, and umoci artifacts after SHA-256 verification, plus Podman and Skopeo from system packages. It logs into ARO, checks outbound connectivity, enables the internal registry, and expands bastion logical volumes.

.ci/manual/aro-disconnected/setup-bastion.sh

extensions.jsonRemove the ShellCheck editor recommendation +0/-1

Remove the ShellCheck editor recommendation

• Drops the dedicated ShellCheck VS Code extension from the workspace recommendations while retaining the Bash language extension.

.vscode/extensions.json

@rhdh-qodo-merge

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (3) 📘 Rule violations (0) 🔗 Cross-repo conflicts (0) 📜 Skill insights (0)

Grey Divider


Action required

1. Default cluster name invalid 🐞 Bug ≡ Correctness
Description
The example configuration derives CLUSTER as aro-disconnected_6, but ARO cluster names do not
permit underscores, so the shipped workflow fails at az aro create after provisioning the network
and firewall. The installer validates the bastion name but never rejects the invalid cluster name
before creating resources.
Code

.ci/manual/aro-disconnected/.env.example[9]

+CLUSTER=${BASE_NAME}_${SUFFIX}
Relevance

●●● Strong

Invalid default cluster naming is a deterministic provisioning failure; accepted history favors
fixing concrete configuration defects.

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The example combines BASE_NAME and SUFFIX with _, producing aro-disconnected_6; that value
is passed unchanged as the ARO name after all network and firewall resources have already been
created.

.ci/manual/aro-disconnected/.env.example[5-10]
.ci/manual/aro-disconnected/install-aro-disconnected.sh[225-236]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The default `CLUSTER` value contains an underscore and is not a valid ARO cluster name, causing the installer to fail after creating prerequisite Azure resources.

## Issue Context
Use a valid separator in the example and validate `CLUSTER` before any Azure resources are created.

## Fix Focus Areas
- .ci/manual/aro-disconnected/.env.example[5-10]
- .ci/manual/aro-disconnected/install-aro-disconnected.sh[55-77]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

2. Invalid CIDRs pass validation 🐞 Bug ≡ Correctness
Description
The bastion source check accepts impossible values such as 999.999.999.999/99 because it validates
only digit shape, not IPv4 octet or CIDR ranges. Such input reaches the NSG rule only after the ARO
cluster has been created, where Azure rejects it and the script exits without creating the bastion.
Code

.ci/manual/aro-disconnected/install-aro-disconnected.sh[R67-70]

+if [[ ! "$BASTION_SOURCE_ADDRESS_PREFIX" =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}(/[0-9]{1,2})?$ ]]; then
+  printf 'BASTION_SOURCE_ADDRESS_PREFIX must be an IPv4 address or CIDR: %s\n' \
+    "$BASTION_SOURCE_ADDRESS_PREFIX" >&2
+  exit 1
Relevance

●●● Strong

Regex-only IP validation admits invalid Azure NSG inputs; this is a concrete correctness defect with
an obvious local fix.

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The regular expression permits any one-to-three-digit octet and any one-to-two-digit prefix; the
unchecked value is later supplied to az network nsg rule create, after az aro create completes.

.ci/manual/aro-disconnected/install-aro-disconnected.sh[67-71]
.ci/manual/aro-disconnected/install-aro-disconnected.sh[225-236]
.ci/manual/aro-disconnected/install-aro-disconnected.sh[256-265]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`BASTION_SOURCE_ADDRESS_PREFIX` validation accepts out-of-range IPv4 octets and CIDR lengths, allowing a late installer failure.

## Issue Context
Reject octets above 255 and prefix lengths above 32 before any Azure resources are created.

## Fix Focus Areas
- .ci/manual/aro-disconnected/install-aro-disconnected.sh[67-71]
- .ci/manual/aro-disconnected/test-install-configuration.sh[7-25]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. Password exposed in argv 🐞 Bug ⛨ Security
Description
setup-bastion.sh expands the kubeadmin password into oc login's command-line arguments, making
the cluster-admin credential visible through process inspection while the command runs. This defeats
the PR's credential-protection goal on a bastion with any additional local user or process
visibility.
Code

.ci/manual/aro-disconnected/setup-bastion.sh[89]

+oc login "$API_SERVER" --username kubeadmin --password "$KUBEADMIN_PASSWORD"
Relevance

●●● Strong

Credentials in login command arguments are exposed to process inspection; similar oc login
credential handling was accepted recently.

PR-#4800

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The README instructs the operator to export KUBEADMIN_PASSWORD, and the setup script then
interpolates that secret directly after the --password option.

.ci/manual/aro-disconnected/setup-bastion.sh[10-13]
.ci/manual/aro-disconnected/setup-bastion.sh[88-89]
.ci/manual/aro-disconnected/README.md[71-79]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The kubeadmin password is passed directly in `oc login` process arguments and can be observed by other local processes while login runs.

## Issue Context
Authenticate without placing the secret in argv, for example by using a protected temporary request/config mechanism supported by the workflow, and securely remove temporary credential material.

## Fix Focus Areas
- .ci/manual/aro-disconnected/setup-bastion.sh[88-90]
- .ci/manual/aro-disconnected/README.md[71-79]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Context sources
✅ Compliance rules (platform): 46 rules
✅ Cross-repo context — repo relationships

Grey Divider

Tip of the day
💡 Did you know, you can type 'qodo, fix this' on a finding and the fix lands right on your PR

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

@github-actions

Copy link
Copy Markdown
Contributor

Image was built and published successfully. It is available at:

@subhashkhileri subhashkhileri left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/lgtm

@openshift-ci openshift-ci Bot added the lgtm label Aug 31, 2026
@openshift-merge-bot
openshift-merge-bot Bot merged commit c4c180f into redhat-developer:main Aug 31, 2026
38 of 41 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants