Skip to content

Commit 02b69a2

Browse files
Add Validations and Sanitize for Inputs (#357)
* loadbalancer validations and sanitizing Signed-off-by: Matt Siwiec <[email protected]> * validation for rest of resources, fix Makefile Signed-off-by: Stephen Hwang <[email protected]> * make generate Signed-off-by: Stephen Hwang <[email protected]> * fix tests Signed-off-by: Stephen Hwang <[email protected]> * remove comment Signed-off-by: Stephen Hwang <[email protected]> --------- Signed-off-by: Matt Siwiec <[email protected]> Signed-off-by: Stephen Hwang <[email protected]> Co-authored-by: Matt Siwiec <[email protected]>
1 parent e10fc85 commit 02b69a2

23 files changed

+331
-54
lines changed

internal/ent/generated/port/port.go

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

internal/ent/generated/port_create.go

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

internal/ent/generated/port_update.go

Lines changed: 10 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

internal/ent/generated/runtime/runtime.go

Lines changed: 4 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

internal/ent/schema/loadbalancer.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import (
1414

1515
"go.infratographer.com/load-balancer-api/internal/ent/schema/audit"
1616
"go.infratographer.com/load-balancer-api/internal/ent/schema/softdelete"
17+
"go.infratographer.com/load-balancer-api/internal/ent/schema/validations"
1718
"go.infratographer.com/load-balancer-api/x/pubsubinfo"
1819
)
1920

@@ -44,7 +45,7 @@ func (LoadBalancer) Fields() []ent.Field {
4445
entgql.OrderField("ID"),
4546
),
4647
field.Text("name").
47-
NotEmpty().
48+
Validate(validations.NameField).
4849
Comment("The name of the load balancer.").
4950
Annotations(
5051
entgql.OrderField("NAME"),

internal/ent/schema/origin.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ func (Origin) Fields() []ent.Field {
4242
Unique().
4343
Immutable(),
4444
field.String("name").
45-
NotEmpty().
45+
Validate(validations.NameField).
4646
Annotations(
4747
entgql.OrderField("name"),
4848
),

internal/ent/schema/pool.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313

1414
"go.infratographer.com/load-balancer-api/internal/ent/schema/audit"
1515
"go.infratographer.com/load-balancer-api/internal/ent/schema/softdelete"
16+
"go.infratographer.com/load-balancer-api/internal/ent/schema/validations"
1617
"go.infratographer.com/load-balancer-api/x/pubsubinfo"
1718
)
1819

@@ -39,7 +40,7 @@ func (Pool) Fields() []ent.Field {
3940
Unique().
4041
Immutable(),
4142
field.String("name").
42-
NotEmpty().
43+
Validate(validations.NameField).
4344
Annotations(
4445
entgql.OrderField("name"),
4546
),

internal/ent/schema/port.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ func (Port) Fields() []ent.Field {
5252
entgql.OrderField("number"),
5353
),
5454
field.String("name").
55+
Validate(validations.OptionalNameField).
5556
Annotations(
5657
entgql.OrderField("name"),
5758
).

internal/ent/schema/provider.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212

1313
"go.infratographer.com/load-balancer-api/internal/ent/schema/audit"
1414
"go.infratographer.com/load-balancer-api/internal/ent/schema/softdelete"
15+
"go.infratographer.com/load-balancer-api/internal/ent/schema/validations"
1516
"go.infratographer.com/load-balancer-api/x/pubsubinfo"
1617
)
1718

@@ -42,7 +43,7 @@ func (Provider) Fields() []ent.Field {
4243
entgql.OrderField("ID"),
4344
),
4445
field.String("name").
45-
NotEmpty().
46+
Validate(validations.NameField).
4647
Comment("The name of the load balancer provider.").
4748
Annotations(
4849
entgql.OrderField("NAME"),
Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
11
package validations
22

3-
import "errors"
3+
import (
4+
"errors"
5+
)
46

57
// ErrInvalidIPAddress is returned when the given string is not a valid IP address
68
var ErrInvalidIPAddress = errors.New("invalid ip address")
79

810
// ErrRestrictedPort is returned when the given port is restricted
911
var ErrRestrictedPort = errors.New("port number restricted")
12+
13+
// ErrFieldEmpty is returned when a field is empty
14+
var ErrFieldEmpty = errors.New("must not be empty")

internal/ent/schema/validations/validations.go

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,23 @@
22
package validations
33

44
import (
5+
"fmt"
56
"net"
7+
"regexp"
8+
"strings"
69

710
"go.infratographer.com/load-balancer-api/internal/config"
811

912
"golang.org/x/exp/slices"
1013
)
1114

15+
const (
16+
// maxNameLength is the maximum length of a name field
17+
maxNameLength = 64
18+
// unallowedChars is a string containing the unallowed characters in a string for a name field
19+
unallowedChars = `<>&'"`
20+
)
21+
1222
// IPAddress validates if the given string is a valid IP address
1323
func IPAddress(ip string) error {
1424
if net.ParseIP(ip) == nil {
@@ -26,3 +36,44 @@ func RestrictedPorts(port int) error {
2636

2737
return nil
2838
}
39+
40+
// NameField validates the name field
41+
func NameField(name string) error {
42+
if len(strings.TrimSpace(name)) == 0 {
43+
return ErrFieldEmpty
44+
}
45+
46+
if len(name) > maxNameLength {
47+
return fmt.Errorf("must not be longer than %d characters", maxNameLength) // nolint: goerr113
48+
}
49+
50+
if containsUnallowedChars(name) {
51+
return fmt.Errorf("must not contain the following characters: %s", unallowedChars) // nolint: goerr113
52+
}
53+
54+
return nil
55+
}
56+
57+
// OptionalNameField validates the name field when optional
58+
func OptionalNameField(name string) error {
59+
if len(name) > maxNameLength {
60+
return fmt.Errorf("must not be longer than %d characters", maxNameLength) // nolint: goerr113
61+
}
62+
63+
if containsUnallowedChars(name) {
64+
return fmt.Errorf("must not contain the following characters: %s", unallowedChars) // nolint: goerr113
65+
}
66+
67+
return nil
68+
}
69+
70+
func containsUnallowedChars(s string) bool {
71+
// Define the regular expression pattern to match the unallowed characters
72+
pattern := "[" + unallowedChars + "]"
73+
74+
// Compile the regular expression pattern
75+
regex := regexp.MustCompile(pattern)
76+
77+
// Check if the pattern matches any part of the string
78+
return regex.MatchString(s)
79+
}

internal/graphapi/errors.go

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
package graphapi
22

3-
import "errors"
3+
import (
4+
"errors"
5+
"fmt"
6+
)
47

58
var (
69
// ErrPortNumberInUse is returned when a port number is already in use.
@@ -20,4 +23,25 @@ var (
2023

2124
// ErrLoadBalancerLimitReached is returned when the load balancer limit has been reached for an owner.
2225
ErrLoadBalancerLimitReached = errors.New("load balancer limit reached")
26+
27+
// ErrFieldEmpty is returned when a required field is empty.
28+
ErrFieldEmpty = errors.New("must not be empty")
29+
30+
// ErrInvalidCharacters is returned when an invalid input is provided
31+
ErrInvalidCharacters = errors.New("valid characters are A-Z a-z 0-9 _ -")
2332
)
33+
34+
// ErrInvalidField is returned when an invalid input is provided.
35+
type ErrInvalidField struct {
36+
field string
37+
err error
38+
}
39+
40+
// Error implements the error interface.
41+
func (e *ErrInvalidField) Error() string {
42+
return fmt.Sprintf("%s: %v", e.field, e.err)
43+
}
44+
45+
func newInvalidFieldError(field string, err error) *ErrInvalidField {
46+
return &ErrInvalidField{field: field, err: err}
47+
}

internal/graphapi/loadbalancer.resolvers.go

Lines changed: 38 additions & 12 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)