Skip to content

Commit 26acc37

Browse files
committed
Fallback to other ACL rules if the policy is set
On failure we were not falling back to other ACL rules and we were not checking if the other ACL rules were matching (like OWNERS file). Tests is more comprehensive and check that we are falling back properly and as well that the target is matching the OWNERS file. We now properly dump the errors/allowance in the kube events streams. Try to make sharing functions between gitea and GitHub as much as possible. Fix https://issues.redhat.com/browse/SRVKP-3542 Signed-off-by: Chmouel Boudjnah <[email protected]>
1 parent e114245 commit 26acc37

File tree

27 files changed

+315
-180
lines changed

27 files changed

+315
-180
lines changed

hack/dev/kind/install.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
# You probably need to install passwordstore https://www.passwordstore.org/ and
1111
# add your github secrets : github-application-id github-private-key
1212
# webhook.secret in a folder which needs to be specified in
13-
# the PAC_PASS_SECRET_FOLDER variable. or otheriwse you have to create the
13+
# the PAC_PASS_SECRET_FOLDER variable. or otherwise you have to create the
1414
# pipelines-as-code-secret manually
1515
#
1616
# If you need to install old pac as shipped in OSP1.7, you check it out somewhere

pkg/pipelineascode/match.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ is that what you want? make sure you use -n when generating the secret, eg: echo
9292

9393
// Set the client, we should error out if there is a problem with
9494
// token or secret or we won't be able to do much.
95-
err = p.vcx.SetClient(ctx, p.run, p.event, repo.Spec.Settings)
95+
err = p.vcx.SetClient(ctx, p.run, p.event, repo, p.eventEmitter)
9696
if err != nil {
9797
return repo, err
9898
}

pkg/policy/policy.go

Lines changed: 36 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"fmt"
66

77
"github.com/openshift-pipelines/pipelines-as-code/pkg/apis/pipelinesascode/v1alpha1"
8+
"github.com/openshift-pipelines/pipelines-as-code/pkg/events"
89
"github.com/openshift-pipelines/pipelines-as-code/pkg/params/info"
910
"github.com/openshift-pipelines/pipelines-as-code/pkg/provider"
1011
"go.uber.org/zap"
@@ -19,24 +20,29 @@ const (
1920
)
2021

2122
type Policy struct {
22-
Settings *v1alpha1.Settings
23-
Event *info.Event
24-
VCX provider.Interface
25-
Logger *zap.SugaredLogger
23+
Repository *v1alpha1.Repository
24+
Event *info.Event
25+
VCX provider.Interface
26+
Logger *zap.SugaredLogger
27+
EventEmitter *events.EventEmitter
2628
}
2729

28-
func (p *Policy) IsAllowed(ctx context.Context, tType info.TriggerType) (Result, error) {
29-
if p.Settings == nil || p.Settings.Policy == nil {
30+
func (p *Policy) checkAllowed(ctx context.Context, tType info.TriggerType) (Result, error) {
31+
if p.Repository == nil {
32+
return ResultNotSet, nil
33+
}
34+
settings := p.Repository.Spec.Settings
35+
if settings == nil || settings.Policy == nil {
3036
return ResultNotSet, nil
3137
}
3238

3339
var sType []string
3440
switch tType {
35-
// NOTE: This make /retest /ok-to-test /test bound to the same policy, which is fine from a security standpoint but maybe we want to refind
41+
// NOTE: This make /retest /ok-to-test /test bound to the same policy, which is fine from a security standpoint but maybe we want to refine this in the future.
3642
case info.TriggerTypeOkToTest, info.TriggerTypeRetest:
37-
sType = p.Settings.Policy.OkToTest
43+
sType = settings.Policy.OkToTest
3844
case info.TriggerTypePullRequest:
39-
sType = p.Settings.Policy.PullRequest
45+
sType = settings.Policy.PullRequest
4046
// NOTE: not supported yet, will imp if it gets requested and reasonable to implement
4147
case info.TriggerTypePush, info.TriggerTypeCancel, info.TriggerTypeCheckSuiteRerequested, info.TriggerTypeCheckRunRerequested:
4248
return ResultNotSet, nil
@@ -51,10 +57,30 @@ func (p *Policy) IsAllowed(ctx context.Context, tType info.TriggerType) (Result,
5157
allowed, reason := p.VCX.CheckPolicyAllowing(ctx, p.Event, sType)
5258
reasonMsg := fmt.Sprintf("policy check: %s, %s", string(tType), reason)
5359
if reason != "" {
54-
p.Logger.Info(reasonMsg)
60+
p.EventEmitter.EmitMessage(p.Repository, zap.InfoLevel, "PolicyCheck", reasonMsg)
5561
}
5662
if allowed {
5763
return ResultAllowed, nil
5864
}
5965
return ResultDisallowed, fmt.Errorf(reasonMsg)
6066
}
67+
68+
func (p *Policy) IsAllowed(ctx context.Context, tType info.TriggerType) (bool, string) {
69+
var reason string
70+
policyRes, err := p.checkAllowed(ctx, tType)
71+
if err != nil {
72+
return false, err.Error()
73+
}
74+
switch policyRes {
75+
case ResultAllowed:
76+
reason = fmt.Sprintf("policy check: policy is set for sender %s has been allowed to run CI via policy", p.Event.Sender)
77+
p.EventEmitter.EmitMessage(p.Repository, zap.InfoLevel, "PolicySetAllowed", reason)
78+
return true, ""
79+
case ResultDisallowed:
80+
reason = fmt.Sprintf("policy check: policy is set but sender %s is not in the allowed groups trying the next ACL conditions", p.Event.Sender)
81+
p.EventEmitter.EmitMessage(p.Repository, zap.InfoLevel, "PolicySetDisallowed", reason)
82+
case ResultNotSet:
83+
// should we put a warning here? it does fill up quite a bit the log every time! so I am not so sure..
84+
}
85+
return false, reason
86+
}

pkg/policy/policy_test.go

Lines changed: 69 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,32 @@ package policy
33
import (
44
"testing"
55

6-
"github.com/openshift-pipelines/pipelines-as-code/pkg/apis/pipelinesascode/v1alpha1"
7-
"github.com/openshift-pipelines/pipelines-as-code/pkg/params/info"
8-
testprovider "github.com/openshift-pipelines/pipelines-as-code/pkg/test/provider"
96
"go.uber.org/zap"
107
zapobserver "go.uber.org/zap/zaptest/observer"
8+
"gotest.tools/v3/assert"
119
rtesting "knative.dev/pkg/reconciler/testing"
10+
11+
"github.com/openshift-pipelines/pipelines-as-code/pkg/apis/pipelinesascode/v1alpha1"
12+
"github.com/openshift-pipelines/pipelines-as-code/pkg/events"
13+
"github.com/openshift-pipelines/pipelines-as-code/pkg/params/info"
14+
testclient "github.com/openshift-pipelines/pipelines-as-code/pkg/test/clients"
15+
testprovider "github.com/openshift-pipelines/pipelines-as-code/pkg/test/provider"
1216
)
1317

18+
func newRepoWithPolicy(policy *v1alpha1.Policy) *v1alpha1.Repository {
19+
return &v1alpha1.Repository{
20+
Spec: v1alpha1.RepositorySpec{
21+
Settings: &v1alpha1.Settings{
22+
Policy: policy,
23+
},
24+
},
25+
}
26+
}
27+
1428
func TestPolicy_IsAllowed(t *testing.T) {
1529
type fields struct {
16-
Settings *v1alpha1.Settings
17-
Event *info.Event
30+
repository *v1alpha1.Repository
31+
event *info.Event
1832
}
1933
type args struct {
2034
tType info.TriggerType
@@ -24,172 +38,141 @@ func TestPolicy_IsAllowed(t *testing.T) {
2438
fields fields
2539
args args
2640
replyAllowed bool
27-
want Result
41+
want bool
2842
wantErr bool
43+
wantReason string
2944
}{
3045
{
3146
name: "Test Policy.IsAllowed with no settings",
3247
fields: fields{
33-
Settings: nil,
34-
Event: nil,
48+
repository: nil,
49+
event: nil,
3550
},
3651
args: args{
3752
tType: info.TriggerTypePush,
3853
},
39-
want: ResultNotSet,
54+
want: false,
4055
},
4156
{
4257
name: "Test Policy.IsAllowed with unknown event type",
4358
fields: fields{
44-
Settings: &v1alpha1.Settings{
45-
Policy: &v1alpha1.Policy{
46-
PullRequest: []string{"pull_request"},
47-
},
48-
},
49-
Event: nil,
59+
repository: newRepoWithPolicy(&v1alpha1.Policy{PullRequest: []string{"pull_request"}}),
60+
event: nil,
5061
},
5162
args: args{
5263
tType: "unknown",
5364
},
54-
want: ResultNotSet,
65+
want: false,
5566
},
5667
{
5768
name: "allowing member not in team for pull request",
5869
fields: fields{
59-
Settings: &v1alpha1.Settings{
60-
Policy: &v1alpha1.Policy{
61-
PullRequest: []string{"pull_request"},
62-
},
63-
},
64-
Event: info.NewEvent(),
70+
repository: newRepoWithPolicy(&v1alpha1.Policy{PullRequest: []string{"pull_request"}}),
71+
event: info.NewEvent(),
6572
},
6673
args: args{
6774
tType: info.TriggerTypePullRequest,
6875
},
6976
replyAllowed: true,
70-
want: ResultAllowed,
77+
want: true,
7178
},
7279
{
73-
name: "empty settings policy ignore",
80+
name: "empty settings policy ignore",
81+
wantReason: "policy check: pull_request, policy disallowing",
7482
fields: fields{
75-
Settings: &v1alpha1.Settings{
76-
Policy: &v1alpha1.Policy{
77-
PullRequest: []string{},
78-
},
79-
},
80-
Event: info.NewEvent(),
83+
repository: newRepoWithPolicy(&v1alpha1.Policy{PullRequest: []string{""}}),
84+
event: info.NewEvent(),
8185
},
8286
args: args{
8387
tType: info.TriggerTypePullRequest,
8488
},
85-
replyAllowed: true,
86-
want: ResultNotSet,
89+
want: false,
8790
},
8891
{
89-
name: "disallowing member not in team for pull request",
92+
name: "disallowing member not in team for pull request",
93+
wantReason: "policy check: pull_request, policy disallowing",
9094
fields: fields{
91-
Settings: &v1alpha1.Settings{
92-
Policy: &v1alpha1.Policy{
93-
PullRequest: []string{"pull_request"},
94-
},
95-
},
96-
Event: info.NewEvent(),
95+
repository: newRepoWithPolicy(&v1alpha1.Policy{PullRequest: []string{"pull_request"}}),
96+
event: info.NewEvent(),
9797
},
9898
args: args{
9999
tType: info.TriggerTypePullRequest,
100100
},
101-
replyAllowed: false,
102-
want: ResultDisallowed,
103-
wantErr: true,
101+
want: false,
102+
wantErr: true,
104103
},
105104
{
106-
name: "allowing member not in team for ok-to-test",
105+
name: "allowing member in team for ok-to-test",
107106
fields: fields{
108-
Settings: &v1alpha1.Settings{
109-
Policy: &v1alpha1.Policy{
110-
OkToTest: []string{"ok-to-test"},
111-
},
112-
},
113-
Event: info.NewEvent(),
107+
repository: newRepoWithPolicy(&v1alpha1.Policy{PullRequest: []string{"ok-to-test"}}),
108+
event: info.NewEvent(),
114109
},
115110
args: args{
116111
tType: info.TriggerTypeOkToTest,
117112
},
118113
replyAllowed: true,
119-
want: ResultAllowed,
114+
want: false,
120115
},
121116
{
122117
name: "disallowing member not in team for ok-to-test",
123118
fields: fields{
124-
Settings: &v1alpha1.Settings{
125-
Policy: &v1alpha1.Policy{
126-
OkToTest: []string{"ok-to-test"},
127-
},
128-
},
129-
Event: info.NewEvent(),
119+
repository: newRepoWithPolicy(&v1alpha1.Policy{PullRequest: []string{"ok-to-test"}}),
120+
event: info.NewEvent(),
130121
},
131122
args: args{
132123
tType: info.TriggerTypeOkToTest,
133124
},
134-
replyAllowed: false,
135-
want: ResultDisallowed,
136-
wantErr: true,
125+
want: false,
126+
wantErr: true,
137127
},
138128
{
139129
name: "allowing member not in team for retest",
140130
fields: fields{
141-
Settings: &v1alpha1.Settings{
142-
Policy: &v1alpha1.Policy{
143-
OkToTest: []string{"ok-to-test"},
144-
},
145-
},
146-
Event: info.NewEvent(),
131+
repository: newRepoWithPolicy(&v1alpha1.Policy{PullRequest: []string{"ok-to-test"}}),
132+
event: info.NewEvent(),
147133
},
148134
args: args{
149135
tType: info.TriggerTypeRetest,
150136
},
151-
replyAllowed: true,
152-
want: ResultAllowed,
137+
want: false,
153138
},
154139
{
155140
name: "disallowing member not in team for retest",
156141
fields: fields{
157-
Settings: &v1alpha1.Settings{
158-
Policy: &v1alpha1.Policy{
159-
OkToTest: []string{"ok-to-test"},
160-
},
161-
},
162-
Event: info.NewEvent(),
142+
repository: newRepoWithPolicy(&v1alpha1.Policy{PullRequest: []string{"ok-to-test"}}),
143+
event: info.NewEvent(),
163144
},
164145
args: args{
165146
tType: info.TriggerTypeRetest,
166147
},
167-
replyAllowed: false,
168-
want: ResultDisallowed,
169-
wantErr: true,
148+
want: false,
149+
wantErr: true,
170150
},
171151
}
172152
for _, tt := range tests {
173153
t.Run(tt.name, func(t *testing.T) {
174154
observer, _ := zapobserver.New(zap.InfoLevel)
175155
logger := zap.New(observer).Sugar()
176156

157+
ctx, _ := rtesting.SetupFakeContext(t)
158+
stdata, _ := testclient.SeedTestData(t, ctx, testclient.Data{})
159+
177160
vcx := &testprovider.TestProviderImp{PolicyDisallowing: !tt.replyAllowed}
178-
p := &Policy{
179-
Settings: tt.fields.Settings,
180-
Event: tt.fields.Event,
181-
VCX: vcx,
182-
Logger: logger,
161+
if tt.fields.event == nil {
162+
tt.fields.event = info.NewEvent()
183163
}
184-
ctx, _ := rtesting.SetupFakeContext(t)
185-
got, err := p.IsAllowed(ctx, tt.args.tType)
186-
if (err != nil) != tt.wantErr {
187-
t.Errorf("Policy.IsAllowed() error = %v, wantErr %v", err, tt.wantErr)
188-
return
164+
p := &Policy{
165+
Repository: tt.fields.repository,
166+
Event: tt.fields.event,
167+
VCX: vcx,
168+
Logger: logger,
169+
EventEmitter: events.NewEventEmitter(stdata.Kube, logger),
189170
}
171+
got, reason := p.IsAllowed(ctx, tt.args.tType)
190172
if got != tt.want {
191173
t.Errorf("Policy.IsAllowed() = %v, want %v", got, tt.want)
192174
}
175+
assert.Equal(t, tt.wantReason, reason)
193176
})
194177
}
195178
}

pkg/provider/bitbucketcloud/bitbucket.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"github.com/ktrysmt/go-bitbucket"
1010
"github.com/mitchellh/mapstructure"
1111
"github.com/openshift-pipelines/pipelines-as-code/pkg/apis/pipelinesascode/v1alpha1"
12+
"github.com/openshift-pipelines/pipelines-as-code/pkg/events"
1213
"github.com/openshift-pipelines/pipelines-as-code/pkg/params"
1314
"github.com/openshift-pipelines/pipelines-as-code/pkg/params/info"
1415
"github.com/openshift-pipelines/pipelines-as-code/pkg/provider"
@@ -165,7 +166,7 @@ func (v *Provider) GetFileInsideRepo(_ context.Context, event *info.Event, path,
165166
return v.getBlob(event, revision, path)
166167
}
167168

168-
func (v *Provider) SetClient(_ context.Context, _ *params.Run, event *info.Event, _ *v1alpha1.Settings) error {
169+
func (v *Provider) SetClient(_ context.Context, _ *params.Run, event *info.Event, _ *v1alpha1.Repository, _ *events.EventEmitter) error {
169170
if event.Provider.Token == "" {
170171
return fmt.Errorf("no git_provider.secret has been set in the repo crd")
171172
}

pkg/provider/bitbucketcloud/bitbucket_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ func TestSetClient(t *testing.T) {
130130
t.Run(tt.name, func(t *testing.T) {
131131
ctx, _ := rtesting.SetupFakeContext(t)
132132
v := Provider{}
133-
err := v.SetClient(ctx, nil, tt.event, nil)
133+
err := v.SetClient(ctx, nil, tt.event, nil, nil)
134134
if tt.wantErrSubstr != "" {
135135
assert.ErrorContains(t, err, tt.wantErrSubstr)
136136
return

0 commit comments

Comments
 (0)