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

Add proto validation for RuleType #4907

Merged
merged 8 commits into from
Nov 11, 2024
Merged

Add proto validation for RuleType #4907

merged 8 commits into from
Nov 11, 2024

Conversation

rdimitrov
Copy link
Member

Summary

Ref https://github.com/stacklok/minder-stories/issues/94

Change Type

Mark the type of change your PR introduces:

  • Bug fix (resolves an issue without affecting existing features)
  • Feature (adds new functionality without breaking changes)
  • Breaking change (may impact existing functionalities or require documentation updates)
  • Documentation (updates or additions to documentation)
  • Refactoring or test improvements (no bug fixes or new functionality)

Testing

Outline how the changes were tested, including steps to reproduce and any relevant configurations.
Attach screenshots if helpful.

Review Checklist:

  • Reviewed my own code for quality and clarity.
  • Added comments to complex or tricky code sections.
  • Updated any affected documentation.
  • Included tests that validate the fix or feature.
  • Checked that related changes are merged.

@rdimitrov rdimitrov requested a review from a team as a code owner November 7, 2024 17:00
@coveralls
Copy link

coveralls commented Nov 7, 2024

Coverage Status

coverage: 54.762% (+0.007%) from 54.755%
when pulling 9d2b131 on validate-ruletype
into 2683161 on main.

@rdimitrov rdimitrov self-assigned this Nov 7, 2024
Copy link
Member

@evankanderson evankanderson left a comment

Choose a reason for hiding this comment

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

I only got partway through, this is a big one.

string body = 2;
string body = 2 [
(buf.validate.field).string = {
pattern: "^\\s*\\{.*\\}\\s*$",
Copy link
Member

Choose a reason for hiding this comment

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

I'm not sure what this is trying to match. This may be a case where we can't qualify the contents or need to use CEL to do so.

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes, it's supposed to be JSON there. so I added the following ^\\s*\\{[\\s\\S]*\\}\\s*$ which should check for opening/closing bracket and match any character including new lines

max_len: 1000,
},
(buf.validate.field).ignore = IGNORE_IF_DEFAULT_VALUE
];
}

// endpoint is the endpoint to fetch data from.
// This can be a URL or the path on the API.bool
Copy link
Member

Choose a reason for hiding this comment

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

I wonder what .bool means here.

Copy link
Member Author

Choose a reason for hiding this comment

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

I think it's perhaps pool or a typo?

Copy link
Member

Choose a reason for hiding this comment

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

I suspect it's a typo. Want to fix it?

