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

Various panics fixes #68

Merged
merged 12 commits into from
Jun 30, 2023
Merged

Various panics fixes #68

merged 12 commits into from
Jun 30, 2023

Conversation

zc-devs
Copy link
Contributor

@zc-devs zc-devs commented Jun 9, 2023

Closes #67 and #56.

  • refactored message parsing
  • introduced custom message, request and response
  • fixed both panics
  • fixed response body processing

spoe "github.com/criteo/haproxy-spoe-go"
)

type message struct {
Copy link
Member

Choose a reason for hiding this comment

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

I'd rather do something functions to get values from the map as string/int/ip.

func getString(args map[string]interface{}, key string) (string, error) {
   ...
}

Adding new struct to fetch values from a map looks overkill unless there are really important logic.

cc @anuraaga

app *application
tx types.Transaction
)

Copy link
Member

Choose a reason for hiding this comment

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

First please check if the RuleEngine is on/off, check https://github.com/corazawaf/coraza/blob/main/http/middleware.go#L132

@jcchavezs
Copy link
Member

Could you please add some unit tests to functions?

}

tx = app.waf.NewTransactionWithID(req.id)
if tx.IsRuleEngineOff() {
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 really need to execute all the previous code if ruleEngine is off?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We need application at least. Then we could get rule engine status from WAF, if it would be public interface. In public interface there are only transactions constructors. So, I think we need to execute all previous code.

}
}

return "", fmt.Errorf("invalid argument for %s, string expected, got %v", key, argVal)

Choose a reason for hiding this comment

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

IIUC, this error should be returned if not ok above, while here it is the not exists case, so not an error

Copy link
Contributor Author

Choose a reason for hiding this comment

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

How to signal caller that there is no such key in the map/message? Is below code OK?


func getString(args map[string]interface{}, key string) (string, bool, error) {
	argVal, exist := args[key]
	if !exist {
		return "", false, nil
	}
	if argVal == nil {
		return "", true, nil
	}
	val, ok := argVal.(string)
	if !ok {
		return "", true, fmt.Errorf("invalid argument for %s, string expected, got %v", key, argVal)
	}
	return val, true, nil
}

Copy link
Contributor Author

Choose a reason for hiding this comment

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

coraza-spoa requires method field in the message.

  1. message app=simple_app method= path... - variable value set up issue in HAProxy (probably haproxy.cfg;
  2. message app=simple_app path... - message definition issue in HAProxy SPOE config.

Choose a reason for hiding this comment

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

Returning a bool seems fine - from what it looks like some fields are required and some aren't so the caller needs to determine whether it's an error or not, not this utility. Or otherwise we would need two versions of each, getFoo and getFooRequired or similar, but maybe too much

Copy link
Member

@jcchavezs jcchavezs Jun 21, 2023

Choose a reason for hiding this comment

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

Still we might need to learn about the error on retrieval. How about

var errNotFound = errors.New("key not found")

func getString(args map[string]interface{}, key string) (string, error) {
	argVal, exist := args[key]
	if !exist {
		return "", errNotFound
	}
	if argVal == nil {
		return "", nil
	}
	val, ok := argVal.(string)
	if !ok {
		return "", fmt.Errorf("invalid argument for %s, string expected, got %v", key, argVal)
	}
	return val, nil
}

so that we can flag when the key isn't in the map and return a ErrNotFound to the upstream function letting them decide what happens if not found and finally another error in case the data isn't correct (hence programatic error).

Copy link
Contributor Author

@zc-devs zc-devs Jun 21, 2023

Choose a reason for hiding this comment

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

the caller needs to determine whether it's an error or not

Already does:

	req.method, err = getString(args, "method")
	if err != nil {
		return nil, err
	}
	req.path, err = getString(args, "path")
	if err != nil {
		fmt.Println(err.Error())
	}
	req.body, _ = getByteArray(args, "body")

@zc-devs zc-devs mentioned this pull request Jun 25, 2023
return nil, err
}

app, err = s.getApplication(req.app)
Copy link
Member

Choose a reason for hiding this comment

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

I would get the app from the spoeMsg and get the request right before we would use it.

Copy link
Contributor Author

@zc-devs zc-devs Jun 26, 2023

Choose a reason for hiding this comment

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

I don't get it. What problem do you try to solve?

From spoeMsg only application name can be obtained. Application != application name.

Also in request and respone application name is already converted to string and 'validated'.

Copy link
Member

Choose a reason for hiding this comment

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

What I am trying to avoid is parsing the entire message if the engine is off. If the engine is off we should cause minimum impact.

Copy link
Contributor Author

@zc-devs zc-devs Jun 26, 2023

Choose a reason for hiding this comment

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

Does c490c9f look OK?

@jcchavezs jcchavezs merged commit dd5eb86 into corazawaf:main Jun 30, 2023
@jcchavezs
Copy link
Member

Awesome work!

@zc-devs zc-devs deleted the 67-panic-on-empty-app-name branch July 12, 2023 08:40
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.

Panic on empty Application name
3 participants