Chapter 20Lesson 01190–250 min

REST API, Repository Provisioning, Security Automation, Pagination, and Infrastructure-as-Code Patterns: Concepts, Architecture, and Mental Model

Build the automation mental model before writing curl commands: the REST API is a versioned control-plane boundary over Nexus configuration and security state, while package content, repository metadata, database records, blob bytes, credentials, and external systems remain distinct state domains.

REST APIOpenAPIIdempotencePaginationDesired state

Learning objectives

  • Locate and interpret the instance-specific OpenAPI/Swagger contract before mutation.
  • Separate API resources, repository content endpoints, database/blob state, and client configuration.
  • Explain authentication, authorization, JSON request/response semantics, and HTTP outcomes.
  • Implement the continuation-token mental model without assuming one-page results.
  • Explain desired state, actual state, idempotence, drift, and version-aware reconciliation.

Version baseline (26 August 2026). These lessons use Sonatype Nexus Repository 3.95.2-01 as the dated self-hosted reference point, verified from Sonatype's public release repository, with Java 21 as the current runtime requirement. The mandatory lab assumes a small, disposable, loopback-only self-hosted Community Edition installation using H2 and a file blob store. The local instance's own /service/rest/swagger.json is authoritative for the exact endpoint schema you are about to call; API fields, repository recipes, security endpoints, and edition entitlements can change between releases.

Automation safety boundary. Do not put real passwords, user-token passcodes, Authorization headers, production base URLs, or employer namespaces into source files or lesson evidence. The examples use environment variables, synthetic names, loopback URLs, and disposable resources. User Tokens are a Pro capability in current self-hosted Nexus Repository; Community labs therefore use a disposable local account/password only for bootstrap and immediately reduce privileges for the service identity.

Pagination documentation note. Current Sonatype pages agree on the continuationToken contract but currently disagree on the documented default item count for components/assets. The robust automation rule is independent of page size: process every returned items array, pass the returned token unchanged, and stop only when continuationToken is null.

1. The practical problem: repeatability without hidden clicks

Manual administration can be appropriate for learning or one-off recovery, but repeated repository provisioning through the browser has three weaknesses: intent is difficult to review, repeated clicks can create drift, and there is no reliable machine-readable record of what the operator expected. Chapter 20 moves the same repository and security concepts you already know into a documented HTTP control plane.

The goal is not “turn every click into curl.” The goal is reconciliation: inspect actual state, compare it with desired state, mutate only the difference, verify the result, and preserve enough evidence to understand failures.

2. Mental model: control plane versus artifact data plane

API-driven administration changes configuration; package clients still use repository protocols
flowchart TD
D[Desired state file / script] --> C[Reconciler]
C -->|HTTPS /service/rest/v1| A[Nexus REST API]
A --> Z[Authorization]
Z --> R[Repository + security configuration]
R --> DB[(Database metadata)]
R --> B[(Blob-store references)]
P[Package client / CI] -->|repository protocol| E["/repository/... endpoint"]
E --> DB
E --> B
A --> J[HTTP result + JSON]
J --> C
C --> V[Independent verification]

The automation client is a new actor, not a replacement for Maven, npm, Docker, pip, or NuGet. Administrative REST calls normally target /service/rest/.... Package clients continue to talk to repository-format endpoints. Keeping these paths distinct prevents a common mistake: treating a successful admin API call as proof that a package workflow works.

3. The API contract lives with the instance

Current Nexus Repository exposes its OpenAPI document at <nexus_url>/service/rest/swagger.json and Swagger UI under Settings → System → API. The document is machine-readable and tied to the running server.

export NEXUS_URL='http://127.0.0.1:8081'
curl --fail --silent --show-error \
  "$NEXUS_URL/service/rest/swagger.json" \
  --output /tmp/nexus-swagger.json

python - <<'PY'
import json
p = json.load(open('/tmp/nexus-swagger.json', encoding='utf-8'))
print('basePath:', p.get('basePath'))
for path in sorted(p.get('paths', {})):
    if path.startswith('/v1/repositories'):
        print(path)
PY

This inspection establishes what the server claims to support before your script sends a mutation. Do not copy a payload from another release and assume fields are unchanged.

4. REST resources and state ownership

Resource family Typical intent State affected Independent verification
Status Read readiness/writability/system checks No intended mutation HTTP result plus logs/metrics if unhealthy
Repositories List/create/update/delete repository configuration Repository configuration; deletion can affect stored content references GET repository + content request + component/assets
Components/assets/search Inspect or operate on stored package objects Repository metadata and, for mutations, associated blob state All pages + checksum/download test
Security users/roles/privileges Manage local authorization objects Security configuration GET objects + positive/negative authorization tests
Tasks Inspect/run server-side jobs Depends on task type Task history/log + affected-state verification

Chapter 19 is why the final row says “depends.” An endpoint can schedule a job, but the state transition belongs to that task type, not to HTTP itself.

