Skip to content

[STORY-3093] feat(dbng): add firewall rules commands - #1171

Merged
briceamen merged 12 commits into
masterfrom
feat/STORY-3093/firewall-rules
Jan 7, 2026
Merged

briceamen merged 12 commits into
masterfrom
feat/STORY-3093/firewall-rules

Conversation

@briceamen

@briceamen briceamen commented Dec 31, 2025 •

Copy link
Copy Markdown
Contributor

Summary

Add firewall rules management commands for DBNG databases:

  • database-firewall-rules - List firewall rules
  • database-firewall-rules-add - Add custom CIDR or managed range rule
  • database-firewall-rules-remove - Remove a rule
  • database-firewall-managed-ranges - List available managed ranges

Commands support both positional arguments and --database flag, matching existing DBNG command patterns (database-info, database-destroy).

Usage examples

# Positional argument style
scalingo database-firewall-rules my-db-id
scalingo database-firewall-rules-add my-db-id --cidr 203.0.113.0/24 --label "Office"
scalingo database-firewall-rules-remove my-db-id rule-id

# --database flag style
scalingo --database my-db database-firewall-rules
scalingo --database my-db database-firewall-rules-add --managed-range man-osc-fr1-egress
scalingo --database my-db database-firewall-rules-remove rule-id

Changes

  • Added GetAddonIDFromDatabase helper in detect/app.go to resolve addon ID from database ID
  • Firewall commands now support positional args like other DBNG commands

Test plan

Tested on staging (osc-st-fr1) with database test-firewall-rules-db:

Positional argument style:

  • database-firewall-rules test-firewall-rules-db - List rules
  • database-firewall-managed-ranges test-firewall-rules-db - List managed ranges
  • database-firewall-rules-add test-firewall-rules-db --cidr 203.0.113.0/24 --label "Test office" - Add custom rule
  • database-firewall-rules-remove test-firewall-rules-db <rule-id> - Remove rule

--database flag style:

  • --database test-firewall-rules-db database-firewall-rules - List rules
  • --database test-firewall-rules-db database-firewall-rules-add --managed-range man-osc-st-fr1-egress - Add managed range
  • --database test-firewall-rules-db database-firewall-rules-remove <rule-id> - Remove rule

@notion-workspace

Copy link
Copy Markdown

@briceamen
briceamen requested a review from Copilot December 31, 2025 10:53

This comment was marked as outdated.

@briceamen briceamen self-assigned this Dec 31, 2025
@briceamen
briceamen requested a review from Copilot December 31, 2025 13:26

This comment was marked as outdated.

@briceamen
briceamen marked this pull request as ready for review December 31, 2025 13:28
@briceamen
briceamen force-pushed the feat/STORY-3093/firewall-rules branch from 10d0d9a to ea3aaaa Compare December 31, 2025 13:39
@briceamen
briceamen requested a review from Copilot December 31, 2025 13:40

This comment was marked as outdated.

@sc-david-voisin sc-david-voisin 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.

Looks good to me, however I have few questions/suggestions

Comment thread detect/app.go Outdated
Comment thread dbng/firewall_rules.go
Comment thread dbng/firewall_rules.go Outdated
}

io.Statusf("Firewall rule '%s' has been added to database '%s'.\n", rule.ID, databaseID)
io.Warning("Firewall rules take time to be applied due to infrastructure provisioning.")

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.

Maybe reformulate a bit. A proposition:

"Expect some delay for the firewall rules to be applied, due to infrastructure provisioning."

Comment thread dbng/firewall_rules.go
Comment thread detect/app.go Outdated
Comment thread cmd/firewall_rules.go Outdated
return cli.ShowCommandHelp(ctx, c, "database-firewall-rules")
}

utils.CheckForConsent(ctx, databaseID, utils.ConsentTypeDBs)

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.

question: is the consent required here?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

IMO yes. But why not?

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.

Because I am not sure how the consent should be used in that case. This is for a database setting, not accessing the data?

Comment thread cmd/firewall_rules.go Outdated
Comment thread cmd/firewall_rules.go
Comment thread cmd/firewall_rules.go Outdated
Comment thread dbng/firewall_rules.go Outdated
Comment thread dbng/firewall_rules.go Outdated
}

io.Statusf("Firewall rule '%s' has been removed from database '%s'.\n", ruleID, databaseID)
io.Warning("Expect some delay for the firewall rules to be applied, due to infrastructure provisioning.")

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.

nitpick: do we want to use applied here?

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.

@briceamen up here. Is applied applicable for removal?

