-
Notifications
You must be signed in to change notification settings - Fork 84
/
contains_scenario_groups_operator.go
107 lines (89 loc) · 3.81 KB
/
contains_scenario_groups_operator.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
106
107
package operators
import (
"context"
"github.com/kyma-incubator/compass/components/director/internal/domain/onetimetoken"
"github.com/kyma-incubator/compass/components/director/internal/model"
"github.com/kyma-incubator/compass/components/director/pkg/formationconstraint"
"github.com/kyma-incubator/compass/components/director/pkg/graphql"
"github.com/kyma-incubator/compass/components/director/pkg/log"
pkgmodel "github.com/kyma-incubator/compass/components/director/pkg/model"
"github.com/pkg/errors"
"k8s.io/utils/strings/slices"
)
const (
// ContainsScenarioGroupsOperator represents the ContainsScenarioGroups operator
ContainsScenarioGroupsOperator = "ContainsScenarioGroups"
)
// NewContainsScenarioGroupsInput is input constructor for ContainsScenarioGroupsOperator operator. It returns empty OperatorInput.
func NewContainsScenarioGroupsInput() OperatorInput {
return &formationconstraint.ContainsScenarioGroupsInput{}
}
// ContainsScenarioGroups is a constraint operator. It checks if the resource from the OperatorInput contains any of the scenario groups.
func (e *ConstraintEngine) ContainsScenarioGroups(ctx context.Context, input OperatorInput) (bool, error) {
log.C(ctx).Infof("Executing operator: %s", ContainsScenarioGroupsOperator)
i, ok := input.(*formationconstraint.ContainsScenarioGroupsInput)
if !ok {
return false, errors.New("Incompatible input")
}
log.C(ctx).Infof("Enforcing %q constraint on resource of type: %q, subtype: %q and ID: %q", ContainsScenarioGroupsOperator, i.ResourceType, i.ResourceSubtype, i.ResourceID)
if i.ResourceType != model.ApplicationResourceType {
return false, errors.Errorf("Unsupported resource type %q", i.ResourceType)
}
hasCorrectScenarioGroups, err := e.hasCorrectScenarioGroups(ctx, i.ResourceID, i.Tenant, i.RequiredScenarioGroups)
if err != nil {
return false, err
}
return hasCorrectScenarioGroups, nil
}
func (e *ConstraintEngine) hasCorrectScenarioGroups(ctx context.Context, applicationID, tenant string, requiredScenarioGroups []string) (bool, error) {
if len(requiredScenarioGroups) == 0 {
return true, nil
}
application, err := e.applicationRepository.GetByID(ctx, tenant, applicationID)
if err != nil {
return false, errors.Wrapf(err, "while getting application with ID %q", applicationID)
}
if application.Status == nil || string(application.Status.Condition) != string(graphql.ApplicationStatusConditionConnected) {
return false, errors.Errorf("Application with ID %q is not in status %s", applicationID, graphql.ApplicationStatusConditionConnected)
}
auths, err := e.systemAuthSvc.ListForObject(ctx, pkgmodel.ApplicationReference, applicationID)
if err != nil {
return false, errors.Wrapf(err, "while getting system auths for application with ID %q", applicationID)
}
latestOTT := getLatestToken(auths)
if latestOTT == nil {
return false, nil
}
if len(latestOTT.ScenarioGroups) == 0 {
// If scenario groups are empty, this means that these are legacy tokens,
// which should be interpreted as unrestricted
return true, nil
}
scenarioGroups, err := onetimetoken.UnmarshalScenarioGroups(latestOTT.ScenarioGroups)
if err != nil {
for _, scenarioGroup := range latestOTT.ScenarioGroups {
if slices.Contains(requiredScenarioGroups, scenarioGroup) {
return true, nil
}
}
return false, nil
}
for _, scenarioGroup := range scenarioGroups {
if slices.Contains(requiredScenarioGroups, scenarioGroup.Key) {
return true, nil
}
}
return false, nil
}
func getLatestToken(auths []pkgmodel.SystemAuth) *model.OneTimeToken {
var latestToken *model.OneTimeToken = nil
for _, auth := range auths {
if auth.Value == nil || auth.Value.OneTimeToken == nil {
continue
}
if latestToken == nil || latestToken.CreatedAt.Before(auth.Value.OneTimeToken.CreatedAt) {
latestToken = auth.Value.OneTimeToken
}
}
return latestToken
}