~45 min read · updated 2026-05-16

Lab 3: contracts and policy enforcement

Build and verify the ACI contract graph for a three-tier application: web to app on TCP 8080 and app to database on TCP 5432.

Lab 3 is where the three-tier ACI model starts to feel like application security policy instead of just inventory. Lab 1 created the EPGs. Lab 2 attached those EPGs to simulated leaf paths. Lab 3 defines which EPGs are allowed to talk to each other.

The current lab models this flow:

web EPG -> app EPG -> db EPG

The web tier is allowed to reach the app tier on TCP 8080. The app tier is allowed to reach the database tier on TCP 5432. There is no direct web-to-database contract.

Target model

What you will create

ObjectName or value
Filterapp-tcp-8080
Filter entryTCP destination port 8080
Filterpostgres
Filter entryTCP destination port 5432
Contractweb-to-app
Subjectallow-app-tcp-8080
Contractapp-to-db
Subjectallow-postgres
Consumer relationshipweb consumes web-to-app
Provider relationshipapp provides web-to-app
Consumer relationshipapp consumes app-to-db
Provider relationshipdb provides app-to-db

Understand the ACI words

An EPG is a group of endpoints that share policy. In this lab, web, app, and db are separate EPGs.

A contract is the agreement between a consumer and provider. A consumer EPG asks for access to a contract. A provider EPG offers the service described by the contract.

A subject is the part of the contract that points to one or more filters.

A filter is the protocol and port match. In this lab, the filters are TCP 8080 and TCP 5432.

Build the web-to-app contract

Create filter app-tcp-8080 with a TCP destination-port entry for 8080.

Create contract web-to-app with subject allow-app-tcp-8080, and attach filter app-tcp-8080.

Then set the EPG relationships:

EPGRelationship
webConsumes web-to-app
appProvides web-to-app

This means the web tier is the client and the app tier is the service provider for TCP 8080.

Build the app-to-db contract

Create filter postgres with a TCP destination-port entry for 5432.

Create contract app-to-db with subject allow-postgres, and attach filter postgres.

Then set the EPG relationships:

EPGRelationship
appConsumes app-to-db
dbProvides app-to-db

This means the app tier is the client and the database tier is the service provider for PostgreSQL-style database access.

What not to create

Do not create a direct web-to-db contract in this beginner lab.

That missing contract is intentional. It makes the design easier to reason about:

web can ask app for service
app can ask db for service
web cannot directly ask db for service

In a real ACI fabric, this is how you keep the frontend tier from directly reaching the database tier unless the design explicitly allows it.

Automation

The lab repo has an idempotent script:

./scripts/configure-aci-lab-3-contracts.sh

The script reads APIC connection details from the local secret store, applies the filters, contracts, and EPG relationships, and verifies the result through the APIC API.

The latest run returned:

ready: true
tenant_fault_count: 0
web consumes web-to-app
app provides web-to-app
app consumes app-to-db
db provides app-to-db

Verification checklist

In APIC, check these before calling the lab complete:

  • Filter app-tcp-8080 exists.
  • Filter app-tcp-8080 matches TCP destination port 8080.
  • Filter postgres exists.
  • Filter postgres matches TCP destination port 5432.
  • Contract web-to-app exists.
  • Contract web-to-app has subject allow-app-tcp-8080.
  • Contract app-to-db exists.
  • Contract app-to-db has subject allow-postgres.
  • EPG web consumes web-to-app.
  • EPG app provides web-to-app.
  • EPG app consumes app-to-db.
  • EPG db provides app-to-db.
  • Tenant lab-prod has no active faults.

What this lab teaches

You should leave Lab 3 understanding:

  • ACI does not think primarily in VLAN ACL terms.
  • ACI policy is built around EPG relationships.
  • Contracts describe allowed service relationships.
  • Provider and consumer direction matters.
  • Filters hold the protocol and port details.
  • A missing contract is just as important as an allowed contract.

This remains a simulator policy lab. It proves APIC object relationships, not packet forwarding. For real traffic tests, mirror the same three-tier model in EVE-NG with Linux endpoints, NX-OSv, and a firewall.