Skip to content

Commit

Permalink
feat: allow to list trusted apps
Browse files Browse the repository at this point in the history
  • Loading branch information
Maximilien-R committed Apr 19, 2024
1 parent 65ad1db commit 1911558
Show file tree
Hide file tree
Showing 5 changed files with 140 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,7 @@ Trigger specifies a configuration for a single trigger.<br /><br />The configura
|---|---|---|---|
| `repos` | []string | No | Repos is either of the form org/repos or just org. |
| `trusted_org` | string | No | TrustedOrg is the org whose members' PRs will be automatically built<br />for PRs to the above repos. The default is the PR's org. |
| `trusted_apps` | []string | No | TrustedApps is the explicit list of GitHub apps whose PRs will be automatically<br />considered as trusted. The list should contain usernames of each GitHub App without [bot] suffix.<br/>By default, trigger will ignore this list. |
| `join_org_url` | string | No | JoinOrgURL is a link that redirects users to a location where they<br />should be able to read more about joining the organization in order<br />to become trusted members. Defaults to the Github link of TrustedOrg. |
| `only_org_members` | bool | No | OnlyOrgMembers requires PRs and/or /ok-to-test comments to come from org members.<br />By default, trigger also include repo collaborators. |
| `ignore_ok_to_test` | bool | No | IgnoreOkToTest makes trigger ignore /ok-to-test comments.<br />This is a security mitigation to only allow testing from trusted users. |
Expand Down
1 change: 1 addition & 0 deletions docs/plugins/Plugins config.md
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,7 @@ Trigger specifies a configuration for a single trigger.<br /><br />The configura
|---|---|---|---|---|
| Repos | `repos` | []string | No | Repos is either of the form org/repos or just org. |
| TrustedOrg | `trusted_org` | string | No | TrustedOrg is the org whose members' PRs will be automatically built<br />for PRs to the above repos. The default is the PR's org. |
| TrustedApps | `trusted_apps` | []string | No | TrustedApps is the explicit list of GitHub apps whose PRs will be automatically<br />considered as trusted. The list should contain usernames of each GitHub App without [bot] suffix.<br/>By default, trigger will ignore this list. |
| JoinOrgURL | `join_org_url` | string | No | JoinOrgURL is a link that redirects users to a location where they<br />should be able to read more about joining the organization in order<br />to become trusted members. Defaults to the Github link of TrustedOrg. |
| OnlyOrgMembers | `only_org_members` | bool | No | OnlyOrgMembers requires PRs and/or /ok-to-test comments to come from org members.<br />By default, trigger also include repo collaborators. |
| IgnoreOkToTest | `ignore_ok_to_test` | bool | No | IgnoreOkToTest makes trigger ignore /ok-to-test comments.<br />This is a security mitigation to only allow testing from trusted users. |
Expand Down
4 changes: 4 additions & 0 deletions pkg/plugins/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,10 @@ type Trigger struct {
// TrustedOrg is the org whose members' PRs will be automatically built
// for PRs to the above repos. The default is the PR's org.
TrustedOrg string `json:"trusted_org,omitempty"`
// TrustedApps is the explicit list of GitHub apps whose PRs will be automatically
// considered as trusted. The list should contain usernames of each GitHub App without [bot] suffix.
// By default, trigger will ignore this list.
TrustedApps []string `json:"trusted_apps,omitempty"`
// JoinOrgURL is a link that redirects users to a location where they
// should be able to read more about joining the organization in order
// to become trusted members. Defaults to the Github link of TrustedOrg.
Expand Down
10 changes: 9 additions & 1 deletion pkg/plugins/trigger/trigger.go
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ func handlePush(pc plugins.Agent, pe scm.PushHook) error {

// TrustedUser returns true if user is trusted in repo.
//
// Trusted users are either repo collaborators, org members or trusted org members.
// Trusted users are either repo collaborators, org members, trusted org members or trusted Github Apps.
// Whether repo collaborators and/or a second org is trusted is configured by trigger.
func TrustedUser(spc trustedUserClient, trigger *plugins.Trigger, user, org, repo string) (bool, error) {
botUser, err := spc.BotName()
Expand Down Expand Up @@ -214,6 +214,14 @@ func TrustedUser(spc trustedUserClient, trigger *plugins.Trigger, user, org, rep
return true, nil
}

// Determine if user is on trusted_apps list.
// This allows automatic tests execution for GitHub automations that cannot be added as collaborators.
for _, trustedApp := range trigger.TrustedApps {
if tUser := strings.TrimSuffix(user, "[bot]"); tUser == trustedApp {
return true, nil
}
}

// Determine if there is a second org to check
if trigger.TrustedOrg == "" || trigger.TrustedOrg == org {
return false, nil // No trusted org and/or it is the same
Expand Down
125 changes: 125 additions & 0 deletions pkg/plugins/trigger/trigger_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -515,3 +515,128 @@ func TestValidateContextOverlap(t *testing.T) {
})
}
}

func TestTrustedUser(t *testing.T) {
var testcases = []struct {
name string

onlyOrgMembers bool
trustedApps []string
trustedOrg string

user string
org string
repo string

expectedTrusted bool
}{
{
name: "user is member of trusted org",
onlyOrgMembers: false,
user: "test",
org: "kubernetes",
repo: "kubernetes",
expectedTrusted: true,
},
{
name: "user is member of trusted org (only org members enabled)",
onlyOrgMembers: true,
user: "test",
org: "kubernetes",
repo: "kubernetes",
expectedTrusted: true,
},
{
name: "user is collaborator",
onlyOrgMembers: false,
user: "test-collaborator",
org: "kubernetes",
repo: "kubernetes",
expectedTrusted: true,
},
{
name: "user is collaborator (only org members enabled)",
onlyOrgMembers: true,
user: "test-collaborator",
org: "kubernetes",
repo: "kubernetes",
expectedTrusted: false,
},
{
name: "user is trusted org member",
onlyOrgMembers: false,
trustedOrg: "kubernetes",
user: "test",
org: "kubernetes-sigs",
repo: "test",
expectedTrusted: true,
},
{
name: "user is not org member",
onlyOrgMembers: false,
user: "test-2",
org: "kubernetes",
repo: "kubernetes",
expectedTrusted: false,
},
{
name: "user is not org member or trusted org member",
onlyOrgMembers: false,
trustedOrg: "kubernetes-sigs",
user: "test-2",
org: "kubernetes",
repo: "kubernetes",
expectedTrusted: false,
},
{
name: "user is not org member or trusted org member, onlyOrgMembers true",
onlyOrgMembers: true,
trustedOrg: "kubernetes-sigs",
user: "test-2",
org: "kubernetes",
repo: "kubernetes",
expectedTrusted: false,
},
{
name: "Self as bot is trusted",
user: "k8s-ci-robot",
expectedTrusted: true,
},
{
name: "github-app[bot] is in trusted list",
user: "github-app[bot]",
trustedApps: []string{"github-app"},
expectedTrusted: true,
},
{
name: "github-app[bot] is not in trusted list",
user: "github-app[bot]",
trustedApps: []string{"other-app"},
expectedTrusted: false,
},
}

for _, tc := range testcases {
t.Run(tc.name, func(t *testing.T) {
fakeSCMClient := fake2.SCMClient{}
fakeSCMClient.OrgMembers = map[string][]string{
"kubernetes": {"test"},
}
fakeSCMClient.Collaborators = []string{"test-collaborator"}

triggerPlugin := plugins.Trigger{
TrustedOrg: tc.trustedOrg,
TrustedApps: tc.trustedApps,
OnlyOrgMembers: tc.onlyOrgMembers,
}

trustedResponse, err := TrustedUser(&fakeSCMClient, &triggerPlugin, tc.user, tc.org, tc.repo)
if err != nil {
t.Errorf("For case %s, didn't expect error from TrustedUser: %v", tc.name, err)
}
if trustedResponse != tc.expectedTrusted {
t.Errorf("For case %s, expect trusted: %v, but got: %v", tc.name, tc.expectedTrusted, trustedResponse)
}
})
}
}

0 comments on commit 1911558

Please sign in to comment.