Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
103 commits
Select commit Hold shift + click to select a range
bda3554
feat: endpoint exposer
javi-null Dec 19, 2025
303f6ce
feat: http routes to handle private and public traffic
javi-null Jan 5, 2026
c95b552
feat: http routes to handle private and public traffic
javi-null Jan 5, 2026
d63abe2
feat: http routes to handle private and public traffic
javi-null Jan 5, 2026
470b16d
feat: http routes to handle private and public traffic
javi-null Jan 5, 2026
9518ebd
chore: link to public gateway
javi-null Jan 5, 2026
467abb8
chore: replace gateway
javi-null Jan 5, 2026
3dfdf91
chore: link to private gateway
javi-null Jan 5, 2026
9cc69db
chore: remove alb scripts
javi-null Jan 5, 2026
82dcf6b
chore: remove alb workflows
javi-null Jan 5, 2026
af379b1
chore: remove unused scripts and dns endpoints
javi-null Jan 5, 2026
11e2315
chore: remote DEBUG logs
javi-null Jan 6, 2026
2b89d8a
chore: remote DEBUG logs
javi-null Jan 6, 2026
d0638a0
chore: DEBUG logs
javi-null Jan 6, 2026
9f89c08
feat: adapt endpoint exposer to work by service action
javi-null Jan 6, 2026
4f3a2ec
feat: adapt endpoint exposer to work by service action
javi-null Jan 6, 2026
cc52dde
feat: adapt endpoint exposer to work by service action
javi-null Jan 6, 2026
85b25e0
fix: retries on action creation
javi-null Jan 6, 2026
3a7991e
feat: if no service instance created allow continue without errors
javi-null Jan 7, 2026
f7b425a
feat: remove links
javi-null Jan 8, 2026
9111e6d
feat: wip authz plugins
javi-null Jan 9, 2026
4eb2a97
feat: public and private domains
javi-null Jan 9, 2026
0a5d9fa
feat: public and private domains
javi-null Jan 9, 2026
684593f
feat: public and private domains
javi-null Jan 9, 2026
be60250
fix: private httproute
javi-null Jan 9, 2026
9215168
fix: update flow
javi-null Jan 9, 2026
b9a7174
Merge branch 'feature/endpoint-exposer' into feature/plugins
javi-null Jan 12, 2026
31e2d63
feat: basic authorization
javi-null Jan 12, 2026
33abaaf
feat: basic authorization
javi-null Jan 12, 2026
8edf8c0
feat: basic authorization
javi-null Jan 12, 2026
786009f
feat: unify private and public logic
javi-null Jan 12, 2026
0081af2
feat: unify private and public logic
javi-null Jan 12, 2026
70abf3a
feat: stable authorization and tests
javi-null Jan 12, 2026
8139855
feat: add pre-commit hook to run tests
javi-null Jan 13, 2026
27d26eb
feat: wip plugins
javi-null Jan 15, 2026
c6b55b1
feat: add echos and remove auth policy from workflows
javi-null Jan 19, 2026
f6cbf48
feat: change output dir read
javi-null Jan 19, 2026
60e967b
feat: adapt overrides path
javi-null Jan 20, 2026
b9431f5
feat: adapt overrides path
javi-null Jan 20, 2026
442e5dc
feat: add subfolder to avoid cli regex issue
javi-null Jan 20, 2026
0e6f985
feat: add change to support plugin
javi-null Jan 23, 2026
73b2f7c
feat: new service spec for avp
javi-null Jan 23, 2026
dfde690
Merge branch 'feature/plugins' into feature/avp-plugin
javi-null Jan 26, 2026
33824d5
chore: change list of domains for PAE
javi-null Jan 26, 2026
4971a66
fix: escape quotes in visible_to gomplate expression to produce valid…
May 21, 2026
b849731
fix(endpoint-exposer): update domain enum to api-private.playground.n…
May 21, 2026
853fd63
feat(endpoint-exposer): generate AuthorizationPolicy per service from…
May 21, 2026
f153141
fix(endpoint-exposer): re-add idp.poc.nullapps.io to enum for backwar…
May 21, 2026
982dcc7
revert(endpoint-exposer): remove idp.poc.nullapps.io from domain enum
May 21, 2026
34196f1
fix: remove output declarations from authz policy steps to unblock apply
May 21, 2026
730ea95
fix: export K8S_NAMESPACE from build_context so apply step can use it
May 21, 2026
09af298
feat: create AuthorizationPolicy per scope DNS instead of publicDomain
May 21, 2026
59b8c17
fix: read routes and application_id from CONTEXT directly in build_au…
May 21, 2026
b5732ac
fix: use --application_id (underscore) flag for np scope list
May 21, 2026
b3c9d77
fix: use correct gateway-name selector in AuthorizationPolicy
May 21, 2026
4a75a1a
feat: manage AVP Cedar policies from endpoint-exposer
May 21, 2026
4f1b387
fix: add has operator for optional host attr and explicit error checking
May 21, 2026
62f3c76
feat(endpoint-exposer): switch to global catch-all AuthorizationPolicy
May 22, 2026
7567d6c
refactor(endpoint-exposer): derive HTTPRoute hostnames from scope dom…
May 22, 2026
bca8b36
fix(endpoint-exposer): remove trailing comma in service-spec after do…
May 22, 2026
e4113ee
docs(endpoint-exposer): remove visibility and domain references from …
May 22, 2026
70735ff
feat(endpoint-exposer): implement read action to show live AVP Cedar …
May 22, 2026
b478f06
fix(endpoint-exposer): enable read action button
May 22, 2026
392a51b
fix(endpoint-exposer): remove gomplate expression from read action sp…
May 22, 2026
a60f32e
fix(endpoint-exposer): replace grep -P with BusyBox-compatible sed/gr…
May 22, 2026
b2a2ab8
fix(endpoint-exposer): add || true to grep calls to avoid set -e fail…
May 22, 2026
8add791
fix(endpoint-exposer): use get-policy for full statement, simplify pa…
May 22, 2026
a48b939
fix(endpoint-exposer): use sed BRE for group extraction, more BusyBox…
May 22, 2026
4d6a7a5
Remove Authorization Group from uiSchema
May 22, 2026
e4190aa
Add link-per-route model for AVP Cedar policy management
May 22, 2026
c380f3e
Remove additionalKeywords from scope in route link spec
May 22, 2026
6187168
feat(endpoint-exposer): add uiSchema to route link spec, remove route…
May 22, 2026
e468049
fix(endpoint-exposer): remove visibleOn from input fields in route li…
May 22, 2026
8e73afe
feat(endpoint-exposer): render Authorized Groups in vertical column l…
May 22, 2026
6fb368d
feat(endpoint-exposer): infer scope from link dimensions instead of f…
May 23, 2026
611b01a
feat(endpoint-exposer): support multiple routes per link
May 23, 2026
6d485dc
fix(endpoint-exposer): shorten AVP policy description to fit 150-char…
May 23, 2026
55a2450
feat(link-spec): allow editing routes after link creation
May 23, 2026
6ca2d83
feat(link-spec): make routes editable after link creation
May 23, 2026
4c63f83
fix(link-spec): use "update" instead of "edit" for editableOn
May 23, 2026
ec44daa
feat(link): add link-update workflow with proper scope and HTTPRoute …
May 23, 2026
87df429
fix(link-update): use LINK_ID for stable HTTPRoute name across updates
May 23, 2026
876c5ad
fix(link-update): add output to delete step so workflow runner continues
May 23, 2026
da397b4
fix(avp): replace exit 0 with conditional flow in delete scripts
May 23, 2026
afb6294
feat: add avp_policy_store_id param to service spec with auto-creation
May 23, 2026
c42ab08
refactor(link): remove visibility field, derive gateway from scope type
May 23, 2026
b5498fa
fix(unlink): derive HTTPROUTE_NAME from LINK_ID instead of stored att…
May 23, 2026
e37a123
fix(create_policies): replace exit 0 with conditional to avoid killin…
May 23, 2026
2091d4c
fix(update): remove duplicate store service results step from update.…
May 23, 2026
f7ad337
fix(apply): remove exit 0 that killed workflow after apply step
May 23, 2026
bb27239
fix(link): pass scope name to process_routes and fix scope lookup
May 26, 2026
590caf3
fix(link): add ensure_policy_store step to link workflows
May 26, 2026
c930674
fix(link): read avp_policy_store_id from service.attributes not servi…
May 26, 2026
b8d1820
feat(service): delete AVP policy store on service deletion
May 26, 2026
5f36184
fix(service): ensure delete_policy_store step runs via include mechanism
May 26, 2026
0e8e88d
fix(service): persist avp_policy_store_id in service.attributes
May 26, 2026
1447810
fix: persist avp store id early and fix delete workflow step ordering
May 26, 2026
fedaaf0
fix(avp): avoid exit 0 in delete_policies to prevent workflow termina…
May 26, 2026
1b242bc
fix(link): store policy_ids as string to satisfy NullPlatform API sch…
May 26, 2026
684fff5
feat(avp): discover policy store via SSM instead of creating per-serv…
May 26, 2026
01d0ee6
feat(spec): remove avp_policy_store_id from service spec UI
May 26, 2026
fb210d9
feat(avp): require avp_policy_store_id as mandatory UI input instead …
May 26, 2026
d9a47fc
fix(spec): translate avp_policy_store_id description to English and r…
May 26, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions .githooks/pre-commit
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#!/bin/bash

