Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
5 changes: 5 additions & 0 deletions docs/auth0_network-acl_create.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ auth0 network-acl create [flags]
auth0 network-acl create --description "Redirect Traffic" --priority 3 --active true --rule '{"action":{"redirect":true,"redirect_uri":"https://example.com"},"scope":"management","match":{"ipv4_cidrs":["192.168.1.0/24"]}}'
auth0 network-acl create -d "Block Bots" -p 4 --active true --rule '{"action":{"block":true},"scope":"tenant","match":{"user_agents":["badbot/*","malicious/*"],"ja3_fingerprints":["deadbeef","cafebabe"]}}'
auth0 network-acl create --description "Complex Rule" --priority 5 --active true --rule '{"action":{"block":true},"scope":"tenant","match":{"ipv4_cidrs":["192.168.1.0/24"],"geo_country_codes":["US"]}}'

# Early Access (auth0_managed match/not_match value):
auth0 network-acl create -d "Curated Blocklist" -p 6 --active true --rule '{"action":{"log":true},"scope":"tenant","not_match":{"auth0_managed":["auth0.vpn","auth0.proxy"]}}'

```


Expand All @@ -33,6 +37,7 @@ auth0 network-acl create [flags]
--action string Action for the rule (block, allow, log, redirect)
--active string Whether the network ACL is active (required, 'true' or 'false')
--asns ints Comma-separated list of ASNs to match (Eg. 64496,64497,64498)
--auth0-managed strings Comma-separated list of Auth0-curated blocklists to match (Eg. auth0.icloud_relay_proxy,auth0.low_reputation). (EA only).
--country-codes strings Comma-separated list of country codes to match (Eg. US,CA,MX)
-d, --description string Description of the network ACL (required)
--ipv4-cidrs strings Comma-separated list of IPv4 CIDR ranges (Eg. 192.168.1.0/24,10.0.0.0/8)
Expand Down
5 changes: 5 additions & 0 deletions docs/auth0_network-acl_update.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ auth0 network-acl update [flags]
auth0 network-acl update <id> --description "Updated description"
auth0 network-acl update <id> --rule '{"action":{"block":true},"scope":"tenant","match":{"ipv4_cidrs":["192.168.1.0/24"]}}'
auth0 network-acl update <id> --description "Complex Rule updated" --priority 1 --active true --rule '{"action":{"block":true},"scope":"tenant","match":{"ipv4_cidrs":["192.168.1.0/24"],"geo_country_codes":["US"]}}'

# Early Access (auth0_managed match/not_match value):
auth0 network-acl update <id> --rule '{"action":{"allow":true},"scope":"tenant","match":{"auth0_managed":["auth0.low_reputation"]}}'

```


Expand All @@ -33,6 +37,7 @@ auth0 network-acl update [flags]
--action string Action for the rule (block, allow, log, redirect)
--active string Whether the network ACL is active ('true' or 'false')
--asns ints Comma-separated list of ASNs to match (Eg. 64496,64497,64498)
--auth0-managed strings Comma-separated list of Auth0-curated blocklists to match (Eg. auth0.icloud_relay_proxy,auth0.low_reputation). (EA only).
--country-codes strings Comma-separated list of country codes to match (Eg. US,CA,MX)
-d, --description string Description of the network ACL
--ipv4-cidrs strings Comma-separated list of IPv4 CIDR ranges (Eg. 192.168.1.0/24,10.0.0.0/8)
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ require (
github.com/AlecAivazis/survey/v2 v2.3.7
github.com/PuerkitoBio/rehttp v1.4.0
github.com/atotto/clipboard v0.1.4
github.com/auth0/go-auth0 v1.45.0
github.com/auth0/go-auth0 v1.46.0
github.com/auth0/go-auth0/v2 v2.14.0
github.com/briandowns/spinner v1.23.2
github.com/charmbracelet/glamour v1.0.0
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ github.com/apparentlymart/go-textseg/v15 v15.0.0 h1:uYvfpb3DyLSCGWnctWKGj857c6ew
github.com/apparentlymart/go-textseg/v15 v15.0.0/go.mod h1:K8XmNZdhEBkdlyDdvbmmsvpAG721bKi0joRfFdHIWJ4=
github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4=
github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI=
github.com/auth0/go-auth0 v1.45.0 h1:fQaNSWpoMneYsutOr+3fTOXIsFAQThSf2A0ShL3oaZg=
github.com/auth0/go-auth0 v1.45.0/go.mod h1:32sQB1uAn+99fJo6N819EniKq8h785p0ag0lMWhiTaE=
github.com/auth0/go-auth0 v1.46.0 h1:2awmVKsBQ+zGi66FnH5PV4NRIQCGkXZK8bnyTOPcdnE=
github.com/auth0/go-auth0 v1.46.0/go.mod h1:32sQB1uAn+99fJo6N819EniKq8h785p0ag0lMWhiTaE=
github.com/auth0/go-auth0/v2 v2.14.0 h1:zDxwRHGAt6gLK/OG6wAkB5ScQEJ8WW/ex1EnJig8fFc=
github.com/auth0/go-auth0/v2 v2.14.0/go.mod h1:Q/Y3VZVoI3sw87VyTPhx2TQL6Sq4Q/iCP67rW2gcn+M=
github.com/aybabtme/iocontrol v0.0.0-20150809002002-ad15bcfc95a0 h1:0NmehRCgyk5rljDQLKUO+cRJCnduDyn11+zGZIc9Z48=
Expand Down
43 changes: 40 additions & 3 deletions internal/cli/network_acl.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,12 @@ var (
LongForm: "user-agents",
Help: "Comma-separated list of user agents to match (Eg. badbot/*,malicious/*)",
}

networkACLAuth0Managed = Flag{
Name: "Auth0Managed",
LongForm: "auth0-managed",
Help: "Comma-separated list of Auth0-curated blocklists to match (Eg. auth0.icloud_relay_proxy,auth0.low_reputation). (EA only).",
}
)

// validateAndSetBasicFields handles the common validation and patch building logic for basic fields.
Expand All @@ -121,6 +127,7 @@ func validateAndSetBasicFields(inputs *struct {
JA3 []string
JA4 []string
UserAgents []string
Auth0Managed []string
MatchRule bool
NoMatchRule bool
}, patch *management.NetworkACL, cmd *cobra.Command) error {
Expand Down Expand Up @@ -183,6 +190,7 @@ func selectNetworkACLParams(cmd *cobra.Command) (map[string]bool, error) {
"JA3Fingerprints",
"JA4Fingerprints",
"User Agents",
"Auth0 Managed",
}

var selected []string
Expand Down Expand Up @@ -221,6 +229,7 @@ type ruleDefaults struct {
JA3 []string
JA4 []string
UserAgents []string
Auth0Managed []string
IsMatchRule bool
HasMatchRule bool
HasNotMatch bool
Expand Down Expand Up @@ -295,6 +304,9 @@ func extractCurrentRuleDefaults(currentACL *management.NetworkACL) *ruleDefaults
if match.UserAgents != nil {
defaults.UserAgents = *match.UserAgents
}
if match.Auth0Managed != nil {
defaults.Auth0Managed = *match.Auth0Managed
}
}

return defaults
Expand All @@ -313,6 +325,7 @@ type ruleInputs struct {
JA3 []string
JA4 []string
UserAgents []string
Auth0Managed []string
IsMatchRule bool
MatchRule bool
NoMatchRule bool
Expand Down Expand Up @@ -373,7 +386,7 @@ func promptForRuleDetails(cmd *cobra.Command, cli *cli, defaults *ruleDefaults,
var selectedMatchOption string
if err := (&Flag{
Name: "What kind of rule do you want to create?",
Help: "Match or Not Match rule (ASNs, Country Codes, Subdivision Codes, IPv4 CIDRs, IPv6 CIDRs, JA3/JA4 Fingerprints, User Agents)",
Help: "Match or Not Match rule (ASNs, Country Codes, Subdivision Codes, IPv4 CIDRs, IPv6 CIDRs, JA3/JA4 Fingerprints, User Agents, Auth0 Managed)",
}).Select(cmd, &selectedMatchOption, matchOptions, nil); err != nil {
return nil, err
}
Expand Down Expand Up @@ -451,6 +464,13 @@ func promptForMatchCriteria(cmd *cobra.Command, selectedParams map[string]bool,
}
}

if selectedParams["Auth0 Managed"] {
currentAuth0ManagedStr := strings.Join(defaults.Auth0Managed, ",")
if err := networkACLAuth0Managed.AskMany(cmd, &inputs.Auth0Managed, &currentAuth0ManagedStr); err != nil {
return err
}
}

return nil
}

Expand Down Expand Up @@ -510,6 +530,10 @@ func buildNetworkACLRule(inputs *ruleInputs) (*management.NetworkACLRule, error)
match.UserAgents = &inputs.UserAgents
matchProvided = true
}
if len(inputs.Auth0Managed) > 0 {
match.Auth0Managed = &inputs.Auth0Managed
matchProvided = true
}

if !matchProvided {
return nil, fmt.Errorf("at least one match criteria must be provided")
Expand Down Expand Up @@ -628,6 +652,7 @@ func createNetworkACLCmd(cli *cli) *cobra.Command {
JA3 []string
JA4 []string
UserAgents []string
Auth0Managed []string
Scope string
isMatchRule bool
}
Expand All @@ -645,7 +670,11 @@ The --rule parameter is required and must contain a valid JSON object with actio
auth0 network-acl create --description "Geo Block" --priority 2 --active true --rule '{"action":{"block":true},"scope":"authentication","match":{"geo_country_codes":["US","CA"]}}'
auth0 network-acl create --description "Redirect Traffic" --priority 3 --active true --rule '{"action":{"redirect":true,"redirect_uri":"https://example.com"},"scope":"management","match":{"ipv4_cidrs":["192.168.1.0/24"]}}'
auth0 network-acl create -d "Block Bots" -p 4 --active true --rule '{"action":{"block":true},"scope":"tenant","match":{"user_agents":["badbot/*","malicious/*"],"ja3_fingerprints":["deadbeef","cafebabe"]}}'
auth0 network-acl create --description "Complex Rule" --priority 5 --active true --rule '{"action":{"block":true},"scope":"tenant","match":{"ipv4_cidrs":["192.168.1.0/24"],"geo_country_codes":["US"]}}'`,
auth0 network-acl create --description "Complex Rule" --priority 5 --active true --rule '{"action":{"block":true},"scope":"tenant","match":{"ipv4_cidrs":["192.168.1.0/24"],"geo_country_codes":["US"]}}'

# Early Access (auth0_managed match/not_match value):
auth0 network-acl create -d "Curated Blocklist" -p 6 --active true --rule '{"action":{"log":true},"scope":"tenant","not_match":{"auth0_managed":["auth0.vpn","auth0.proxy"]}}'
`,
RunE: func(cmd *cobra.Command, args []string) error {
// Check if we're in non-interactive mode (flags provided) but rule JSON is missing.
if !canPrompt(cmd) && !cmd.Flags().Changed("rule") {
Expand Down Expand Up @@ -770,7 +799,9 @@ The --rule parameter is required and must contain a valid JSON object with actio
networkACLJA3Fingerprints.RegisterStringSlice(cmd, &inputs.JA3, nil)
networkACLJA4Fingerprints.RegisterStringSlice(cmd, &inputs.JA4, nil)
networkACLUserAgents.RegisterStringSlice(cmd, &inputs.UserAgents, nil)
networkACLAuth0Managed.RegisterStringSlice(cmd, &inputs.Auth0Managed, nil)

// These flags must be passed in non-interactive mode.
cmd.MarkFlagRequired("description")
cmd.MarkFlagRequired("active")
cmd.MarkFlagRequired("priority")
Expand All @@ -797,6 +828,7 @@ func updateNetworkACLCmd(cli *cli) *cobra.Command {
JA3 []string
JA4 []string
UserAgents []string
Auth0Managed []string
MatchRule bool
NoMatchRule bool
}
Expand All @@ -814,7 +846,11 @@ To update non-interactively, supply the description, active, priority, and rule
auth0 network-acl update <id> --active true
auth0 network-acl update <id> --description "Updated description"
auth0 network-acl update <id> --rule '{"action":{"block":true},"scope":"tenant","match":{"ipv4_cidrs":["192.168.1.0/24"]}}'
auth0 network-acl update <id> --description "Complex Rule updated" --priority 1 --active true --rule '{"action":{"block":true},"scope":"tenant","match":{"ipv4_cidrs":["192.168.1.0/24"],"geo_country_codes":["US"]}}'`,
auth0 network-acl update <id> --description "Complex Rule updated" --priority 1 --active true --rule '{"action":{"block":true},"scope":"tenant","match":{"ipv4_cidrs":["192.168.1.0/24"],"geo_country_codes":["US"]}}'

# Early Access (auth0_managed match/not_match value):
auth0 network-acl update <id> --rule '{"action":{"allow":true},"scope":"tenant","match":{"auth0_managed":["auth0.low_reputation"]}}'
`,
RunE: func(cmd *cobra.Command, args []string) error {
// Get the network ACL ID.
if len(args) > 0 {
Expand Down Expand Up @@ -924,6 +960,7 @@ To update non-interactively, supply the description, active, priority, and rule
networkACLJA3Fingerprints.RegisterStringSlice(cmd, &inputs.JA3, nil)
networkACLJA4Fingerprints.RegisterStringSlice(cmd, &inputs.JA4, nil)
networkACLUserAgents.RegisterStringSlice(cmd, &inputs.UserAgents, nil)
networkACLAuth0Managed.RegisterStringSlice(cmd, &inputs.Auth0Managed, nil)

return cmd
}
Expand Down
128 changes: 128 additions & 0 deletions internal/cli/network_acl_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,3 +97,131 @@ func TestNetworkACLPickerOptions(t *testing.T) {
})
}
}

func TestBuildNetworkACLRule_Auth0Managed(t *testing.T) {
tests := []struct {
name string
inputs *ruleInputs
assertRule func(t testing.TB, rule *management.NetworkACLRule)
expectError bool
}{
{
name: "auth0_managed on match",
inputs: &ruleInputs{
Scope: "tenant",
Action: "block",
Auth0Managed: []string{"auth0.low_reputation", "auth0.icloud_relay_proxy"},
IsMatchRule: true,
},
assertRule: func(t testing.TB, rule *management.NetworkACLRule) {
assert.Nil(t, rule.NotMatch)
assert.NotNil(t, rule.Match)
assert.NotNil(t, rule.Match.Auth0Managed)
assert.Equal(t, []string{"auth0.low_reputation", "auth0.icloud_relay_proxy"}, *rule.Match.Auth0Managed)
},
},
{
name: "auth0_managed on not_match",
inputs: &ruleInputs{
Scope: "tenant",
Action: "block",
Auth0Managed: []string{"auth0.low_reputation"},
IsMatchRule: false,
},
assertRule: func(t testing.TB, rule *management.NetworkACLRule) {
assert.Nil(t, rule.Match)
assert.NotNil(t, rule.NotMatch)
assert.NotNil(t, rule.NotMatch.Auth0Managed)
assert.Equal(t, []string{"auth0.low_reputation"}, *rule.NotMatch.Auth0Managed)
},
},
{
name: "auth0_managed coexists with other criteria",
inputs: &ruleInputs{
Scope: "tenant",
Action: "block",
IPv4CIDRs: []string{"192.168.1.0/24"},
Auth0Managed: []string{"auth0.low_reputation"},
IsMatchRule: true,
},
assertRule: func(t testing.TB, rule *management.NetworkACLRule) {
assert.NotNil(t, rule.Match)
assert.NotNil(t, rule.Match.IPv4Cidrs)
assert.NotNil(t, rule.Match.Auth0Managed)
assert.Equal(t, []string{"auth0.low_reputation"}, *rule.Match.Auth0Managed)
},
},
{
name: "auth0_managed empty is not set",
inputs: &ruleInputs{
Scope: "tenant",
Action: "block",
IsMatchRule: true,
},
expectError: true,
},
}

for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
rule, err := buildNetworkACLRule(test.inputs)

if test.expectError {
assert.Error(t, err)
return
}

assert.NoError(t, err)
test.assertRule(t, rule)
})
}
}

func TestExtractCurrentRuleDefaults_Auth0Managed(t *testing.T) {
tests := []struct {
name string
acl *management.NetworkACL
wantAuth0Managed []string
}{
{
name: "extracts auth0_managed from match",
acl: &management.NetworkACL{
Rule: &management.NetworkACLRule{
Match: &management.NetworkACLRuleMatch{
Auth0Managed: &[]string{"auth0.low_reputation", "auth0.icloud_relay_proxy"},
},
},
},
wantAuth0Managed: []string{"auth0.low_reputation", "auth0.icloud_relay_proxy"},
},
{
name: "extracts auth0_managed from not_match",
acl: &management.NetworkACL{
Rule: &management.NetworkACLRule{
NotMatch: &management.NetworkACLRuleMatch{
Auth0Managed: &[]string{"auth0.low_reputation"},
},
},
},
wantAuth0Managed: []string{"auth0.low_reputation"},
},
{
name: "no auth0_managed set",
acl: &management.NetworkACL{
Rule: &management.NetworkACLRule{
Match: &management.NetworkACLRuleMatch{
IPv4Cidrs: &[]string{"192.168.1.0/24"},
},
},
},
wantAuth0Managed: nil,
},
}

for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
defaults := extractCurrentRuleDefaults(test.acl)
assert.Equal(t, test.wantAuth0Managed, defaults.Auth0Managed)
})
}
}
11 changes: 9 additions & 2 deletions internal/display/network_acl.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,12 +100,15 @@ func (v *networkACLView) KeyValues() [][]string {
if match.UserAgents != nil && len(*match.UserAgents) > 0 {
keyValues = append(keyValues, []string{"USER AGENTS", strings.Join(*match.UserAgents, ", ")})
}

if match.Auth0Managed != nil && len(*match.Auth0Managed) > 0 {
keyValues = append(keyValues, []string{"AUTH0 MANAGED", strings.Join(*match.Auth0Managed, ", ")})
}
}

// Add not_match criteria if present.
if acl.Rule.NotMatch != nil {
notMatch := acl.Rule.NotMatch
keyValues = append(keyValues, []string{"NOT MATCH", "true"})

if len(notMatch.Asns) > 0 {
asns := make([]string, len(notMatch.Asns))
Expand Down Expand Up @@ -142,6 +145,10 @@ func (v *networkACLView) KeyValues() [][]string {
if notMatch.UserAgents != nil && len(*notMatch.UserAgents) > 0 {
keyValues = append(keyValues, []string{"NOT USER AGENTS", strings.Join(*notMatch.UserAgents, ", ")})
}

if notMatch.Auth0Managed != nil && len(*notMatch.Auth0Managed) > 0 {
keyValues = append(keyValues, []string{"NOT AUTH0 MANAGED", strings.Join(*notMatch.Auth0Managed, ", ")})
}
}
}

Expand Down Expand Up @@ -192,7 +199,7 @@ func makeNetworkACLView(acl *management.NetworkACL) *networkACLView {
Active: fmt.Sprintf("%v", active),
Action: action,
Rule: string(ruleJSON),
raw: rawData,
raw: &rawData,
}
}

Expand Down
Loading
Loading