Skip to content

Feat/ip list get#423

Merged
dthampy merged 12 commits into
adobe:masterfrom
pru55e11:feat/ip-list-get
Jun 1, 2026
Merged

Feat/ip list get#423
dthampy merged 12 commits into
adobe:masterfrom
pru55e11:feat/ip-list-get

Conversation

@dthampy

@dthampy dthampy commented May 27, 2026

Copy link
Copy Markdown
Contributor

Description

This PR adds a new sub command aio runtime ip-list get, that fetches the Adobe I/O Runtime egress IP allowlist from an IMS-authenticated backend service. Supports per-region filtering (--region), structured --json output, and an interactive or programmatic (--accept-terms --contact-email) terms-acceptance flow on first use.

Related Issue

Motivation and Context

Customers running App Builder / I/O Runtime workloads behind corporate egress firewalls need a self-service way to retrieve the current set of outbound IP addresses for their network allowlists. Today this information is only available via support tickets. Hence exposing it through the standard aio CLI removes that round-trip and provides a scriptable source of truth.

How Has This Been Tested?

added new unit tests and verified via npm test
manually tested the workflow against the backend using different IMS orgs by aio plugins link the local cloned repo

Screenshots (if appropriate):

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)

Checklist:

  • I have signed the Adobe Open Source CLA.
  • My code follows the code style of this project.
  • My change requires a change to the documentation.
  • I have updated the documentation accordingly.
  • I have read the CONTRIBUTING document.
  • I have added tests to cover my changes.
  • All new and existing tests passed.

pru55e11 and others added 7 commits April 21, 2026 11:06
Adds an IMS-authenticated self-service command that fetches the Adobe I/O
Runtime egress IP allowlist from the ip-list-service.

- `aio runtime ip-list get` [--region <r>] [--accept-terms --contact-email <e>] [--json]
- First-use terms acceptance flow (interactive via inquirer, or
  non-interactive via flags), mirroring the action-level surface
- Hits the runtime host directly to sidestep the CloudFront 503 masking
  that would otherwise hide the 403 TERMS_REQUIRED response (see ACNA-4547)
- Pure-JS helpers are exported for unit tests; 28 Jest tests cover flag
  validation, terms gating, retry-after-accept, interactive decline,
  JSON mode, region filtering, and server-error surfacing
- No regressions across the existing 822 plugin tests (total 850 passing)
The ip-list-service `get-ip-list` action returns `regions[region]` as a
flat array of CIDR strings, not a nested `{ cidrs: [...] }` object. The
human formatter in v1 assumed the latter and rendered "0 CIDRs" for
every region on the first real end-to-end Stage run.

- Normalize both shapes in formatHumanOutput; array form is the primary
  wire format, nested form is tolerated as defense-in-depth
- Update the IP_LIST_OK test fixture to match the actual Stage response
- Add a regression test for the legacy nested shape
- Verified end-to-end against Stage:
  `aio runtime ip-list get` → 4 regions, 3 CIDRs each
  `aio runtime ip-list get --region emea` → just emea
  `aio runtime ip-list get --region mars` → client-side validation error
Matches the server-side cross-org refactor
(OneAdobe/ip-list-service#9): the service no longer runs under the
require-adobe-auth gateway wrapper, so there's no point attaching
Authorization / x-gw-ims-org-id headers to every request. Instead
we POST `{token, imsOrgId, surface, [region]}` to both endpoints
and the in-action auth helper validates the token + org membership.

This lets the CLI serve authenticated users from any Adobe org, not
just whichever org happens to own the service's App Builder workspace.

Unit tests updated to assert the new wire shape + guard against
regressions where the old header-based auth sneaks back in.

Verified end-to-end against Stage:
  $ aio runtime ip-list get
  Adobe I/O Runtime egress IPs
  ... (real CIDRs) ...
inquirer v9 went ESM-first; its CJS build exposes the public API under
`.default` instead of at the module root, so `require('inquirer').prompt`
was undefined and the interactive acceptance path crashed with
"inquirer.prompt is not a function" before ever reaching stdin.

Normalize with `require('inquirer').default || require('inquirer')` so
the command keeps working against inquirer v8 (flat export) and v12
(default-wrapped). Tighten the test's module mock to expose the same
jest.fn() under both the flat and `.default` shapes so assertions stay
agnostic to the inquirer major version.
…rompt vs flag

When the user runs:
    aio runtime ip-list get
...and gets the TERMS_REQUIRED 403, the command prompts them via
inquirer and posts `acceptanceMode: "interactive"` to the service.
When the user runs:
    aio runtime ip-list get --accept-terms --contact-email ...
...no prompt fires, so the command posts `acceptanceMode:
"programmatic"` instead.

The service records this verbatim on the terms_acceptance document so
the admin dashboard can tell a human-attested acceptance from a
scripted one. Tests assert both paths send the right mode alongside
the existing contactEmail / surface / token / imsOrgId payload.
@codecov

codecov Bot commented May 27, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@purplecabbage purplecabbage 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.

I added a few minor nits, questions really.

Comment thread src/commands/runtime/ip-list/get.js Outdated
]

IndexCommand.examples = [
'$ aio runtime ip-list get',

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.

Why do we need a get subcommand? Are there plans for set, delete, search? We have an alias already for aio rt ip-list ... why do we need the get?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Hey @pru55e11 what's your take on collapsing the subcommand from aio rt ip-list get( the actual fetch command ) --> aio rt ip-list
If we want to have additional subcommands like aio rt ip-list status or aio rt ip-list reset etc in the future then we can keep the verb. If not, Jesse is right

Comment thread src/commands/runtime/ip-list/get.js Outdated
@dthampy dthampy merged commit ee75fb2 into adobe:master Jun 1, 2026
11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants