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

fix(#19314): allow ssh/altssh subdomains in repo URLs to match webhook payload #19315

Closed
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
801aae4
allow ssh/altssh subdomains in repo URLs to match webhook payload
mtbennett-godaddy Jul 30, 2024
3f8958f
Merge branch 'master' of github.com:argoproj/argo-cd into allow-alt-s…
mtbennett-godaddy Aug 1, 2024
c79b60d
test nit
mtbennett-godaddy Aug 1, 2024
858d6df
Merge branch 'master' of github.com:argoproj/argo-cd into allow-alt-s…
mtbennett-godaddy Aug 2, 2024
7746506
Merge branch 'master' of github.com:argoproj/argo-cd into allow-alt-s…
mtbennett-godaddy Aug 5, 2024
cf8ce08
Merge branch 'master' of github.com:argoproj/argo-cd into allow-alt-s…
mtbennett-godaddy Aug 6, 2024
1948699
Merge branch 'master' of github.com:argoproj/argo-cd into allow-alt-s…
mtbennett-godaddy Aug 8, 2024
7c6a3ab
Merge branch 'master' of github.com:argoproj/argo-cd into allow-alt-s…
mtbennett-godaddy Aug 9, 2024
eb25202
wip
mtbennett-godaddy Aug 12, 2024
c4665d3
Merge branch 'master' of github.com:argoproj/argo-cd into allow-alt-s…
mtbennett-godaddy Aug 12, 2024
a58f88a
unify return types and allow for nil webhook
mtbennett-godaddy Aug 13, 2024
dba501e
lint fixes
mtbennett-godaddy Aug 13, 2024
40a16ce
missing import
mtbennett-godaddy Aug 13, 2024
5857b05
resolve with base and push argoCdSettings init down
mtbennett-godaddy Aug 13, 2024
e3c9acb
Merge branch 'master' of github.com:argoproj/argo-cd into allow-alt-s…
mtbennett-godaddy Aug 13, 2024
f4e0773
use numbered inputs so caller can provide regex format
mtbennett-godaddy Aug 13, 2024
30cc282
resolve with base
mtbennett-godaddy Aug 13, 2024
f9da773
resolve with base
mtbennett-godaddy Aug 13, 2024
27d62e2
resolve with base
mtbennett-godaddy Aug 13, 2024
7ba2875
tweak URL regular expressions
mtbennett-godaddy Aug 14, 2024
d04bb80
resolve with base
mtbennett-godaddy Aug 14, 2024
0937a9a
resolve with base
mtbennett-godaddy Aug 14, 2024
b433ec0
resolve with base
mtbennett-godaddy Aug 15, 2024
3917438
resolve with base
mtbennett-godaddy Aug 15, 2024
717ecac
resolve with base
mtbennett-godaddy Aug 15, 2024
259ff98
resolve with base
mtbennett-godaddy Aug 16, 2024
0f36a7d
resolve with base
mtbennett-godaddy Aug 19, 2024
fb09082
resolve with base
mtbennett-godaddy Aug 19, 2024
7369ba2
resolve with base
mtbennett-godaddy Aug 20, 2024
10909de
resolve with base
mtbennett-godaddy Aug 22, 2024
3bd6d61
resolve with base
mtbennett-godaddy Aug 22, 2024
0520145
resolve with base
mtbennett-godaddy Aug 22, 2024
d70f91f
resolve with base
mtbennett-godaddy Aug 23, 2024
601d857
resolve with base
mtbennett-godaddy Aug 23, 2024
08e0a5f
resolve with base
mtbennett-godaddy Aug 26, 2024
6208575
resolve with base
mtbennett-godaddy Aug 27, 2024
1fc1257
resolve with base
mtbennett-godaddy Aug 28, 2024
ddade23
resolve with base
mtbennett-godaddy Aug 30, 2024
ac206d3
resolve with base
mtbennett-godaddy Sep 3, 2024
735fbc3
resolve with base
mtbennett-godaddy Sep 3, 2024
f359d34
resolve with base
mtbennett-godaddy Sep 4, 2024
12e827f
resolve with base
mtbennett-godaddy Sep 5, 2024
27ef474
fix test data file indentation
mtbennett-godaddy Sep 5, 2024
046b24e
resolve with base
mtbennett-godaddy Sep 5, 2024
ae3e907
resolve with base
mtbennett-godaddy Sep 5, 2024
e9cee07
resolve with base
mtbennett-godaddy Sep 6, 2024
68309fc
resolve with base
mtbennett-godaddy Sep 9, 2024
6b55fe3
resolve with base
mtbennett-godaddy Sep 11, 2024
207dccf
resolve with base
mtbennett-godaddy Sep 12, 2024
ac143ad
resolve with base
mtbennett-godaddy Sep 20, 2024
d8438f0
resolve with base
mtbennett-godaddy Sep 23, 2024
c3396ab
resolve with base
mtbennett-godaddy Sep 24, 2024
cedbd1e
resolve with base
mtbennett-godaddy Oct 3, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 12 additions & 12 deletions applicationset/webhook/testdata/gitlab-event.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,26 +16,26 @@
"id": 1,
"name": "project",
"description": "",
"web_url": "https://gitlab/group/name",
"web_url": "https://gitlab.com/group/name",
crenshaw-dev marked this conversation as resolved.
Show resolved Hide resolved
"avatar_url": null,
"git_ssh_url": "ssh://git@gitlab:2222/group/name.git",
"git_http_url": "https://gitlab/group/name.git",
"git_ssh_url": "ssh://git@gitlab.com:2222/group/name.git",
"git_http_url": "https://gitlab.com/group/name.git",
"namespace": "group",
"visibility_level": 1,
"path_with_namespace": "group/name",
"default_branch": "master",
"ci_config_path": null,
"homepage": "https://gitlab/group/name",
"url": "ssh://git@gitlab:2222/group/name.git",
"ssh_url": "ssh://git@gitlab:2222/group/name.git",
"http_url": "https://gitlab/group/name.git"
"homepage": "https://gitlab.com/group/name",
"url": "ssh://git@gitlab.com:2222/group/name.git",
"ssh_url": "ssh://git@gitlab.com:2222/group/name.git",
"http_url": "https://gitlab.com/group/name.git"
},
"commits": [
{
"id": "bb0748feaa336d841c251017e4e374c22d0c8a98",
"message": "Test commit message\n",
"timestamp": "2020-01-06T03:47:55Z",
"url": "https://gitlab/group/name/commit/bb0748feaa336d841c251017e4e374c22d0c8a98",
"url": "https://gitlab.com/group/name/commit/bb0748feaa336d841c251017e4e374c22d0c8a98",
"author": {
"name": "User",
"email": "[email protected]"
Expand All @@ -55,11 +55,11 @@
},
"repository": {
"name": "name",
"url": "ssh://git@gitlab:2222/group/name.git",
"url": "ssh://git@gitlab.com:2222/group/name.git",
"description": "",
"homepage": "https://gitlab/group/name",
"git_http_url": "https://gitlab/group/name.git",
"git_ssh_url": "ssh://git@gitlab:2222/group/name.git",
"homepage": "https://gitlab.com/group/name",
"git_http_url": "https://gitlab.com/group/name.git",
"git_ssh_url": "ssh://git@gitlab.com:2222/group/name.git",
"visibility_level": 10
}
}
13 changes: 11 additions & 2 deletions applicationset/webhook/webhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ import (
log "github.com/sirupsen/logrus"
)

// https://www.rfc-editor.org/rfc/rfc3986#section-3.2.1
// https://github.com/shadow-maint/shadow/blob/master/libmisc/chkname.c#L36
const usernameRegex = `[a-zA-Z0-9_\.][a-zA-Z0-9_\.-]{0,30}[a-zA-Z0-9_\.\$-]?`
Copy link
Author

Choose a reason for hiding this comment

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

Copy link
Member

Choose a reason for hiding this comment

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

Should we instead move this to a common util package?

Copy link
Author

Choose a reason for hiding this comment

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

I had the same thought but wasn’t sure if I should dig in that much. (Wasn’t sure if the 2 webhooks were being allowed to diverge intentionally for some reason.) There’s another new feature in the Application webhook (maxPayloadSizeMB) that isn’t here either that I wanted to pull in.

I’ll see what I can do about reusing as much as possible between the 2 webhooks.

Copy link
Member

Choose a reason for hiding this comment

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

I have a similar PR open where the thing with the util package is already done (#16292). Maybe this can be used as an inspiration to these two PRs can be combined somehow.


const payloadQueueSize = 50000

var errBasicAuthVerificationFailed = errors.New("basic auth verification failed")
Expand Down Expand Up @@ -246,7 +250,10 @@ func getGitGeneratorInfo(payload interface{}) *gitGeneratorInfo {
log.Errorf("Failed to parse repoURL '%s'", webURL)
return nil
}
regexpStr := `(?i)(http://|https://|\w+@|ssh://(\w+@)?)` + urlObj.Hostname() + "(:[0-9]+|)[:/]" + urlObj.Path[1:] + "(\\.git)?"
regexEscapedHostname := regexp.QuoteMeta(urlObj.Hostname())
regexEscapedPath := regexp.QuoteMeta(urlObj.EscapedPath()[1:])
regexpStr := fmt.Sprintf(`(?i)^(http://|https://|%s@|ssh://(%s@)?((alt)?ssh\.)?)%s(:[0-9]+|)[:/]%s(\.git)?$`,
usernameRegex, usernameRegex, regexEscapedHostname, regexEscapedPath)
Copy link
Author

Choose a reason for hiding this comment

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

Copy link
Member

Choose a reason for hiding this comment

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

Ditto with this, if it's identical to the appset webhook handling logic, can we just move it to a shared location?

repoRegexp, err := regexp.Compile(regexpStr)
if err != nil {
log.Errorf("Failed to compile regexp for repoURL '%s'", webURL)
Expand Down Expand Up @@ -274,7 +281,9 @@ func getPRGeneratorInfo(payload interface{}) *prGeneratorInfo {
log.Errorf("Failed to parse repoURL '%s'", apiURL)
return nil
}
regexpStr := `(?i)(http://|https://|\w+@|ssh://(\w+@)?)` + urlObj.Hostname() + "(:[0-9]+|)[:/]"
regexEscapedHostname := regexp.QuoteMeta(urlObj.Hostname())
regexpStr := fmt.Sprintf(`(?i)^(http://|https://|%s@|ssh://(%s@)?)%s(:[0-9]+|)[:/]$`,
usernameRegex, usernameRegex, regexEscapedHostname)
apiRegexp, err := regexp.Compile(regexpStr)
if err != nil {
log.Errorf("Failed to compile regexp for repoURL '%s'", apiURL)
Expand Down
18 changes: 11 additions & 7 deletions applicationset/webhook/webhook_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ func TestWebhookHandler(t *testing.T) {
headerKey: "X-GitHub-Event",
headerValue: "push",
payloadFile: "github-commit-event.json",
effectedAppSets: []string{"git-github", "matrix-git-github", "merge-git-github", "matrix-scm-git-github", "matrix-nested-git-github", "merge-nested-git-github", "plugin", "matrix-pull-request-github-plugin"},
effectedAppSets: []string{"git-github", "git-github-ssh", "git-github-alt-ssh", "matrix-git-github", "merge-git-github", "matrix-scm-git-github", "matrix-nested-git-github", "merge-nested-git-github", "plugin", "matrix-pull-request-github-plugin"},
expectedStatusCode: http.StatusOK,
expectedRefresh: true,
},
Expand All @@ -72,7 +72,7 @@ func TestWebhookHandler(t *testing.T) {
headerKey: "X-GitHub-Event",
headerValue: "push",
payloadFile: "github-commit-branch-event.json",
effectedAppSets: []string{"git-github", "plugin", "matrix-pull-request-github-plugin"},
effectedAppSets: []string{"git-github", "git-github-ssh", "git-github-alt-ssh", "plugin", "matrix-pull-request-github-plugin"},
expectedStatusCode: http.StatusOK,
expectedRefresh: true,
},
Expand All @@ -81,7 +81,7 @@ func TestWebhookHandler(t *testing.T) {
headerKey: "X-GitHub-Event",
headerValue: "ping",
payloadFile: "github-ping-event.json",
effectedAppSets: []string{"git-github", "plugin"},
effectedAppSets: []string{"git-github", "git-github-ssh", "git-github-alt-ssh", "plugin"},
expectedStatusCode: http.StatusOK,
expectedRefresh: false,
},
Expand All @@ -90,7 +90,7 @@ func TestWebhookHandler(t *testing.T) {
headerKey: "X-Gitlab-Event",
headerValue: "Push Hook",
payloadFile: "gitlab-event.json",
effectedAppSets: []string{"git-gitlab", "plugin", "matrix-pull-request-github-plugin"},
effectedAppSets: []string{"git-gitlab", "git-gitlab-ssh", "git-gitlab-alt-ssh", "plugin", "matrix-pull-request-github-plugin"},
expectedStatusCode: http.StatusOK,
expectedRefresh: true,
},
Expand All @@ -99,7 +99,7 @@ func TestWebhookHandler(t *testing.T) {
headerKey: "X-Random-Event",
headerValue: "Push Hook",
payloadFile: "gitlab-event.json",
effectedAppSets: []string{"git-gitlab", "plugin"},
effectedAppSets: []string{"git-gitlab", "git-gitlab-ssh", "git-gitlab-alt-ssh", "plugin"},
expectedStatusCode: http.StatusBadRequest,
expectedRefresh: false,
},
Expand All @@ -108,7 +108,7 @@ func TestWebhookHandler(t *testing.T) {
headerKey: "X-Random-Event",
headerValue: "Push Hook",
payloadFile: "invalid-event.json",
effectedAppSets: []string{"git-gitlab", "plugin"},
effectedAppSets: []string{"git-gitlab", "git-gitlab-ssh", "git-gitlab-alt-ssh", "plugin"},
expectedStatusCode: http.StatusBadRequest,
expectedRefresh: false,
},
Expand Down Expand Up @@ -190,7 +190,11 @@ func TestWebhookHandler(t *testing.T) {
t.Run(test.desc, func(t *testing.T) {
fc := fake.NewClientBuilder().WithScheme(scheme).WithObjects(
fakeAppWithGitGenerator("git-github", namespace, "https://github.com/org/repo"),
fakeAppWithGitGenerator("git-gitlab", namespace, "https://gitlab/group/name"),
fakeAppWithGitGenerator("git-github-ssh", namespace, "ssh://[email protected]/org/repo"),
fakeAppWithGitGenerator("git-github-alt-ssh", namespace, "ssh://[email protected]:443/org/repo"),
fakeAppWithGitGenerator("git-gitlab", namespace, "https://gitlab.com/group/name"),
fakeAppWithGitGenerator("git-gitlab-ssh", namespace, "ssh://[email protected]/group/name"),
fakeAppWithGitGenerator("git-gitlab-alt-ssh", namespace, "ssh://[email protected]:443/group/name"),
fakeAppWithGitGenerator("git-azure-devops", namespace, "https://dev.azure.com/fabrikam-fiber-inc/DefaultCollection/_git/Fabrikam-Fiber-Git"),
fakeAppWithGithubPullRequestGenerator("pull-request-github", namespace, "CodErTOcat", "Hello-World"),
fakeAppWithGitlabPullRequestGenerator("pull-request-gitlab", namespace, "100500"),
Expand Down
2 changes: 1 addition & 1 deletion util/webhook/webhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -347,7 +347,7 @@ func getWebUrlRegex(webURL string) (*regexp.Regexp, error) {

regexEscapedHostname := regexp.QuoteMeta(urlObj.Hostname())
regexEscapedPath := regexp.QuoteMeta(urlObj.EscapedPath()[1:])
regexpStr := fmt.Sprintf(`(?i)^(http://|https://|%s@|ssh://(%s@)?)%s(:[0-9]+|)[:/]%s(\.git)?$`,
regexpStr := fmt.Sprintf(`(?i)^(http://|https://|%s@|ssh://(%s@)?((alt)?ssh\.)?)%s(:[0-9]+|)[:/]%s(\.git)?$`,
usernameRegex, usernameRegex, regexEscapedHostname, regexEscapedPath)
repoRegexp, err := regexp.Compile(regexpStr)
if err != nil {
Expand Down
5 changes: 4 additions & 1 deletion util/webhook/webhook_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -616,10 +616,13 @@ func Test_getWebUrlRegex(t *testing.T) {
{false, "https://example.com/org/repo", "https://example.com/org/repo-2", "partial match should not match"},
{true, "https://example.com/org/repo", "https://example.com/org/repo.git", "no .git should match with .git"},
{true, "https://example.com/org/repo", "[email protected]:org/repo", "git without protocol should match"},
{true, "https://example.com/org/repo", "[email protected]:org/repo", "git with non-git username shout match"},
{true, "https://example.com/org/repo", "[email protected]:org/repo", "git with non-git username should match"},
{true, "https://example.com/org/repo", "ssh://[email protected]/org/repo", "git with protocol should match"},
{true, "https://example.com/org/repo", "ssh://[email protected]:22/org/repo", "git with port number should match"},
{true, "https://example.com:443/org/repo", "ssh://[email protected]:22/org/repo", "https and ssh w/ different port numbers should match"},
{true, "https://example.com:443/org/repo", "ssh://[email protected]:443/org/repo", "https and ssh w/ ssh subdomain should match"},
{true, "https://example.com:443/org/repo", "ssh://[email protected]:443/org/repo", "https and ssh w/ altssh subdomain should match"},
{false, "https://example.com:443/org/repo", "ssh://[email protected]:443/org/repo", "https and ssh w/ unknown subdomain should not match"},
{true, "https://example.com/org/repo", "ssh://[email protected]/org/repo", "valid usernames with hyphens in repo should match"},
{false, "https://example.com/org/repo", "ssh://[email protected]/org/repo", "invalid usernames with hyphens in repo should not match"},
{true, "https://example.com:443/org/repo", "[email protected]:22:ORG/REPO", "matches aren't case-sensitive"},
Expand Down