Skip to content

Commit eb141da

Browse files
authored
validate uuid requests (#98)
* validate uuid requests Signed-off-by: Mike Mason <[email protected]> * golanglint-ci action skip-pkg-cache Seeing issues with running golanglint-ci action, one solution was to disable package cache. https://github.com/metal-toolbox/hollow-metadataservice/actions/runs/4683823976/jobs/8299350650?pr=98 golangci/golangci-lint-action#23 (comment) Signed-off-by: Mike Mason <[email protected]> --------- Signed-off-by: Mike Mason <[email protected]>
1 parent e47b818 commit eb141da

File tree

7 files changed

+60
-14
lines changed

7 files changed

+60
-14
lines changed

.github/workflows/lint-test.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ jobs:
3535
with:
3636
version: v1.51.1
3737
args: --timeout=5m
38+
skip-pkg-cache: true
3839

3940
- name: Run go tests for generated models code
4041
run: go test -race ./internal/models

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ require (
1010
github.com/gin-contrib/zap v0.1.0
1111
github.com/gin-gonic/gin v1.9.0
1212
github.com/go-playground/validator/v10 v10.12.0
13+
github.com/google/uuid v1.3.0
1314
github.com/jmoiron/sqlx v1.3.5
1415
github.com/lib/pq v1.10.7
1516
github.com/mitchellh/go-homedir v1.1.0

go.sum

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -642,8 +642,6 @@ go.etcd.io/etcd/api/v3 v3.5.4/go.mod h1:5GB2vv4A4AOn3yk7MftYGHkUfGtDHnEraIjym4dY
642642
go.etcd.io/etcd/client/pkg/v3 v3.5.4/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g=
643643
go.etcd.io/etcd/client/v2 v2.305.4/go.mod h1:Ud+VUwIi9/uQHOMA+4ekToJ12lTxlv0zB/+DHwTGEbU=
644644
go.etcd.io/etcd/client/v3 v3.5.4/go.mod h1:ZaRkVgBZC+L+dLCjTcF1hRXpgZXQPOvnA/Ak/gq3kiY=
645-
go.hollow.sh/toolbox v0.4.1 h1:4ANXNRybTyLd0T/3+ePXp9PAnr+j7HXQDTeiEAaup3k=
646-
go.hollow.sh/toolbox v0.4.1/go.mod h1:kroiA62wlwnxLixA+aWV9Oc26piRaAYMn+uqHYRRfdc=
647645
go.hollow.sh/toolbox v0.5.1 h1:x/tRdpgUFckT/pw6FySxUpSFxhw+Sc66zxbwlra+br4=
648646
go.hollow.sh/toolbox v0.5.1/go.mod h1:nfUNHobFfItossU5I0m7h2dw+0nY7rQt3DSUm2wGI5Q=
649647
go.infratographer.com/x v0.0.3 h1:7txN1iBq1Ts4XF6Ea/9/LWK2vpTeXKnh+DjdJ1OLHVQ=

pkg/api/v1/router.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111

1212
"github.com/gin-gonic/gin"
1313
"github.com/go-playground/validator/v10"
14+
"github.com/google/uuid"
1415
"github.com/jmoiron/sqlx"
1516
"go.uber.org/zap"
1617

@@ -59,6 +60,12 @@ var (
5960
// - the item wasn't found in the DB
6061
// - the item wasn't found in the upstream lookup service
6162
errNotFound = errors.New("not found")
63+
64+
// ErrUUIDNotFound is returned when an expected uuid is not provided.
65+
ErrUUIDNotFound = errors.New("uuid not found")
66+
67+
// ErrInvalidUUID is returned when an invalid uuid is provided.
68+
ErrInvalidUUID = errors.New("invalid uuid")
6269
)
6370

6471
// Router provides a router for the v1 API
@@ -263,3 +270,18 @@ func setupValidator() {
263270
return name
264271
})
265272
}
273+
274+
// getUUIDParam parses and validates a UUID from the request params if the param is found
275+
func getUUIDParam(c *gin.Context, name string) (string, error) {
276+
id, ok := c.Params.Get(name)
277+
278+
if !ok || id == "" {
279+
return "", ErrUUIDNotFound
280+
}
281+
282+
if _, err := uuid.Parse(id); err != nil {
283+
return "", ErrInvalidUUID
284+
}
285+
286+
return id, nil
287+
}

pkg/api/v1/router_instance_metadata.go

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -87,10 +87,11 @@ func (r *Router) instanceMetadataGet(c *gin.Context) {
8787
// which instances the metadata service already knows about, and which
8888
// instances may still need their metadata pushed to the service.
8989
func (r *Router) instanceMetadataGetInternal(c *gin.Context) {
90-
instanceID, ok := c.Params.Get("instance-id")
90+
instanceID, err := getUUIDParam(c, "instance-id")
91+
92+
if err != nil {
93+
invalidUUIDResponse(c, err)
9194

92-
if !ok || instanceID == "" {
93-
notFoundResponse(c)
9495
return
9596
}
9697

@@ -140,10 +141,11 @@ func (r *Router) instanceUserdataGet(c *gin.Context) {
140141
// which instances the userdata service already knows about, and which
141142
// instances may still need their userdata pushed to the service.
142143
func (r *Router) instanceUserdataGetInternal(c *gin.Context) {
143-
instanceID, ok := c.Params.Get("instance-id")
144+
instanceID, err := getUUIDParam(c, "instance-id")
145+
146+
if err != nil {
147+
invalidUUIDResponse(c, err)
144148

145-
if !ok || instanceID == "" {
146-
notFoundResponse(c)
147149
return
148150
}
149151

@@ -240,10 +242,11 @@ func (r *Router) instanceMetadataDelete(c *gin.Context) {
240242
// When deleting metadata for an instance, we need to check if there is
241243
// userdata stored for the instance. If there is not, we should go ahead and
242244
// also delete the associated instance_ip_addresses rows.
243-
instanceID, ok := c.Params.Get("instance-id")
245+
instanceID, err := getUUIDParam(c, "instance-id")
246+
247+
if err != nil {
248+
invalidUUIDResponse(c, err)
244249

245-
if !ok || instanceID == "" {
246-
notFoundResponse(c)
247250
return
248251
}
249252

@@ -261,10 +264,11 @@ func (r *Router) instanceUserdataDelete(c *gin.Context) {
261264
// When deleting userdata for an instance, we need to check if there is
262265
// metadata stored for the instance. If there is not, we should go ahead and
263266
// also delete the associated instance_ip_addresses rows.
264-
instanceID, ok := c.Params.Get("instance-id")
267+
instanceID, err := getUUIDParam(c, "instance-id")
268+
269+
if err != nil {
270+
invalidUUIDResponse(c, err)
265271

266-
if !ok || instanceID == "" {
267-
notFoundResponse(c)
268272
return
269273
}
270274

pkg/api/v1/router_instance_metadata_test.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -622,6 +622,12 @@ func TestGetMetadataInternal(t *testing.T) {
622622
http.StatusNotFound,
623623
"",
624624
},
625+
{
626+
"invalid ID",
627+
"bad-id",
628+
http.StatusBadRequest,
629+
"",
630+
},
625631
{
626632
"Instance A",
627633
dbtools.FixtureInstanceA.InstanceID,

pkg/api/v1/router_responses.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,20 @@ func badRequestResponse(c *gin.Context, message string, err error) {
4646
c.AbortWithStatusJSON(http.StatusBadRequest, &ErrorResponse{Message: message, Errors: errMsgs})
4747
}
4848

49+
func invalidUUIDResponse(c *gin.Context, err error) {
50+
if err != nil {
51+
switch {
52+
case errors.Is(err, ErrUUIDNotFound):
53+
notFoundResponse(c)
54+
case errors.Is(err, ErrInvalidUUID):
55+
c.Error(err) //nolint:errcheck // no need to check this error.
56+
c.AbortWithStatusJSON(http.StatusBadRequest, &ErrorResponse{Message: err.Error(), Errors: []string{err.Error()}})
57+
}
58+
}
59+
60+
c.AbortWithStatusJSON(http.StatusInternalServerError, &ErrorResponse{Errors: []string{"internal server error"}})
61+
}
62+
4963
func getErrorMessagesFromError(err error) []string {
5064
if err == nil {
5165
return []string{}

0 commit comments

Comments
 (0)