set -e

echo "Running tests before commit..."

# Change to the repository root
REPO_ROOT="$(git rev-parse --show-toplevel)"
cd "$REPO_ROOT"

# Check if endpoint-exposer tests need to be run (if any endpoint-exposer files changed)
if git diff --cached --name-only | grep -q "^endpoint-exposer/"; then
echo "Endpoint-exposer files changed, running tests..."

if command -v bats &> /dev/null; then
cd endpoint-exposer
bats test/
else
echo "⚠️ BATS not installed, skipping tests"
echo "Install BATS: brew install bats-core (macOS) or see https://bats-core.readthedocs.io"
exit 0
fi

echo "✅ All endpoint-exposer tests passed!"
fi
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,6 @@
*.iml
out
gen

# VSCode project files
.vscode/
233 changes: 233 additions & 0 deletions endpoint-exposer/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,233 @@
# Endpoint Exposer Service

## Overview

The **endpoint-exposer** service is a critical infrastructure component of Nullplatform that manages dynamic exposure of application endpoints through public and private domains. It functions as a route orchestrator that translates high-level specifications into native Kubernetes configurations using Istio Service Mesh.

## Core Responsibilities

### 1. Dynamic Endpoint Management
- Expose application endpoints declaratively
- Configure separate public and private domains for different access levels
- Update route configurations with zero downtime
- Maintain configuration synchronized with desired state