string endpoint = 1;
string endpoint = 1 [
(buf.validate.field).string = {
pattern: "^(https:\\/\\/[a-zA-Z0-9.-]+)?(\\/[a-zA-Z0-9._-]+)*(\\/\\{\\{[^}]+\\}\\})*(\\/)?$",
Copy link
Member

Choose a reason for hiding this comment

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

Is this a "URI with Go template values embedded"? Again, CEL might be an option, or combining prefix with some other expressions.

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes, I updated it to "^(https?:\\/\\/)?[a-zA-Z0-9._-]+(\\/[a-zA-Z0-9._{}\\/-]*)?$" which should allow for:

string method = 2;
string method = 2 [
(buf.validate.field).string = {
pattern: "^(GET|POST|PUT|PATCH|DELETE)$",
Copy link
Member

Choose a reason for hiding this comment

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

Prefer in

Is capitalization important?

Copy link
Member Author

Choose a reason for hiding this comment

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

Thanks, made it case insensitive 👍

Copy link
Member Author

Choose a reason for hiding this comment

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

in doesn't work though as I couldn't find an option to ignore casing in parallel 👍 The other way was to expand the list with upper and lower case values which seems odd

(buf.validate.field).repeated = {
items: {
string: {
pattern: "^[a-zA-Z0-9-]+: .+$",
Copy link
Member

Choose a reason for hiding this comment

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

You probably want to limit the RHS to avoid \n, among others.

Copy link
Member Author

Choose a reason for hiding this comment

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

Adressed 👍

string branch = 2;
string branch = 2 [
(buf.validate.field).string = {
pattern: "^[a-zA-Z0-9._/-]+$",
Copy link
Member

Choose a reason for hiding this comment

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

^[[:word:]./-]+$?

string version = 11;
string version = 11 [
(buf.validate.field).string = {
pattern: "^v\\d+(\\.\\d+)?(\\.\\d+)?(?:-[\\w\\.-]+)?$",
Copy link
Member

Choose a reason for hiding this comment

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

Again, I'd prefer just v1 than v1.1.7 here for now.

Copy link
Member Author

Choose a reason for hiding this comment

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

Fixed 👍

string short_failure_message = 10;
string short_failure_message = 10 [
(buf.validate.field).string = {
pattern: "[A-Za-z][-/.!?,:;[:word:] *#\\[\\]()`{}]*",
Copy link
Member

Choose a reason for hiding this comment

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

Is this markdown, or plain-text?

Copy link
Member Author

Choose a reason for hiding this comment

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

It should be markdown

Copy link
Member

Choose a reason for hiding this comment

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

This may be a case where we want to simply say "this field is markdown", and then do validation in the code, rather than via annotation.

Copy link
Member Author

Choose a reason for hiding this comment

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

Removed the pattern check but left the length one 👍

string type = 1;
string type = 1 [
(buf.validate.field).string = {
pattern: "^[a-z]+(_[a-z]+)*$",
Copy link
Member

Choose a reason for hiding this comment

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

Should this use in, or are there more types?

Copy link
Member Author

Choose a reason for hiding this comment

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

I think there are, i.e. recently we added yq I believe

Copy link
Member

Choose a reason for hiding this comment

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

If this is still a small enum, I'd use those values, as it also provides documentation.

Copy link
Member Author

Choose a reason for hiding this comment

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

Refactored it to using in 👍

string def = 1;
string def = 1 [
(buf.validate.field).string = {
pattern: "^\\.[a-z_]+(\\.[a-z_]+)*$",
Copy link
Member

Choose a reason for hiding this comment

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

Hey, this would have fixed my bad ruletype debugging experience! Thank you!

Copy link
Member

Choose a reason for hiding this comment

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

Do we need to accommodate " or array access ([])?

Copy link
Member Author

Choose a reason for hiding this comment

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

Fixed 👍

@rdimitrov rdimitrov force-pushed the validate-ruletype branch 4 times, most recently from 50b8d78 to 6892cd7 Compare November 8, 2024 16:26
Copy link
Member

@evankanderson evankanderson left a comment

Choose a reason for hiding this comment

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

Okay, I got through the rest of this one.

At some point, we should look at creating predefined constraints for a lot of our use cases. For example:

  • rule_type_name, markdown_with_go_templates, profile_name, file_name etc.

I wouldn't do that here at this point, because it looks like it might be a lot of toolchaining, but we should leave a note somewhere for when someone is looking for a mid-sized cleanup project.

string depfile = 2;
string depfile = 2 [
(buf.validate.field).string = {
pattern: "^(\\./)?([a-zA-Z0-9_]+\\/)*[a-zA-Z0-9_]+(\\.[a-zA-Z0-9]+)?$",
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
pattern: "^(\\./)?([a-zA-Z0-9_]+\\/)*[a-zA-Z0-9_]+(\\.[a-zA-Z0-9]+)?$",
pattern: "^(\\./)?([[:word:]]+\\/)*[[:word:]]+(\\.[[:alnum:]]+)?$",

Though, it seems like we should allow for . to show up in other file parts, so maybe:

Suggested change
pattern: "^(\\./)?([a-zA-Z0-9_]+\\/)*[a-zA-Z0-9_]+(\\.[a-zA-Z0-9]+)?$",
pattern: "^([[:word:].]+\\/)*[[:word:].]+$",

string short_failure_message = 10;
string short_failure_message = 10 [
(buf.validate.field).string = {
pattern: "[A-Za-z][-/.!?,:;[:word:] *#\\[\\]()`{}]*",
Copy link
Member

Choose a reason for hiding this comment

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

This may be a case where we want to simply say "this field is markdown", and then do validation in the code, rather than via annotation.

string type = 1;
string type = 1 [
(buf.validate.field).string = {
pattern: "^[a-z]+(_[a-z]+)*$",
Copy link
Member

Choose a reason for hiding this comment

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

If this is still a small enum, I'd use those values, as it also provides documentation.

string def = 1;
string def = 1 [
(buf.validate.field).string = {
pattern: "^\\.[a-z_]+(\\.[a-z_]+|\\[\\d+]|\\[\"[a-z_]+\"\\])*$",
Copy link
Member

Choose a reason for hiding this comment

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

Do we allow uppercase letters here? I know that GitHub prefers lower_with_underscores, but I think these could also be camelCase.

Copy link
Member Author

Choose a reason for hiding this comment

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

Updated it to allow for camelCase 👍

string type = 1;
string type = 1 [
(buf.validate.field).string = {
pattern: "^[a-z]+(_[a-z]+)*$",
Copy link
Member

Choose a reason for hiding this comment

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

Can we use:

Suggested change
pattern: "^[a-z]+(_[a-z]+)*$",
in: ["deny-by-default", "constraints"]

pattern: "^minder(?:\\.[a-zA-Z0-9_]+)*$",
max_len: 200,
}
];
// params are unstructured parameters passed to the method. These are optional
// and evaluated by the method.
google.protobuf.Struct params = 6;
Copy link
Member

Choose a reason for hiding this comment

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

Hmm, this is tricky, because it's arbitrary content, but in a structured format that may be interpreted by the rest of our rules.

I don't think we can do much here now, but we'll get a fun bug at some point later.

Copy link
Member Author

Choose a reason for hiding this comment

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

yes 👍 I wonder if we should cover this by having custom validation functions or by updating our API to expect a better defined field for this

string type = 1;
string type = 1 [
(buf.validate.field).string = {
pattern: "^[a-z]+(_[a-z]+)*$",
Copy link
Member

Choose a reason for hiding this comment

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

Maybe:

Suggested change
pattern: "^[a-z]+(_[a-z]+)*$",
in: ["security_advisory"]

Copy link
Member Author

Choose a reason for hiding this comment

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

Applied 👍

string severity = 1;
string severity = 1 [
(buf.validate.field).string = {
pattern: "^[a-z]+(_[a-z]+)*$",
Copy link
Member

Choose a reason for hiding this comment

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

This is a Severity enum as a string:

Suggested change
pattern: "^[a-z]+(_[a-z]+)*$",
in: ["unknown", "info", "low", "medium", "high", "critical"]

Copy link
Member Author

Choose a reason for hiding this comment

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

Applied 👍

string description = 5;
string description = 5 [
(buf.validate.field).string = {
pattern: "[A-Za-z][-/.!?,:;[:word:] *#\\[\\]()`{}]*",
Copy link
Member

Choose a reason for hiding this comment

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

Again, this is markdown, so we can do this for now, but we may need to parse in Go code.

Copy link
Member Author

Choose a reason for hiding this comment

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

Removed the pattern validation 👍

string guidance = 6;
string guidance = 6 [
(buf.validate.field).string = {
pattern: "[A-Za-z][-/.!?,:;[:word:] *#\\[\\]()`{}]*",
Copy link
Member

Choose a reason for hiding this comment

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

Again, I think this is markdown. We should add to the comment in all the markdown cases, saying:

This value should be rendered as markdown.

Copy link
Member Author

Choose a reason for hiding this comment

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

Removed the pattern validation 👍

@rdimitrov rdimitrov force-pushed the validate-ruletype branch 2 times, most recently from a25d1d5 to ab5a7f1 Compare November 11, 2024 12:21
Copy link
Member

@evankanderson evankanderson left a comment

Choose a reason for hiding this comment

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

Just a few more comments, but I'm not sure they are blocking, you could probably revisit them in a future PR.

max_len: 1000,
},
(buf.validate.field).ignore = IGNORE_IF_DEFAULT_VALUE
];
}

// endpoint is the endpoint to fetch data from.
// This can be a URL or the path on the API.bool
Copy link
Member

Choose a reason for hiding this comment

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

I suspect it's a typo. Want to fix it?

string body = 2;
string body = 2 [
(buf.validate.field).string = {
pattern: "^\\s*\\{[\\s\\S]*\\}\\s*$",
Copy link
Member

Choose a reason for hiding this comment

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

Is this trying to say "valid JSON"? This pattern doesn't seem meaningful.

(buf.validate.field).repeated = {
items: {
string: {
pattern: "^[a-zA-Z0-9-]+: [^\n\r]+$",
Copy link
Member

Choose a reason for hiding this comment

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

I'm going to let this pass for now, but we should prefer a positive expression. From https://www.rfc-editor.org/rfc/rfc7230#section-3.2 :

Suggested change
pattern: "^[a-zA-Z0-9-]+: [^\n\r]+$",
pattern: "^[a-zA-Z0-9-]+:[[:graph:][:blank:]]+$",

optional string body = 4;
optional string body = 4 [
(buf.validate.field).string = {
pattern: "^\\s*\\{[\\s\\S]*\\}\\s*$",
Copy link
Member

Choose a reason for hiding this comment

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

Again, I think this is "is JSON", which I'd just leave as a comment here.

string depfile = 2;
string depfile = 2 [
(buf.validate.field).string = {
pattern: "^(\\./)?([a-zA-Z0-9_\\-]+/)*[a-zA-Z0-9_\\-]+(\\.[a-zA-Z0-9]+)?$",
Copy link
Member

Choose a reason for hiding this comment

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

We don't want to allow . in the filename for the depfile path or multiple dots in the requirements file? (The python "standard" for development dependencies is requirements-dep.txt, but given how loose that standard is, I could see requirements.dep.txt slipping in.)

Copy link
Member Author

Choose a reason for hiding this comment

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

yeah, I wasn't sure about this too, but I'm okay to leave it for now because of the reasons you mentioned 👍

}

// the title of the PR
string title = 1;
string title = 1 [
(buf.validate.field).string = {
Copy link
Member

Choose a reason for hiding this comment

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

No pattern here? That could be okay, given that GitHub will validate this, but you should put a comment as to why no pattern.

string description = 5;
string description = 5 [
(buf.validate.field).string = {
min_len: 1,
Copy link
Member

Choose a reason for hiding this comment

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

Again, add a comment that this is markdown?


// guidance are instructions we give the user in case a rule fails.
string guidance = 6;
string guidance = 6 [
(buf.validate.field).string = {
Copy link
Member

Choose a reason for hiding this comment

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

Ditto on the markdown comment.

@rdimitrov rdimitrov merged commit 5971728 into main Nov 11, 2024
26 checks passed
@rdimitrov rdimitrov deleted the validate-ruletype branch November 11, 2024 16:52
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.

3 participants