@curzolapierre curzolapierre left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Some remarks in addition of @matthieu526-scalingo's ones

Overall, LGTM

Comment thread cmd/firewall_rules.go Outdated
return cli.ShowCommandHelp(ctx, c, "database-firewall-rules")
}

utils.CheckForConsent(ctx, databaseID, utils.ConsentTypeDBs)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

IMO yes. But why not?

Comment thread cmd/firewall_rules.go Outdated
Comment thread cmd/firewall_rules.go Outdated
Comment on lines +32 to +43
var databaseID, addonID string
var err error

switch c.Args().Len() {
case 0:
// No positional arg, database from --database flag
databaseID, addonID = detect.GetCurrentDatabase(ctx, c)
case 1:
// database-id provided as positional arg
databaseID = c.Args().First()
addonID, err = detect.GetAddonIDFromDatabase(ctx, databaseID)
if err != nil {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Semantically we used database "name" instead of ID. Could you apply the change elsewhere in this file?

Or do I miss something?

Suggested change
var databaseID, addonID string
var err error
switch c.Args().Len() {
case 0:
// No positional arg, database from --database flag
databaseID, addonID = detect.GetCurrentDatabase(ctx, c)
case 1:
// database-id provided as positional arg
databaseID = c.Args().First()
addonID, err = detect.GetAddonIDFromDatabase(ctx, databaseID)
if err != nil {
var databaseName, addonID string
var err error
switch c.Args().Len() {
case 0:
// No positional arg, database from --database flag
databaseName, addonID = detect.GetCurrentDatabase(ctx, c)
case 1:
// database-name provided as positional arg
databaseName = c.Args().First()
addonID, err = detect.GetAddonIDFromDatabase(ctx, databaseName)
if err != nil {

Comment thread detect/app.go Outdated
// A DBNG database is modeled as an app with a single addon (itself),
// whereas an application can have multiple addons (postgresql, redis, etc.).
// If multiple addons are returned, the ID is likely an application, not a database.
addons, err := client.AddonsList(ctx, databaseID)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Like before, this should be the databaseName

Suggested change
addons, err := client.AddonsList(ctx, databaseID)
addons, err := client.AddonsList(ctx, databaseName)

@curzolapierre curzolapierre left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I've remaining questions

Comment thread cmd/firewall_rules.go
Comment on lines +33 to +40
if err != nil {
if err == detect.ErrTooManyArguments {
io.Error(err)
return cli.ShowCommandHelp(ctx, c, "database-firewall-rules")
}
errorQuit(ctx, err)
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggestion: Could be simplified by:

Suggested change
if err != nil {
if err == detect.ErrTooManyArguments {
io.Error(err)
return cli.ShowCommandHelp(ctx, c, "database-firewall-rules")
}
errorQuit(ctx, err)
}
if errors.Is(err, detect.ErrTooManyArguments) {
io.Error(err)
return cli.ShowCommandHelp(ctx, c, "database-firewall-rules")
}
if err != nil {
errorQuit(ctx, err)
}

In addition, this is a good practice to use errors.Is instead of direct comparison.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Much cleaner indeed. Thanks.

Comment thread cmd/firewall_rules.go Outdated
Comment on lines +99 to +101
if managedRange != "" && label != "" {
io.Warning("--label flag is ignored for managed ranges")
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Question: are you sure we cannot add label to managed ranges?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Oups you're right FirewallRuleCreateParams has Label as a general field (not specific to custom ranges), and FirewallRule response also has Label for all types. Will change

Comment thread cmd/firewall_rules.go
Comment on lines +209 to 215
if err != nil {
if err == detect.ErrTooManyArguments {
io.Error(err)
return cli.ShowCommandHelp(ctx, c, "database-firewall-managed-ranges")
}
default:
io.Error("Too many arguments")
return cli.ShowCommandHelp(ctx, c, "database-firewall-managed-ranges")
errorQuit(ctx, err)
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Same as above

Comment thread cmd/firewall_rules.go
Comment on lines +77 to +82
if err != nil {
if err == detect.ErrTooManyArguments {
io.Error(err)
return cli.ShowCommandHelp(ctx, c, "database-firewall-rules-add")
}
default:
io.Error("Too many arguments")
return cli.ShowCommandHelp(ctx, c, "database-firewall-rules-add")
errorQuit(ctx, err)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Same as above

@curzolapierre curzolapierre left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks! LGTM

@briceamen
briceamen merged commit 4f3135a into master Jan 7, 2026
7 checks passed
@briceamen
briceamen deleted the feat/STORY-3093/firewall-rules branch January 7, 2026 10:24
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.

5 participants