Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[automate-3198] reduce validation #3312

Merged
merged 22 commits into from
Apr 15, 2020
Merged

Conversation

blakestier
Copy link

@blakestier blakestier commented Apr 7, 2020

🔩 Description: What code changed, and why?

When creating a project, we use the same validation as other objects at the server level: character count must be 64 or less.

However, we auto-generate several roles and policies using that id and additional characters. The resulting policy id can then be over the expected limit, making it impossible to Get the policy bc of our validation on id length in Get requests.

With this change, project_ids must be 48 chars or less (allowing the other id creation without trouble).

Validation on policy Get requests (and, while I was in there, all other resource requests that didn't create the id) no longer validate on length. Instead, validation confirms the required field is present and has more than whitespace characters.

It was a toss up whether to put the validation for this in the server (where we do our other proto validations, and where the problem would be caught early) or in the db (where we probably should have our more fine-grained validation code). The answer is probably both, but this change keeps it in the server, with a few moves to storage-level validation that had parity with this kind of validation.

👟 How to Build and Test the Change

start on a studio without this version of authz

make a project with an id longer than 50 chars
curl -kH "api-token: $TOK" -d '{"name":"p123456789p123456789p123456789p123456789p123456789p123456789", "id":"p123456789p123456789p123456789p123456789p12342222"}' https://a2-dev.test/apis/iam/v2/projects

attempt to fetch the associated policy (this should fail)
curl -kH "api-token: $TOK" https://a2-dev.test/apis/iam/v2/policies/p123456789p123456789p123456789p123456789p123456789p123456789-project-editors

rebuild components/authz-service

attempt to fetch the same policy (should now succeed)
curl -kH "api-token: $TOK" https://a2-dev.test/apis/iam/v2/policies/p123456789p123456789p123456789p123456789p123456789p123456789-project-editors

attempt to create a project with an id longer than 48 chars (should now fail)
curl -kH "api-token: $TOK" -d '{"name":"p123456789p123456789p123456789p123456789p123456789p123456789", "id":"p123456789p123456789p123456789p123456789p12342222"}' https://a2-dev.test/apis/iam/v2/projects {"error":"invalid CreateProjectReq.Id: value does not match regex pattern \"^[a-z0-9-_]{1,48}$\"","code":3,"message":"invalid CreateProjectReq.Id: value does not match regex pattern \"^[a-z0-9-_]{1,48}$\"","details":[]}

Also, any other requests (GetRule, GetPolicy, etc) now fail with InvalidArg if the required ids are blank or absent.

✅ Checklist

📷 Screenshots, if applicable

@blakestier blakestier force-pushed the automate-3198/reduce-validation branch 5 times, most recently from 4250081 to fee7483 Compare April 10, 2020 16:29
@blakestier blakestier marked this pull request as ready for review April 10, 2020 17:32
@blakestier blakestier requested a review from a team as a code owner April 10, 2020 17:32
@blakestier blakestier changed the title Automate 3198/reduce validation [automate-3198] reduce validation Apr 10, 2020
@@ -13,7 +13,7 @@ import (
// TimestampName returns a name with a timestamp
func TimestampName() string {
ts := time.Now()
return "integration-diagnostic-" + ts.Format("20060102150405")
return "diagnostic-" + ts.Format("20060102150405")
Copy link
Author

Choose a reason for hiding this comment

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

didn't fit the new char limit

@@ -948,7 +948,7 @@
end

after(:all) do
resp = automate_api_request("/apis/iam/v2/projects/#{CUSTOM_RULE[:project_id]}/rules/#{CUSTOM_RULE[:id]}", http_method: 'DELETE')
resp = automate_api_request("/apis/iam/v2/projects/#{CUSTOM_RULE_1[:project_id]}/rules/#{CUSTOM_RULE_1[:id]}", http_method: 'DELETE')
Copy link
Author

Choose a reason for hiding this comment

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

driveby fix

@blakestier blakestier self-assigned this Apr 10, 2020
@blakestier blakestier added auth-team anything that needs to be on the auth team board automate-auth labels Apr 10, 2020
@@ -134,31 +134,11 @@ func TestValidationCreatePolicy(t *testing.T) {
Statements: []*v2.Statement{&validStatement},
},
// projects
"whitespace projects list": &v2.CreatePolicyReq{
Copy link
Contributor

@bcmdarroch bcmdarroch Apr 10, 2020

Choose a reason for hiding this comment

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

these are all pushed into server tests?

Copy link
Author

Choose a reason for hiding this comment

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

Several that were about validation are removed as they are now the equivalent of a "not found"-- instead of duplicating more invalid things that would result in "not found", I removed them.

Copy link
Contributor

@bcmdarroch bcmdarroch left a comment

Choose a reason for hiding this comment

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

Looks good to me!

I did find something that we should probably fix in another card:

Fetching a rule with a missing rule ID gets the nice validation error you added.

[42][default:/src:0]# curl -kH "api-token: $TOK" https://a2-dev.test/apis/iam/v2/projects/neato/rules/ | jq
{
  "error": "a rule id is required and must contain at least one non-whitespace character",
  "code": 3,
  "message": "a rule id is required and must contain at least one non-whitespace character",
  "details": []
}

But fetching a project with a missing ID gets this error that's a bit of a red herring:

[47][default:/src:0]# curl -kH "api-token: $TOK" https://a2-dev.test/apis/iam/v2/projects/ | jq
{
  "error": "error authorizing action \"iam:projects:get\" on resource \"iam:projects:\" filtered by projects [] for members [\"token:admin-token-1586543035\"]: rpc error: code = InvalidArgument desc = invalid ProjectsAuthorizedReq.Resource: value does not match regex pattern \"^[a-z][^:*]*(?::[^:*]+)*$\"",
  "code": 7,
  "message": "error authorizing action \"iam:projects:get\" on resource \"iam:projects:\" filtered by projects [] for members [\"token:admin-token-1586543035\"]: rpc error: code = InvalidArgument desc = invalid ProjectsAuthorizedReq.Resource: value does not match regex pattern \"^[a-z][^:*]*(?::[^:*]+)*$\"",
  "details": []
}

@@ -189,8 +189,8 @@ func TestGetProject(t *testing.T) {
grpctest.AssertCode(t, codes.InvalidArgument, err)
assert.Nil(t, resp)
}},
{"if the project id is invalid, returns 'invalid argument'", func(t *testing.T) {
resp, err := cl.GetProject(ctx, &api.GetProjectReq{Id: "no spaces allowed"})
Copy link
Contributor

Choose a reason for hiding this comment

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

so these no space allowed would return not found right? Could we add tests that verify that behavior?

Copy link
Author

Choose a reason for hiding this comment

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

since we're not validating at this level, an invalid name is the same as a not found. there are other tests for not found names, but they seemed functionally equivalent. What do think?

return err
}

func confirmRequiredField(field, fieldName, resourceName string) error {
Copy link
Contributor

Choose a reason for hiding this comment

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

nice DRY refactor 🎉

Copy link
Contributor

@msorens msorens left a comment

Choose a reason for hiding this comment

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

Nice work! Some notes below but everything looks sound so 👍 .

if err != nil {
return nil, status.Errorf(codes.InvalidArgument, err.Error())
}
err = validateProjects(req.Projects)
Copy link
Contributor

Choose a reason for hiding this comment

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

You have two calls to this new function, but they return very different messages from each other. Was that intentional...?

Copy link
Author

Choose a reason for hiding this comment

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

Yes-- once it's called within the primary server call itself (where the code is processed/returned), the other time in a helper, which just bubbles the error. That said, I can try to make that less confusing!

@@ -881,8 +881,8 @@ func TestGetPolicy(t *testing.T) {
require.Nil(t, pol)
grpctest.AssertCode(t, codes.InvalidArgument, err)
}},
{"fails with InvalidArgument when ID isn't valid", func(t *testing.T) {
req := api_v2.GetPolicyReq{Id: "no spaces"}
{"fails with InvalidArgument when ID is whitespace", func(t *testing.T) {
Copy link
Contributor

Choose a reason for hiding this comment

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

I think this change to "is whitespace" is valuable; consider propagating to the other touched tests in this file that still say "is not valid".

p, err := storage.NewProject(req.Id, req.Name, storage.Custom, storage.NoRules)
if err != nil {
return nil, status.Errorf(codes.InvalidArgument,
return nil, status.Errorf(codes.Internal,
Copy link
Contributor

Choose a reason for hiding this comment

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

Good eye!

@@ -74,9 +74,9 @@ func TestCreateRule(t *testing.T) {
grpctest.AssertCode(t, codes.InvalidArgument, err)
assert.Nil(t, resp)
}},
{"if the passed rule project id is invalid, returns 'invalid argument'", func(t *testing.T) {
{"if the passed rule project id is empty spaces, returns 'invalid argument'", func(t *testing.T) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Consistency with previous 2 files suggest "is whitespace":

Suggested change
{"if the passed rule project id is empty spaces, returns 'invalid argument'", func(t *testing.T) {
{"if the passed rule project id is whitespace, returns 'invalid argument'", func(t *testing.T) {

Comment on lines -80 to -81
if len(actions) == 0 {
return errors.New("a role must contain at least one action")
Copy link
Contributor

Choose a reason for hiding this comment

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

I see this check is covered by the proto file so OK to remove it here. (Just wondering if we are happy with that error message vs. this one, thinking about our move away from proto-validation. 🤔 ).

Copy link
Author

Choose a reason for hiding this comment

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

🤔

if len(actions) == 0 {
return errors.New("a role must contain at least one action")
}
err := ValidateProjects(projects)
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this check covered elsewhere?

Copy link
Author

Choose a reason for hiding this comment

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

Yep-- back in the server

Copy link
Author

Choose a reason for hiding this comment

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

Oh the unassigned! Now it is :D

@blakestier blakestier force-pushed the automate-3198/reduce-validation branch from 4a8cc20 to b324067 Compare April 13, 2020 23:42
@blakestier blakestier force-pushed the automate-3198/reduce-validation branch 4 times, most recently from 7bc89f0 to 8d31cf9 Compare April 14, 2020 22:38
Signed-off-by: Blake Johnson <[email protected]>
@blakestier blakestier force-pushed the automate-3198/reduce-validation branch from 8d31cf9 to 9511906 Compare April 14, 2020 23:03
@bcmdarroch bcmdarroch force-pushed the automate-3198/reduce-validation branch from c5d745f to 50060ef Compare April 14, 2020 23:46
Signed-off-by: Brenna Hewer-Darroch <[email protected]>
@bcmdarroch bcmdarroch force-pushed the automate-3198/reduce-validation branch from 50060ef to e4dd2b9 Compare April 14, 2020 23:46
Copy link
Contributor

@srenatus srenatus left a comment

Choose a reason for hiding this comment

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

Nothing substantial, just some nitpicks... 😉

It could be a fun exercise to try to validate IDs from a custom middleware -- not PGV -- by peeking at the protobuf message. (Not trival, I think.)

@@ -151,10 +160,15 @@ func (s *ProjectState) CreateProject(ctx context.Context,

func (s *ProjectState) UpdateProject(ctx context.Context,
req *api.UpdateProjectReq) (*api.UpdateProjectResp, error) {

err := confirmRequiredIDandName(req.Id, req.Name, "project")
Copy link
Contributor

Choose a reason for hiding this comment

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

[nit] It looks weird, but the canonical casing here would be this:

Suggested change
err := confirmRequiredIDandName(req.Id, req.Name, "project")
err := confirmRequiredIDAndName(req.Id, req.Name, "project")

...but I'm down to turning a blind eye 🙈

Copy link
Author

Choose a reason for hiding this comment

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

this does seem like an opportunity conceding that the "right" way is not always the most readable, huh

Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah probably. Also naming is hard 😉

Blake Johnson and others added 2 commits April 15, 2020 08:01
@msorens
Copy link
Contributor

msorens commented Apr 15, 2020

FYI: Created issue #3371 to mirror this strategy change to teams and authn services.

Signed-off-by: Blake Johnson <[email protected]>
@blakestier blakestier force-pushed the automate-3198/reduce-validation branch 2 times, most recently from 751ac0f to cb80e5b Compare April 15, 2020 19:30
Signed-off-by: Blake Johnson <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
auth-team anything that needs to be on the auth team board automate-auth
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants