What is a Network Policy?
A network policy in Garnet defines rules for allowing or blocking network traffic based on IP addresses and domain names. Network policies are the enforcement mechanism that translates security decisions into actual protection.
Policies are hierarchical and context-aware, allowing you to apply rules at different scopes from global organization-wide rules down to specific workflows or nodes.
Policy Structure
type NetworkPolicy struct {
ID string `json:"id"`
ProjectID string `json:"-"`
Scope NetworkPolicyScope `json:"scope"`
Config NetworkPolicyConfig `json:"config"`
Rules [] NetworkPolicyRule `json:"rules"`
CreatedAt time . Time `json:"created_at"`
UpdatedAt time . Time `json:"updated_at"`
DeletedAt * time . Time `json:"deleted_at,omitempty"`
}
Policy Scopes
Policies can be applied at different hierarchical levels:
const (
NetworkPolicyScopeSystemGlobal NetworkPolicyScope = "system_global"
NetworkPolicyScopeGlobal NetworkPolicyScope = "global"
NetworkPolicyScopeRepo NetworkPolicyScope = "repo"
NetworkPolicyScopeWorkflow NetworkPolicyScope = "workflow"
NetworkPolicyScopeCluster NetworkPolicyScope = "cluster"
NetworkPolicyScopeNode NetworkPolicyScope = "node"
)
System-Wide System Global : Applies across all projects (admin only)Project Global : Applies to all agents in a projectPriority : Lowest (can be overridden by more specific policies)
GitHub Context Repository : Applies to all workflows in a repositoryWorkflow : Applies to specific workflowPriority : Workflow overrides Repository, which overrides Global
Kubernetes Context Cluster : Applies to entire Kubernetes clusterNode : Applies to specific nodePriority : Node overrides Cluster, which overrides Global
Vanilla Context Uses Project Global scope Rules apply to all vanilla agents in the project Priority : Project-level enforcement
Scope Hierarchy
Policies merge in order of increasing specificity:
System Global
Base policies set by system administrators
Project Global
Project-wide policies override system global
Context-Specific
Repository/Cluster policies override project global
Most Specific
Workflow/Node policies override all others
When multiple policies apply to an agent, they are merged with more specific policies taking precedence. Rules from all applicable policies are combined.
Policy Configuration
Each policy has a configuration that controls enforcement behavior:
type NetworkPolicyConfig struct {
CIDRMode NetworkPolicyCIDRMode `json:"cidr_mode"`
CIDRPolicy NetworkPolicyType `json:"cidr_policy"`
ResolveMode NetworkPolicyResolveMode `json:"resolve_mode"`
ResolvePolicy NetworkPolicyType `json:"resolve_policy"`
}
Enforcement Modes
Controls how IP-based rules are enforced: const (
NetworkPolicyCIDRModeAlert NetworkPolicyCIDRMode = "alert" // Log only
NetworkPolicyCIDRModeEnforce NetworkPolicyCIDRMode = "enforce" // Block
NetworkPolicyCIDRModeBoth NetworkPolicyCIDRMode = "both" // Log + Block
)
Alert : Violations are logged but traffic is allowed
Enforce : Violations are blocked
Both : Violations are logged AND blocked
Controls DNS resolution behavior: const (
NetworkPolicyResolveModsBypass NetworkPolicyResolveMode = "bypass" // No DNS checking
NetworkPolicyResolveModeStrict NetworkPolicyResolveMode = "strict" // Enforce DNS rules
NetworkPolicyResolveModePermissive NetworkPolicyResolveMode = "permissive" // Relaxed checking
)
Bypass : DNS resolution not enforced
Strict : Domain rules strictly enforced
Permissive : Allows some DNS resolution flexibility
Default action for traffic not matching any rules: const (
NetworkPolicyTypeAllow NetworkPolicyType = "allow" // Default allow
NetworkPolicyTypeDeny NetworkPolicyType = "deny" // Default deny
)
Allow : Traffic is allowed unless explicitly denied
Deny : Traffic is denied unless explicitly allowed
Simplified Mode Field
For easier configuration, policies support a simplified mode:
type NetworkPolicyMode string
const (
NetworkPolicyModeBypass NetworkPolicyMode = "bypass" // No enforcement
NetworkPolicyModeAlert NetworkPolicyMode = "alert" // Log violations
NetworkPolicyModeEnforce NetworkPolicyMode = "enforce" // Block violations
NetworkPolicyModeBoth NetworkPolicyMode = "both" // Log + Block
)
Policy Rules
Rules define specific allow or deny actions:
type NetworkPolicyRule struct {
ID string `json:"id"`
PolicyID string `json:"policy_id"`
Type NetworkPolicyRuleType `json:"type"`
Value string `json:"value"`
Action NetworkPolicyType `json:"action"`
CreatedAt time . Time `json:"created_at"`
UpdatedAt time . Time `json:"updated_at"`
}
Rule Types
CIDR Rules Match IP addresses or ranges: NetworkPolicyRuleTypeCIDR NetworkPolicyRuleType = "cidr"
Examples:
192.168.1.0/24 - Subnet
10.0.0.1/32 - Single IP
2001:db8::/32 - IPv6 range
Domain Rules Match domain names: NetworkPolicyRuleTypeDomain NetworkPolicyRuleType = "domain"
Examples:
example.com
api.service.io
*.malicious.net
Rule Actions
const (
NetworkPolicyTypeAllow NetworkPolicyType = "allow" // Explicitly allow
NetworkPolicyTypeDeny NetworkPolicyType = "deny" // Explicitly deny
)
Rules override the default policy. An allow rule in a deny-by-default policy will permit that specific destination.
Creating Policies
Global Policy
import (
" context "
" github.com/garnet-org/api/client "
" github.com/garnet-org/api/types "
)
func createGlobalPolicy () {
c := client . New ( "your-api-key" )
policy := types . CreateNetworkPolicy {
Scope : types . NetworkPolicyScopeGlobal ,
Config : types . NetworkPolicyConfig {
CIDRMode : types . NetworkPolicyCIDRModeEnforce ,
CIDRPolicy : types . NetworkPolicyTypeAllow ,
ResolveMode : types . NetworkPolicyResolveModsBypass ,
ResolvePolicy : types . NetworkPolicyTypeAllow ,
},
Rules : [] types . CreateNetworkPolicyRule {
{
Type : types . NetworkPolicyRuleTypeCIDR ,
Value : "192.168.0.0/16" ,
Action : types . NetworkPolicyTypeAllow ,
},
{
Type : types . NetworkPolicyRuleTypeDomain ,
Value : "malicious.example.com" ,
Action : types . NetworkPolicyTypeDeny ,
},
},
}
result , err := c . CreateNetworkPolicy ( context . Background (), policy )
if err != nil {
// Handle error
}
fmt . Printf ( "Created policy: %s \n " , result . ID )
}
Repository-Scoped Policy
func createRepoPolicy ( repositoryID string ) {
c := client . New ( "your-api-key" )
policy := types . CreateNetworkPolicy {
Scope : types . NetworkPolicyScopeRepo ,
RepositoryID : repositoryID ,
Config : types . GetDefaultNetworkPolicyConfig (),
}
result , err := c . CreateNetworkPolicy ( context . Background (), policy )
if err != nil {
// Handle error
}
}
Workflow-Scoped Policy
func createWorkflowPolicy ( repositoryID , workflowName string ) {
c := client . New ( "your-api-key" )
policy := types . CreateNetworkPolicy {
Scope : types . NetworkPolicyScopeWorkflow ,
RepositoryID : repositoryID ,
WorkflowName : workflowName ,
Config : types . GetDefaultNetworkPolicyConfig (),
}
result , err := c . CreateNetworkPolicy ( context . Background (), policy )
if err != nil {
// Handle error
}
}
Kubernetes Cluster Policy
func createClusterPolicy ( clusterName string ) {
c := client . New ( "your-api-key" )
policy := types . CreateNetworkPolicy {
Scope : types . NetworkPolicyScopeCluster ,
ClusterName : clusterName ,
Config : types . GetDefaultNetworkPolicyConfig (),
}
result , err := c . CreateNetworkPolicy ( context . Background (), policy )
if err != nil {
// Handle error
}
}
Kubernetes Node Policy
func createNodePolicy ( clusterName , nodeName string ) {
c := client . New ( "your-api-key" )
policy := types . CreateNetworkPolicy {
Scope : types . NetworkPolicyScopeNode ,
ClusterName : clusterName ,
NodeName : nodeName ,
Config : types . GetDefaultNetworkPolicyConfig (),
}
result , err := c . CreateNetworkPolicy ( context . Background (), policy )
if err != nil {
// Handle error
}
}
Managing Policy Rules
Adding Rules
func addRule ( policyID string ) {
c := client . New ( "your-api-key" )
rule := types . CreateNetworkPolicyRule {
Type : types . NetworkPolicyRuleTypeDomain ,
Value : "safe-api.example.com" ,
Action : types . NetworkPolicyTypeAllow ,
}
result , err := c . CreateNetworkPolicyRule ( context . Background (), policyID , rule )
if err != nil {
// Handle error
}
fmt . Printf ( "Created rule: %s \n " , result . ID )
}
Updating Rules
func updateRule ( ruleID string ) {
c := client . New ( "your-api-key" )
newAction := types . NetworkPolicyTypeDeny
update := types . UpdateNetworkPolicyRule {
Action : & newAction ,
}
result , err := c . UpdateNetworkPolicyRule ( context . Background (), ruleID , update )
if err != nil {
// Handle error
}
}
Deleting Rules
func deleteRule ( ruleID string ) {
c := client . New ( "your-api-key" )
err := c . DeleteNetworkPolicyRule ( context . Background (), ruleID )
if err != nil {
// Handle error
}
}
Merged Network Policies
Agents receive a merged policy that combines all applicable policies:
type MergedNetworkPolicy struct {
// Legacy format (for backwards compatibility)
Config NetworkPolicyConfig `json:"config"`
Rules [] NetworkPolicyRule `json:"rules"`
// Simplified format
Mode NetworkPolicyMode `json:"mode"`
Policy NetworkPolicyType `json:"policy"`
Allow [] string `json:"allow"`
Deny [] string `json:"deny"`
Resolve [] string `json:"resolve"`
// Policy references for traceability
SystemGlobalPolicy * SystemGlobalNetworkPolicy `json:"system_global_policy,omitempty"`
GlobalPolicy * NetworkPolicy `json:"global_policy,omitempty"`
RepoPolicy * RepoNetworkPolicy `json:"repo_policy,omitempty"`
WorkflowPolicy * WorkflowNetworkPolicy `json:"workflow_policy,omitempty"`
ClusterPolicy * ClusterNetworkPolicy `json:"cluster_policy,omitempty"`
NodePolicy * NodeNetworkPolicy `json:"node_policy,omitempty"`
}
Retrieving Merged Policies
For GitHub Context:
func getMergedPolicyGitHub ( repositoryID , workflowName string ) {
c := client . New ( "your-api-key" )
// Get as JSON
policy , err := c . MergedNetworkPolicyGithubJSON (
context . Background (),
repositoryID ,
workflowName ,
)
if err != nil {
// Handle error
}
// Or get as YAML
yamlPolicy , err := c . MergedNetworkPolicyGithubYAML (
context . Background (),
repositoryID ,
workflowName ,
)
if err != nil {
// Handle error
}
}
For Kubernetes Context:
func getMergedPolicyK8s ( clusterName , nodeName string ) {
c := client . New ( "your-api-key" )
policy , err := c . MergedNetworkPolicyForK8s (
context . Background (),
clusterName ,
nodeName ,
)
if err != nil {
// Handle error
}
fmt . Printf ( "Mode: %s \n " , policy . Mode )
fmt . Printf ( "Policy: %s \n " , policy . Policy )
fmt . Printf ( "Allow: %v \n " , policy . Allow )
fmt . Printf ( "Deny: %v \n " , policy . Deny )
}
The merged policy includes references to all source policies, allowing you to trace which policy contributed each rule.
Policy Merge Logic
The merge algorithm (types/network_policy.go:671-775):
Start with default configuration
Apply system global policy (if exists)
Apply project global policy (overrides system)
Apply context-specific policy (repo/cluster)
Apply most-specific policy (workflow/node)
Populate simplified format from merged rules
More specific policies completely override the configuration of less specific policies, but rules from all policies are combined.
Listing Policies
Retrieve policies by scope:
func listPolicies ( scope types . NetworkPolicyScope ) {
c := client . New ( "your-api-key" )
policies , err := c . NetworkPolicies ( context . Background (), scope )
if err != nil {
// Handle error
}
for _ , policy := range policies {
fmt . Printf ( "Policy: %s (scope: %s ) \n " , policy . ID , policy . Scope )
fmt . Printf ( " Rules: %d \n " , len ( policy . Rules ))
}
}
Updating Policies
Modify policy configuration:
func updatePolicy ( policyID string ) {
c := client . New ( "your-api-key" )
newConfig := types . NetworkPolicyConfig {
CIDRMode : types . NetworkPolicyCIDRModeEnforce ,
CIDRPolicy : types . NetworkPolicyTypeDeny ,
ResolveMode : types . NetworkPolicyResolveModeStrict ,
ResolvePolicy : types . NetworkPolicyTypeDeny ,
}
update := types . UpdateNetworkPolicy {
Config : & newConfig ,
}
result , err := c . UpdateNetworkPolicy ( context . Background (), policyID , update )
if err != nil {
// Handle error
}
fmt . Printf ( "Updated policy: %s \n " , result . ID )
}
Deleting Policies
Remove a network policy:
func deletePolicy ( policyID string ) {
c := client . New ( "your-api-key" )
err := c . DeleteNetworkPolicy ( context . Background (), policyID )
if err != nil {
// Handle error
}
}
Deleting a policy soft-deletes it (sets DeletedAt timestamp). Agents will no longer receive rules from deleted policies.
Best Practices
Start with alert mode before enforcing
Use default-deny for high-security environments
Apply narrow scopes for testing
Document the purpose of each policy
Review merged policies to understand actual enforcement
Use CIDR rules for IP ranges
Use domain rules for service names
Prefer allow lists over deny lists when possible
Regularly audit and cleanup unused rules
Test rules before deploying broadly
Use global policies for organization-wide rules
Use repo/cluster policies for team-specific rules
Use workflow/node policies for specific cases
Document scope decisions
Avoid conflicting rules across scopes
Monitor alert mode violations before enforcing
Gradually transition from alert to enforce
Use bypass mode for troubleshooting
Set up alerting for policy violations
Review enforcement effectiveness regularly
Error Handling
Common Errors
ErrInvalidNetworkPolicyScope (types/network_policy.go:24)
ErrInvalidNetworkPolicyScope = errs . InvalidArgumentError ( "invalid network policy scope" )
Returned when the policy scope is not one of the supported types.
ErrNetworkPolicyNotFound (types/network_policy.go:67)
ErrNetworkPolicyNotFound = errs . NotFoundError ( "network policy not found" )
Returned when querying a non-existent policy.
ErrNetworkPolicyAlreadyExists (types/network_policy.go:73)
ErrNetworkPolicyAlreadyExists = errs . ConflictError ( "network policy already exists" )
Returned when trying to create a duplicate policy for a scope.
ErrInvalidNetworkPolicyRuleValue (types/network_policy.go:43)
ErrInvalidNetworkPolicyRuleValue = errs . InvalidArgumentError ( "invalid network policy rule value" )
Returned when the rule value (CIDR or domain) is malformed.
Agents - Components that enforce network policies
Events - Detections that can trigger policy rules
Issues - Security concerns that lead to policy actions