### 2. Route Configuration
- Define route patterns (exact, regex, wildcards)
- Specify allowed HTTP methods (GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS)
- Associate routes with Nullplatform scopes for access control
- Control route visibility (public vs. private)

### 3. Kubernetes and Istio Integration
- Generate HTTPRoute resources (Kubernetes Gateway API v1)
- Create Istio AuthorizationPolicies for access control
- Configure RequestAuthentication for JWT validation
- Apply routing policies in the service mesh

### 4. Scope-Based Access Control
- Map endpoints to specific Nullplatform scopes
- Integrate with Open Policy Agent (OPA) for external authorization
- Implement granular authorization policies per route
- Validate JWT tokens according to scope configuration

## Key Features

### Route Management
```yaml
routes:
- method: GET
path: /api/users
scope: user-management
visible_on: public
enable_authorization: true
```

- **Path Types**:
- Exact: `/api/users`
- Regex with parameters: `/api/users/{id}`
- Wildcard: `/api/users/*`

- **HTTP Methods**: Supports all standard HTTP methods
- **Visibility**: Public or private routes on separate domains
- **Authorization**: Optional per-route with JWT and OPA validation

### Domain Separation

**Public Domain:**
- Endpoints accessible from the internet
- Typically for public APIs and unauthenticated resources
- Connected to `gateway-public` gateway

**Private Domain:**
- Internal organization endpoints
- Requires private network access
- Connected to `gateway-private` gateway

### Authorization and Security

- **JWT Validation**: Verifies authentication tokens on each request
- **Authorization Policies**: Istio AuthorizationPolicies per route
- **OPA Integration**: Authorization decisions delegated to Open Policy Agent
- **Scope Control**: Route-to-scope mapping for granular permissions

## Architecture

### Workflow

1. **Build Context**
- Extracts service action parameters
- Retrieves Kubernetes namespace information
- Classifies routes by visibility (public/private)

2. **Build HTTPRoutes**
- Generates base HTTPRoute templates per domain
- Queries scopes associated with each route
- Constructs Istio routing rules

3. **Process Routes**
- Sorts routes by specificity (exact > regex > prefix)
- Generates AuthorizationPolicies if authorization is enabled
- Maps scope IDs to backend services

4. **Apply Configuration**
- Applies generated YAML manifests to the cluster
- Manages cleanup of obsolete resources
- Maintains tracking of applied resources

### Technologies

- **Kubernetes**: Orchestration platform (Gateway API v1)
- **Istio**: Service mesh for traffic management and security
- **Bash**: Workflow scripting and automation
- **jq**: JSON processing and manipulation
- **gomplate**: Resource template generation
- **kubectl**: Kubernetes resource management
- **OPA**: Open Policy Agent for external authorization

### Nullplatform Integration

- **Scopes Service**: Scope queries for authorization (`np scope list/read`)
- **Notification Channel**: Receives events to trigger actions
- **Service Specification**: Service specification registration
- **Deployment Service**: Coordination with deployment workflows

## File Structure

```
/endpoint-exposer
├── configure # Service configuration script
├── entrypoint/ # Entry points for actions
│ ├── service-action # Service action handler
│ └── link-action # Dependency handler
├── specs/ # Service specifications
│ ├── service-specification.json
│ └── link-specification.json
├── workflows/istio/ # Workflow definitions
│ ├── service-action.json
│ └── link-action.json
├── scripts/istio/ # Core routing logic
│ ├── build_context
│ ├── build_httproute
│ ├── process_routes
│ ├── build_rule
│ └── build_ingress_with_rule
├── scripts/common/ # Shared utilities
│ ├── apply
│ └── delete
├── templates/istio/ # K8s resource templates
│ ├── httproute.yaml.tmpl
│ ├── authz-policy.yaml.tmpl
│ └── request-authn.yaml.tmpl
├── test/ # BATS test suite
├── examples/ # Example configurations
└── container-scope-override/ # Custom deployment support
```

## Configuration

### Environment Variables

- `K8S_NAMESPACE`: Kubernetes namespace for resources (default: `nullplatform`)
- `PUBLIC_GATEWAY_NAME`: Public gateway name (default: `gateway-public`)
- `PRIVATE_GATEWAY_NAME`: Private gateway name (default: `gateway-private`)
- `GATEWAY_NAMESPACE`: Gateway namespace (default: `gateways`)
- `OPA_PROVIDER_NAME`: OPA authorization provider (default: `opa-ext-authz`)

### Route Configuration Example

```json
{
"routes": [
{
"method": "GET",
"path": "/api/v1/resource/{id}",
"scope": "resource-read",
"visible_on": "public",
"enable_authorization": true
},
{
"method": "POST",
"path": "/api/v1/resource",
"scope": "resource-write",
"visible_on": "private",
"enable_authorization": true
}
],
"public_domain": "api.example.com",
"private_domain": "internal-api.example.com"
}
```

## Testing

The service uses BATS (Bash Automated Testing System) for testing:

```bash
# Run all tests
./test/run-tests.sh

# Run specific tests
bats test/istio/
```

Tests cover:
- Simple routes
- Public and private routes
- Authorization scenarios
- JWT configurations
- Manifest generation

## Operations

### Create/Update Endpoints

The service responds to Nullplatform actions:
- `create`: Generates and applies initial configuration
- `update`: Modifies existing configuration
- `delete`: Cleans up Kubernetes resources

### Monitoring

Generated resources can be monitored with:

```bash
# View HTTPRoutes
kubectl get httproutes -n <namespace>

# View AuthorizationPolicies
kubectl get authorizationpolicies -n <namespace>

# View gateway status
kubectl get gateway -n gateways
```

## Use Cases

1. **Public API**: Expose public REST endpoints with rate limiting and optional authentication
2. **Admin API**: Private endpoints with JWT authentication and scope-based authorization
3. **Internal Microservices**: Private routes between services with authorization policies
4. **Multi-Version APIs**: Path-based routing for API versioning

## Contributing

See [test/README.md](test/README.md) for information about testing and development.
Loading