• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

SAP / sap-btp-service-operator / 16642491316

31 Jul 2025 07:15AM UTC coverage: 79.955% (-0.3%) from 80.217%
16642491316

Pull #545

github

kerenlahav
review fixes
Pull Request #545: [BUG FIX] cred rotation is not working when binding's name is longer than 63 chars

16 of 55 new or added lines in 3 files covered. (29.09%)

2 existing lines in 1 file now uncovered.

2820 of 3527 relevant lines covered (79.95%)

0.9 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

72.84
/api/v1/servicebinding_validating_webhook.go
1
/*
2

3

4
Licensed under the Apache License, Version 2.0 (the "License");
5
you may not use this file except in compliance with the License.
6
You may obtain a copy of the License at
7

8
    http://www.apache.org/licenses/LICENSE-2.0
9

10
Unless required by applicable law or agreed to in writing, software
11
distributed under the License is distributed on an "AS IS" BASIS,
12
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
See the License for the specific language governing permissions and
14
limitations under the License.
15
*/
16

17
package v1
18

19
import (
20
        "context"
21
        "fmt"
22
        "reflect"
23
        "time"
24

25
        "github.com/SAP/sap-btp-service-operator/api/common"
26
        "k8s.io/apimachinery/pkg/runtime"
27
        ctrl "sigs.k8s.io/controller-runtime"
28
        logf "sigs.k8s.io/controller-runtime/pkg/log"
29
        "sigs.k8s.io/controller-runtime/pkg/webhook"
30
        "sigs.k8s.io/controller-runtime/pkg/webhook/admission"
31
)
32

33
// log is for logging in this package.
34
var servicebindinglog = logf.Log.WithName("servicebinding-resource")
35

36
func (sb *ServiceBinding) SetupWebhookWithManager(mgr ctrl.Manager) error {
×
37
        return ctrl.NewWebhookManagedBy(mgr).For(sb).WithValidator(sb).Complete()
×
38
}
×
39

40
// EDIT THIS FILE!  THIS IS SCAFFOLDING FOR YOU TO OWN!
41

42
// TODO(user): change verbs to "verbs=create;update;delete" if you want to enable deletion validation.
43
// +kubebuilder:webhook:verbs=create;update,path=/validate-services-cloud-sap-com-v1-servicebinding,mutating=false,failurePolicy=fail,groups=services.cloud.sap.com,resources=servicebindings,versions=v1,name=vservicebinding.kb.io,sideEffects=None,admissionReviewVersions=v1beta1;v1
44

45
var _ webhook.CustomValidator = &ServiceBinding{}
46

47
// ValidateCreate implements webhook.Validator so a webhook will be registered for the type
48
func (sb *ServiceBinding) ValidateCreate(_ context.Context, obj runtime.Object) (admission.Warnings, error) {
1✔
49
        newBinding := obj.(*ServiceBinding)
1✔
50
        servicebindinglog.Info("validate create", "name", newBinding.ObjectMeta.Name)
1✔
51
        if newBinding.Spec.CredRotationPolicy != nil {
2✔
52
                if err := newBinding.validateCredRotatingConfig(); err != nil {
1✔
53
                        return nil, err
×
54
                }
×
55
        }
56
        return nil, nil
1✔
57
}
58

59
// ValidateUpdate implements webhook.Validator so a webhook will be registered for the type
60
func (sb *ServiceBinding) ValidateUpdate(_ context.Context, oldObj, newObj runtime.Object) (admission.Warnings, error) {
1✔
61
        oldBinding := oldObj.(*ServiceBinding)
1✔
62
        newBinding := newObj.(*ServiceBinding)
1✔
63
        servicebindinglog.Info("validate update", "name", newBinding.ObjectMeta.Name)
1✔
64
        if newBinding.Spec.CredRotationPolicy != nil {
2✔
65
                if err := newBinding.validateCredRotatingConfig(); err != nil {
2✔
66
                        return nil, err
1✔
67
                }
1✔
68
        }
69
        isStale := false
1✔
70
        if oldBinding.Labels != nil {
2✔
71
                if _, ok := oldBinding.Labels[common.StaleBindingIDLabel]; ok {
2✔
72
                        if newBinding.Spec.CredRotationPolicy.Enabled {
2✔
73
                                return nil, fmt.Errorf("enabling cred rotation for rotated binding is not allowed")
1✔
74
                        }
1✔
NEW
75
                        if !newBinding.validateRotationFields(oldBinding) {
×
76
                                return nil, fmt.Errorf("modifying rotation labels is not allowed")
×
77
                        }
×
78
                        isStale = true
×
79
                }
80
        }
81

82
        if newBinding.Spec.UserInfo == nil {
2✔
83
                newBinding.Spec.UserInfo = oldBinding.Spec.UserInfo
1✔
84
        } else if !reflect.DeepEqual(newBinding.Spec.UserInfo, oldBinding.Spec.UserInfo) {
3✔
85
                return nil, fmt.Errorf("modifying spec.userInfo is not allowed")
1✔
86
        }
1✔
87

88
        isSpecChanged := newBinding.specChanged(oldBinding)
1✔
89
        if isSpecChanged && (newBinding.Status.BindingID != "" || isStale) {
2✔
90

1✔
91
                return nil, fmt.Errorf("updating service bindings is not supported")
1✔
92
        }
1✔
93
        return nil, nil
1✔
94
}
95

NEW
96
func (sb *ServiceBinding) validateRotationFields(old *ServiceBinding) bool {
×
NEW
97
        if sb.ObjectMeta.Labels == nil {
×
98
                return false
×
99
        }
×
100

NEW
101
        isValid := sb.ObjectMeta.Labels[common.StaleBindingIDLabel] == old.ObjectMeta.Labels[common.StaleBindingIDLabel] &&
×
NEW
102
                sb.ObjectMeta.Labels[common.StaleBindingRotationOfLabel] == old.ObjectMeta.Labels[common.StaleBindingRotationOfLabel]
×
NEW
103

×
NEW
104
        if old.ObjectMeta.Annotations != nil && len(old.ObjectMeta.Annotations[common.StaleBindingOrigBindingNameAnnotation]) > 0 {
×
NEW
105
                isValid = isValid && sb.ObjectMeta.Annotations[common.StaleBindingOrigBindingNameAnnotation] == old.ObjectMeta.Annotations[common.StaleBindingOrigBindingNameAnnotation]
×
NEW
106
        }
×
NEW
107
        return isValid
×
108
}
109

110
func (sb *ServiceBinding) specChanged(oldBinding *ServiceBinding) bool {
1✔
111
        oldSpec := oldBinding.Spec.DeepCopy()
1✔
112
        newSpec := sb.Spec.DeepCopy()
1✔
113

1✔
114
        //allow changing cred rotation config
1✔
115
        oldSpec.CredRotationPolicy = nil
1✔
116
        newSpec.CredRotationPolicy = nil
1✔
117

1✔
118
        //allow changing SecretTemplate
1✔
119
        oldSpec.SecretTemplate = ""
1✔
120
        newSpec.SecretTemplate = ""
1✔
121

1✔
122
        return !reflect.DeepEqual(oldSpec, newSpec)
1✔
123
}
1✔
124

125
// ValidateDelete implements webhook.Validator so a webhook will be registered for the type
126
func (sb *ServiceBinding) ValidateDelete(_ context.Context, _ runtime.Object) (admission.Warnings, error) {
1✔
127
        servicebindinglog.Info("validate delete", "name", sb.ObjectMeta.Name)
1✔
128

1✔
129
        // TODO(user): fill in your validation logic upon object deletion.
1✔
130
        return nil, nil
1✔
131
}
1✔
132

133
func (sb *ServiceBinding) validateCredRotatingConfig() error {
1✔
134
        _, err := time.ParseDuration(sb.Spec.CredRotationPolicy.RotatedBindingTTL)
1✔
135
        if err != nil {
2✔
136
                return err
1✔
137
        }
1✔
138
        _, err = time.ParseDuration(sb.Spec.CredRotationPolicy.RotationFrequency)
1✔
139
        if err != nil {
1✔
140
                return err
×
141
        }
×
142

143
        return nil
1✔
144
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc