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 an validator to verify correctness of ProxyUrl string/secret #706

Merged
merged 3 commits into from
Apr 14, 2022

Conversation

aorcholski
Copy link
Contributor

Description
ActiveGate Proxy URL has to be properly encoded URI. ActiveGate POD fails if Proxy URL contains special characters (for instance "?) unencoded. To improve user experience I propose to add an Validator to reject a CR if the Proxy value or Proxy secret is invalid.

How can this be tested?
Use any unencoded special character(s) in the Proxy Url (proxy.value, proxy secret) and try to apply your CR - should be rejected.

Checklist

  • Unit tests have been updated/added
  • PR is labeled accordingly

@aorcholski aorcholski added bug Something isn't working activegate Changes related to Activegate labels Apr 7, 2022
@aorcholski aorcholski force-pushed the bugfix/ag-proxyurl-parse-error branch 3 times, most recently from ce71ddc to fd75261 Compare April 8, 2022 14:50
@aorcholski aorcholski marked this pull request as ready for review April 11, 2022 06:49
@aorcholski aorcholski requested a review from a team as a code owner April 11, 2022 06:49
@@ -129,7 +129,7 @@ func (agProxySecretGenerator *ActiveGateProxySecretGenerator) proxyUrlFromUserSe
func parseProxyUrl(proxy string) (host string, port string, username string, password string, err error) {
proxyUrl, err := url.Parse(proxy)
if err != nil {
return "", "", "", "", err
return "", "", "", "", fmt.Errorf("could not parse proxy URL")
Copy link
Contributor

Choose a reason for hiding this comment

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

use errors.New() from the pkg/errors library

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

if k8serrors.IsNotFound(err) {
return errorMissingActiveGateProxySecret
} else if err != nil {
return fmt.Sprintf("error occurred while reading PROXY secret indicated in the Dynakube specification (%s)", err.Error())
Copy link
Contributor

Choose a reason for hiding this comment

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

use errors.Wrap() from the pkg/errors libraries

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

Comment on lines 110 to 112
// proxyUrl is valid if
// 1) encoded
// 2) "`\ are escaped using \
Copy link
Contributor

Choose a reason for hiding this comment

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

does that mean it must be either escaped or encoded or must it be both?
If it must be both, would that then work with the dtclient, since it would take the password unencoded?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

my fault, characters can not be escaped

// 'eval' command is used by entrypoint.sh:readSecret function to return its result.
// For this reason quotation mark ", backtick ` and backslash \ characters have to be escaped using backslash.
func isEvalEscapeNeeded(str string) bool {
previousChar := '\000'
Copy link
Contributor

Choose a reason for hiding this comment

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

introduce a local constant for the null character just so it is more obvious that that magic number is supposed to be that character

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Characters can not be escaped due to dtclient (which uses the same password) so the logic is simpler - apostrophe and backtick are forbidden. The function has been renamed to evalIsStringInvalid


// 'eval' command is used by entrypoint.sh:readSecret function to return its result.
// For this reason quotation mark ", backtick ` and backslash \ characters have to be escaped using backslash.
func isEvalEscapeNeeded(str string) bool {
Copy link
Contributor

Choose a reason for hiding this comment

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

as far as I understand, this function would effectively be a block-list, blocking the three known characters. It would be more secure to restructure it to an allow-list, checking that every character is one of the known ones, i.e., letters, numbers and tested special characters and then checking if they are appropriately escaped

Copy link
Contributor Author

Choose a reason for hiding this comment

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

my fault, characters can not be escaped because of dtclient. Finally, there are two invalid characters : apostrophe and backtick.

Comment on lines 28 to 36
errorInvalidActiveGateProxyUrl = `The DynaKube's specification has an invalid Proxy URL value set. Make sure you correctly specify the URL in your custom resource.`
errorInvalidEvalCharacter = `The DynaKube's specification has an invalid Proxy password value set. Make sure you correctly escape quotation mark, backtick and backslash characters using backslash.`

errorMissingActiveGateProxySecret = `The Proxy secret indicated by the DynaKube specification doesn't exist.`

errorInvalidProxySecretFormat = `The Proxy secret indicated by the DynaKube specification has an invalid format. Make sure you correctly creates the secret.`

errorInvalidProxySecretUrl = `The Proxy secret indicated by the DynaKube specification has an invalid URL value set. Make sure you correctly specify the URL in the secret.`
errorInvalidProxySecretEvalCharacter = `The Proxy secret indicated by the DynaKube specification has an invalid Proxy password value set. Make sure you correctly escape quotation mark, backtick and backslash characters using backslash.`
Copy link
Contributor

Choose a reason for hiding this comment

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

With so many specifc errors (and also logic), this code and other proxy validation code should probably belong into a separate file, e.g., "validation/proxy.go"

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

@aorcholski aorcholski force-pushed the bugfix/ag-proxyurl-parse-error branch 3 times, most recently from 6361b3a to dff074c Compare April 12, 2022 10:51
@aorcholski aorcholski requested a review from meik99 April 12, 2022 11:20
// Finally, these 2 characters are forbidden.
func evalIsStringInvalid(str string) bool {
for _, char := range str {
if char == '\'' || char == '`' {
Copy link
Contributor

Choose a reason for hiding this comment

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

This implements a blocklist again, please rewrite that function to return true anytime it encounters an unkown character

Copy link
Contributor

Choose a reason for hiding this comment

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

Something like this would implement an allowlist, only permitting the characters in the brackets to be used

func isStringValidForEval(str string) bool {
	regex := regexp.MustCompile(`^[a-zA-Z0-9./?,*;\\ ]+$`)
	return regex.MatchString(str)
}

func TestAllowList(t *testing.T) {
	assert.True(t, isStringValidForEval("a simple password"))
	assert.True(t, isStringValidForEval("a simple password w1th sp?cial ;; chara/cters"))
	assert.False(t, isStringValidForEval("A ` backtick"))
	assert.False(t, isStringValidForEval("A ' single quote"))
}

Copy link
Contributor Author

Choose a reason for hiding this comment

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

regex is used

(including user:password) so has to be replaced by less verbose message
@aorcholski aorcholski force-pushed the bugfix/ag-proxyurl-parse-error branch 6 times, most recently from c0aa044 to 96a2524 Compare April 13, 2022 14:26
@aorcholski aorcholski force-pushed the bugfix/ag-proxyurl-parse-error branch from 96a2524 to b6944fa Compare April 14, 2022 07:24
@aorcholski aorcholski requested a review from meik99 April 14, 2022 08:28
Comment on lines 139 to 140
assert.Equal(t, true, isStringValidForAG("password"))
assert.Equal(t, true, isStringValidForAG("test~!@#^*()_-|}{[]\":;?><./pass"))
Copy link
Contributor

Choose a reason for hiding this comment

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

sorry I didn't see that during the first review. There is assert.True and assert.False for these kinds of assertions. Otherweise lgmt

Copy link
Contributor Author

Choose a reason for hiding this comment

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

good point, fixed

@aorcholski aorcholski requested a review from meik99 April 14, 2022 08:55
@aorcholski aorcholski force-pushed the bugfix/ag-proxyurl-parse-error branch 2 times, most recently from 9413cd5 to 38b90fe Compare April 14, 2022 10:00
meik99
meik99 previously approved these changes Apr 14, 2022
@aorcholski aorcholski force-pushed the bugfix/ag-proxyurl-parse-error branch from 38b90fe to 532208b Compare April 14, 2022 10:51
@aorcholski aorcholski merged commit cc8b7b1 into master Apr 14, 2022
@aorcholski aorcholski deleted the bugfix/ag-proxyurl-parse-error branch April 14, 2022 11:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
activegate Changes related to Activegate bug Something isn't working
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants