Skip to content

[codex] Add access control flags to netbird expose#6675

Draft
constantins2001 wants to merge 2 commits into
netbirdio:mainfrom
constantins2001:codex/expose-access-control-flags
Draft

[codex] Add access control flags to netbird expose#6675
constantins2001 wants to merge 2 commits into
netbirdio:mainfrom
constantins2001:codex/expose-access-control-flags

Conversation

@constantins2001

@constantins2001 constantins2001 commented Jul 6, 2026

Copy link
Copy Markdown

Describe your changes

Adds CLI parity for reverse-proxy Access Control Rules when creating peer-initiated expose services with netbird expose.

The new flags are:

  • --allow-ip
  • --block-ip
  • --allow-cidr
  • --block-cidr
  • --allow-country
  • --block-country

Single IP flags are normalized to /32 or /128 CIDRs before being sent to management, matching the existing reverse-proxy access restriction model.

Implementation details:

  • Threads access restrictions through the daemon expose request, management expose request, and reverse-proxy peer service creation flow.
  • Reuses the existing AccessRestrictions backend model and validation.
  • Keeps auth flag behavior unchanged: L4/TLS still reject password/PIN/user-group auth, while access restrictions apply to both HTTP and L4 services.
  • Preserves crowdsec_mode when peer-created expose services receive the shared AccessRestrictions proto.
  • Adds focused tests for CLI normalization, request conversion, proto mapping, service validation, and service construction.

Issue ticket number and link

Closes #6673

Discussion-first validation: #6676

Stack

Single-PR change; no stacked dependencies.

Checklist

  • Is it a bug fix
  • Is a typo/documentation fix
  • Is a feature enhancement
  • It is a refactor
  • Created tests that fail without the change (if possible)
  • This change does not modify the public API, gRPC protocols, functionality behavior, CLI / service flags, or introduce a new feature — OR I have discussed it with the NetBird team beforehand (link the issue / Slack thread in the description). See CONTRIBUTING.md.

This PR is intentionally kept as draft while the discussion-first validation happens in #6676.

By submitting this pull request, you confirm that you have read and agree to the terms of the Contributor License Agreement.

Documentation

Select exactly one:

  • I added/updated documentation for this change
  • Documentation is not needed for this change (explain why)

The CLI help output is updated by the Cobra flags in this PR. External docs can be added in netbirdio/docs after maintainers confirm the CLI/API shape.

Docs PR URL (required if "docs added" is checked)

Paste the PR link from https://github.com/netbirdio/docs here:

https://github.com/netbirdio/docs/pull/__

Validation

  • GOCACHE=/private/tmp/netbird-go-build-cache GOMODCACHE=/private/tmp/netbird-go-mod-cache go test ./client/cmd ./management/internals/shared/grpc
  • GOCACHE=/private/tmp/netbird-go-build-cache GOMODCACHE=/private/tmp/netbird-go-mod-cache go test ./client/cmd ./client/internal/expose ./shared/management/client ./management/internals/modules/reverseproxy/service ./management/internals/shared/grpc ./management/internals/modules/reverseproxy/service/manager
  • git diff --check

@CLAassistant

CLAassistant commented Jul 6, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@coderabbitai

coderabbitai Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

This PR adds allow/block IP, CIDR, and country access restrictions to netbird expose and carries them through proto messages, client request conversions, management validation, and service creation.

Changes

Expose Access Restrictions Feature

Layer / File(s) Summary
Proto schema
client/proto/daemon.proto, shared/management/proto/management.proto
Adds access-restriction messages and access_restrictions fields to expose service requests.
CLI flags and restriction building
client/cmd/expose.go, client/cmd/expose_test.go
Adds allow/block IP, CIDR, and country flags; builds normalized access restrictions; validates parsing and host-bit handling; wires the result into the expose request.
Client daemon request mapping
client/internal/expose/manager.go, client/internal/expose/request.go, client/internal/expose/manager_test.go, shared/management/client/grpc.go, shared/management/client/grpc_expose_test.go
Adds access-restriction fields to request types and copies them through daemon-to-management and management-to-proto conversion paths.
Management validation and persistence
management/internals/modules/reverseproxy/service/service.go, management/internals/modules/reverseproxy/service/service_test.go, management/internals/shared/grpc/expose_service.go, management/internals/shared/grpc/expose_service_test.go
Validates restrictions on expose requests, copies them into services, and converts proto restrictions in the gRPC expose handler.

Estimated code review effort: 3 (Moderate) | ~30 minutes

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant ExposeCmd
  participant buildExposeAccessRestrictions
  participant DaemonRequest
  participant ManagementGRPC
  participant ReverseProxyService

  User->>ExposeCmd: netbird expose --allow-ip/--block-cidr/--allow-country
  ExposeCmd->>buildExposeAccessRestrictions: parse and normalize flags
  buildExposeAccessRestrictions-->>ExposeCmd: AccessRestrictions or nil
  ExposeCmd->>DaemonRequest: proto.ExposeServiceRequest.AccessRestrictions
  DaemonRequest->>ManagementGRPC: expose request conversion
  ManagementGRPC->>ReverseProxyService: Restrictions
  ReverseProxyService->>ReverseProxyService: Validate() and ToService()