5. Authentication answers “who”; privileges answer “may they do this?”

REST automation needs an identity. In a disposable Community lab, a local account can authenticate with HTTP Basic authentication. In production, prefer a dedicated automation identity and a supported credential mechanism appropriate to your edition and identity architecture. Current self-hosted User Tokens are Pro-only, so they are not required in this chapter's Community path.

A user who can browse a repository is not automatically allowed to create repositories or users. For every automation identity, document the endpoint families and repository paths it needs, then grant the smallest privileges that satisfy that scope.

6. JSON is a contract, not decoration

Many create/update endpoints accept JSON. Distinguish:

  • Identity fields such as repository name or role ID.
  • Desired configuration fields such as online state, blob store, write policy, or member order.
  • Server-generated/read-only fields that may appear in GET responses but must not be blindly echoed into PUT/POST unless the OpenAPI schema permits them.

An IaC-style tool normalizes the fields it owns, compares only those fields, and leaves unrelated server-managed data alone.

7. HTTP status codes are control flow

Class/example Automation interpretation Safe response
2xx Request succeeded according to endpoint contract Still verify resulting Nexus state
400 Payload/query violates current contract Stop; inspect body and local Swagger; do not retry unchanged
401 Authentication failed/missing Fix credential path; never print secret
403 Identity authenticated but lacks authorization Inspect required privilege; avoid nx-admin as a shortcut
404 Resource/path not found; malformed URLs can also fail after Jetty 12 stricter parsing Validate base URL/path/encoding/version
409 Conflict with current resource/state Re-read actual state and decide whether conflict is expected drift

8. Pagination: “200 OK” can still mean “incomplete inventory”

List APIs that return items plus continuationToken tell you whether another request is required. Treat the token as opaque.

{
  "items": [{"id": "opaque-id", "repository": "learner-api-hosted"}],
  "continuationToken": "opaque-token-from-server"
}

Repeat the original filters and add the returned token. Continue until continuationToken is null. Processing only the first response can silently miss artifacts and make unsafe cleanup, migration, or audit decisions.

9. Desired state, actual state, and the reconciliation loop

Idempotence comes from comparison, not from hoping POST is harmless
flowchart TB
S[Load desired state] --> G[GET actual state]
G --> N[Normalize owned fields]
N --> D{Difference?}
D -->|No| K[No-op / verify]
D -->|Create missing| P[POST]
D -->|Update drift| U[PUT]
D -->|Delete only explicit managed lab resource| X[DELETE]
P --> V[GET + functional verification]
U --> V
X --> V
K --> V

Idempotent means rerunning automation against already-correct state produces no unintended additional change. Your reconciliation logic—not the mere choice of an HTTP verb—creates that property.

10. Drift requires an ownership policy

If automation creates a repository with strict content-type validation enabled and a human later disables it, the next run must know whether to restore it, report drift for approval, accept the change into desired state, or ignore the field because another owner controls it. Without an ownership rule, reconciliation becomes a fight between scripts and operators.

11. API version drift and URL correctness

New releases can add fields, formats, endpoints, constraints, or permissions. Since 3.81.0, Jetty 12 also enforces stricter URL parsing; malformed query parameters that older versions tolerated can return 404. Encode query parameters according to RFC 3986 and prefer an HTTP library that performs safe encoding over hand-built query strings.

12. Read-only preflight before mutation

  1. Record Nexus version/edition and Java runtime.
  2. Fetch swagger.json and confirm required paths exist.
  3. GET /service/rest/v1/status and /service/rest/v1/status/writable.
  4. GET repositories and identify the disposable blob store.
  5. GET privileges and later verify exact repository-view privilege IDs for your lab repository.
  6. Confirm the base URL resolves only to the disposable loopback/private instance.
  7. Confirm secret environment variables exist without printing their values.

13. Why this matters in DevOps

Reviewable desired state improves onboarding, disaster reconstruction, environment parity, auditability, and change review. The diff itself becomes an operational artifact: it shows what automation intended to change before Nexus is changed.

14. Knowledge check

Why read the running instance's Swagger document before sending a copied payload?

A components request returns HTTP 200 and a non-null continuationToken. Is inventory complete?

Does using PUT automatically make the provisioning workflow idempotent?

Why is a successful repository-creation API call not proof that package clients can use it?

15. Summary and next step

You now have the control-plane model: inspect OpenAPI, authenticate without leaking credentials, authorize narrowly, understand JSON and HTTP outcomes, paginate to completion, compare desired and actual state, and reconcile only owned fields. Lesson 2 turns that model into a disposable API workflow.

Official references and version notes

Keep the academy open

Support free, practical DevOps education.

Every lesson is designed to remain readable in a browser, downloadable from GitHub, and usable without a paid learning platform. Contributions help expand and maintain the curriculum.

Ethereum / ERC-20
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0 Send only Ethereum/ERC-20 compatible assets to this address.