-
Notifications
You must be signed in to change notification settings - Fork 81
/
policy.go
105 lines (93 loc) · 3.31 KB
/
policy.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
package policy
import (
"context"
"fmt"
"github.com/openshift-pipelines/pipelines-as-code/pkg/apis/pipelinesascode/v1alpha1"
"github.com/openshift-pipelines/pipelines-as-code/pkg/events"
"github.com/openshift-pipelines/pipelines-as-code/pkg/params/info"
"github.com/openshift-pipelines/pipelines-as-code/pkg/provider"
"go.uber.org/zap"
)
type Result int
const (
ResultNotSet Result = 0
ResultAllowed Result = 1
ResultDisallowed Result = 2
)
type Policy struct {
Repository *v1alpha1.Repository
Event *info.Event
VCX provider.Interface
Logger *zap.SugaredLogger
EventEmitter *events.EventEmitter
}
func (p *Policy) checkAllowed(ctx context.Context, tType info.TriggerType) (Result, string) {
if p.Repository == nil {
return ResultNotSet, ""
}
settings := p.Repository.Spec.Settings
if settings == nil || settings.Policy == nil {
return ResultNotSet, ""
}
var sType []string
switch tType {
// 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.
case info.TriggerTypeOkToTest, info.TriggerTypeRetest:
sType = settings.Policy.OkToTest
case info.TriggerTypePullRequest:
sType = settings.Policy.PullRequest
// NOTE: not supported yet, will imp if it gets requested and reasonable to implement
case info.TriggerTypePush, info.TriggerTypeCancel, info.TriggerTypeCheckSuiteRerequested, info.TriggerTypeCheckRunRerequested:
return ResultNotSet, ""
default:
return ResultNotSet, ""
}
// if policy is set but empty then it mean disallow everything
if len(sType) == 0 {
return ResultDisallowed, "no policy set"
}
// remove empty values from sType
temp := []string{}
for _, val := range sType {
if val != "" {
temp = append(temp, val)
}
}
sType = temp
// if policy is set but with empty values then bail out.
if len(sType) == 0 {
return ResultDisallowed, "policy set and empty with no groups"
}
allowed, reason := p.VCX.CheckPolicyAllowing(ctx, p.Event, sType)
if allowed {
return ResultAllowed, ""
}
return ResultDisallowed, fmt.Sprintf("policy check: %s, %s", string(tType), reason)
}
func (p *Policy) IsAllowed(ctx context.Context, tType info.TriggerType) (Result, string) {
var reason string
policyRes, reason := p.checkAllowed(ctx, tType)
switch policyRes {
case ResultAllowed:
reason = fmt.Sprintf("policy check: policy is set for sender %s has been allowed to run CI via policy", p.Event.Sender)
p.EventEmitter.EmitMessage(p.Repository, zap.InfoLevel, "PolicySetAllowed", reason)
return ResultAllowed, ""
case ResultDisallowed:
allowed, err := p.VCX.IsAllowedOwnersFile(ctx, p.Event)
if err != nil {
return ResultDisallowed, err.Error()
}
if allowed {
reason = fmt.Sprintf("policy check: policy is set, sender %s not in the allowed policy but allowed via OWNERS file", p.Event.Sender)
p.EventEmitter.EmitMessage(p.Repository, zap.InfoLevel, "PolicySetAllowed", reason)
return ResultAllowed, ""
}
if reason == "" {
reason = fmt.Sprintf("policy check: policy is set but sender %s is not in the allowed groups", p.Event.Sender)
}
p.EventEmitter.EmitMessage(p.Repository, zap.InfoLevel, "PolicySetDisallowed", reason)
return ResultDisallowed, ""
case ResultNotSet: // this is to make golangci-lint happy
}
return ResultNotSet, reason
}