Loading

Possibly related PRs

Suggested reviewers: pascal-fischer, lixmal, mlsmaycon

Poem

A rabbit hops with flags in tow,
For IP and country, yes and no.
CIDRs clipped and cleaned just right,
Then travel safely through the pipe.
Hop, hop — the proxy knows the way,
With guarded paths for every day.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The PR adds the requested expose access-control flags, validation, and request plumbing for #6673.
Out of Scope Changes check ✅ Passed The changes stay focused on expose access-control plumbing and tests, with no obvious unrelated additions.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Title check ✅ Passed The title clearly summarizes the main change: adding access-control flags to netbird expose.
Description check ✅ Passed The PR description follows the template and includes changes, issue link, stack, checklist, docs choice, and validation.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@constantins2001 constantins2001 marked this pull request as ready for review July 6, 2026 10:06

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
management/internals/shared/grpc/expose_service.go (1)

55-66: 🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win

Map crowdsec_mode through exposeAccessRestrictionsFromProto
This helper drops the shared AccessRestrictions.crowdsec_mode field, so callers can set CrowdSec mode in ExposeService.access_restrictions but it will be silently ignored. Carry it through to rpservice.AccessRestrictions (or reject it explicitly if this RPC shouldn’t accept it).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@management/internals/shared/grpc/expose_service.go` around lines 55 - 66, The
ExposeServiceRequest construction in expose_service.go is dropping
AccessRestrictions.crowdsec_mode because exposeAccessRestrictionsFromProto does
not carry it through. Update exposeAccessRestrictionsFromProto and the
rpservice.AccessRestrictions mapping used by CreateServiceFromPeer so
crowdsec_mode is preserved end-to-end, or explicitly reject it in the
ExposeService RPC if that field is not supported.
🧹 Nitpick comments (1)
client/cmd/expose.go (1)

215-225: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Country code check only verifies length, not that it's alphabetic.

normalizeExposeCountryCodes accepts any 2-character string (e.g. "12", "$$") since it only checks len(code) != 2. Invalid codes will only be caught later by management validation, after a daemon round-trip, giving a less immediate error than validating locally.

♻️ Suggested tightening
 func normalizeExposeCountryCodes(flag string, codes []string) ([]string, error) {
 	normalized := make([]string, 0, len(codes))
 	for _, raw := range codes {
 		code := strings.ToUpper(strings.TrimSpace(raw))
-		if len(code) != 2 {
+		if len(code) != 2 || code[0] < 'A' || code[0] > 'Z' || code[1] < 'A' || code[1] > 'Z' {
 			return nil, fmt.Errorf("--%s %q must be a 2-letter ISO 3166-1 alpha-2 country code", flag, raw)
 		}
 		normalized = append(normalized, code)
 	}
 	return normalized, nil
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@client/cmd/expose.go` around lines 215 - 225, The validation in
normalizeExposeCountryCodes only checks that each country code has length 2, so
non-letter values can pass through. Tighten the local check in this function by
also verifying the normalized code is alphabetic before appending it, and return
the same kind of fmt.Errorf for invalid inputs. Use the existing
normalizeExposeCountryCodes helper and its country-code parsing logic to keep
the fix localized.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@management/internals/shared/grpc/expose_service.go`:
- Around line 55-66: The ExposeServiceRequest construction in expose_service.go
is dropping AccessRestrictions.crowdsec_mode because
exposeAccessRestrictionsFromProto does not carry it through. Update
exposeAccessRestrictionsFromProto and the rpservice.AccessRestrictions mapping
used by CreateServiceFromPeer so crowdsec_mode is preserved end-to-end, or
explicitly reject it in the ExposeService RPC if that field is not supported.

---

Nitpick comments:
In `@client/cmd/expose.go`:
- Around line 215-225: The validation in normalizeExposeCountryCodes only checks
that each country code has length 2, so non-letter values can pass through.
Tighten the local check in this function by also verifying the normalized code
is alphabetic before appending it, and return the same kind of fmt.Errorf for
invalid inputs. Use the existing normalizeExposeCountryCodes helper and its
country-code parsing logic to keep the fix localized.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 6a772375-2350-4f1b-813c-b66ad3e060a9

📥 Commits

Reviewing files that changed from the base of the PR and between c9d387b and 4bf3a3c.

⛔ Files ignored due to path filters (2)
  • client/proto/daemon.pb.go is excluded by !**/*.pb.go
  • shared/management/proto/management.pb.go is excluded by !**/*.pb.go
📒 Files selected for processing (12)
  • client/cmd/expose.go
  • client/cmd/expose_test.go
  • client/internal/expose/manager.go
  • client/internal/expose/manager_test.go
  • client/internal/expose/request.go
  • client/proto/daemon.proto
  • management/internals/modules/reverseproxy/service/service.go
  • management/internals/modules/reverseproxy/service/service_test.go
  • management/internals/shared/grpc/expose_service.go
  • shared/management/client/grpc.go
  • shared/management/client/grpc_expose_test.go
  • shared/management/proto/management.proto

@sonarqubecloud

sonarqubecloud Bot commented Jul 6, 2026

Copy link
Copy Markdown

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.

Feature Request: Add reverse-proxy access control flags to netbird expose

2 participants