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

regexp.replace Fails with Curly Brackets in Teleport Role Interpolation #41725

Open
programmerq opened this issue May 17, 2024 · 2 comments
Open
Labels
bug rbac Issues related to Role Based Access Control

Comments

@programmerq
Copy link
Contributor

programmerq commented May 17, 2024

Expected behavior:

The regexp.replace function should correctly handle regular expressions that include curly brackets {} for specifying matches, such as regexp.replace(external.some_external_list, "^str_to_match:(.{0,28}).*$", "usr-$1"). This should truncate the matching string to 28 characters.

Current behavior:

The regexp.replace function fails to process regular expressions with curly brackets {} within role interpolation logic. The template parsing layer treats it as an invalid match.

Bug details:

  • Teleport version: observed on 15.3.5
  • Recreation steps:
    1. Define a role with regexp.replace using a regex that includes curly brackets, e.g.:
      kind: role
      metadata:
        name: example_role
      spec:
        allow:
          db_users:
          - '{{regexp.replace(external.some_external_list, "^str_to_match:(.{0,28}).*$","user-$1")}}'
    2. Define a user with appropriate traits:
      kind: user
      spec:
        roles:
        - example_role
        traits:
          some_external_list:
          - str_to_match:database-user
          - str_to_match:verylongdatabaseuserthatneedstobetruncated
    3. Inspect the user's generated db_users on the Teleport user's certificate. Any regex that includes a curly bracket produces no output. No user-facing errors surface.

Additional info

While testing, I added this Test case added to TestVariable in parse_test.go:

{
  title: "regexp replace with curly brackets",
  in:    `{{regexp.replace(internal.foo, "^f.{0,3}.*$", "$1")}}`,
  out:   "oov",
}

Running the test produces:

GOROOT=/usr/local/opt/go/libexec #gosetup
GOPATH=/Users/jeff/go #gosetup
/usr/local/opt/go/libexec/bin/go test -c -o /Users/jeff/Library/Caches/JetBrains/GoLand2024.1/tmp/GoLand/___TestVariable_regexp_replace_with_curly_brackets_in_github_com_gravitational_teleport_lib_utils_parse.test github.com/gravitational/teleport/lib/utils/parse #gosetup
/usr/local/opt/go/libexec/bin/go tool test2json -t /Users/jeff/Library/Caches/JetBrains/GoLand2024.1/tmp/GoLand/___TestVariable_regexp_replace_with_curly_brackets_in_github_com_gravitational_teleport_lib_utils_parse.test -test.v -test.paniconexit0 -test.run ^\QTestVariable\E$/^\Qregexp_replace_with_curly_brackets\E$
=== RUN   TestVariable
=== PAUSE TestVariable
=== CONT  TestVariable
=== RUN   TestVariable/regexp_replace_with_curly_brackets
    parse_test.go:202: 
        	Error Trace:	/Users/jeff/workspace/teleport/lib/utils/parse/parse_test.go:202
        	Error:      	Received unexpected error:
        	            	"{{regexp.replace(internal.foo, \"^f.{0,3}.*$\", \"$1\")}}" is using template brackets '{{' or '}}', however expression does not parse, make sure the format is {{expression}}
        	Test:       	TestVariable/regexp_replace_with_curly_brackets
        	Messages:   	
        	            	ERROR REPORT:
        	            	Original Error: *trace.BadParameterError "{{regexp.replace(internal.foo, \"^f.{0,3}.*$\", \"$1\")}}" is using template brackets '{{' or '}}', however expression does not parse, make sure the format is {{expression}}
        	            	Stack Trace:
        	            		/Users/jeff/workspace/teleport/lib/utils/parse/parse.go:82 github.com/gravitational/teleport/lib/utils/parse.NewTraitsTemplateExpression
        	            		/Users/jeff/workspace/teleport/lib/utils/parse/parse_test.go:197 github.com/gravitational/teleport/lib/utils/parse.TestVariable.func1
        	            		/usr/local/opt/go/libexec/src/testing/testing.go:1689 testing.tRunner
        	            		/usr/local/opt/go/libexec/src/runtime/asm_amd64.s:1695 runtime.goexit
        	            	User Message: "{{regexp.replace(internal.foo, \"^f.{0,3}.*$\", \"$1\")}}" is using template brackets '{{' or '}}', however expression does not parse, make sure the format is {{expression}}
--- FAIL: TestVariable (0.00s)
    --- FAIL: TestVariable/regexp_replace_with_curly_brackets (0.00s)


FAIL

Process finished with the exit code 1

It looks like this is the regex that fails the match:

https://github.com/gravitational/teleport/blob/v15.3.1/lib/utils/parse/parse.go#L54-L61

reVariable = regexp.MustCompile(
// prefix is anything that is not { or }
`^(?P<prefix>[^}{]*)` +
// variable is anything in brackets {{}} that is not { or }
`{{(?P<expression>\s*[^}{]*\s*)}}` +
// suffix is anything that is not { or }
`(?P<suffix>[^}{]*)$`,
)

@programmerq programmerq added bug rbac Issues related to Role Based Access Control labels May 17, 2024
@webvictim
Copy link
Contributor

webvictim commented May 17, 2024

I think I had this issue once and had to escape the braces:

\{0,28\}

Edit: nope, this doesn't work either.

2024-05-17T18:25:18Z WARN Detected invalid role "test-regex-brace-role": parsing allow.db_users expression: "{{regexp.replace(external.some_external_list, \"^str_to_match:(.\\{0,28\\}).*$\",\"user-$1\")}}" is using template brackets '{{' or '}}', however expression does not parse, make sure the format is {{expression}} services/role.go:265

@programmerq
Copy link
Contributor Author

programmerq commented May 17, 2024 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug rbac Issues related to Role Based Access Control
Projects
None yet
Development

No branches or pull requests

2 participants