Skip to content

Commit

Permalink
Bug fix - block user updates on spec.userInfo (#399)
Browse files Browse the repository at this point in the history
  • Loading branch information
kerenlahav authored Feb 22, 2024
1 parent b434879 commit bb925b0
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 30 deletions.
6 changes: 3 additions & 3 deletions api/v1/webhooks/servicebinding_mutating_webhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ func (s *ServiceBindingDefaulter) Handle(_ context.Context, req admission.Reques
}
}

if req.Operation == v1admission.Create || req.Operation == v1admission.Delete {
if req.Operation == v1admission.Create {
binding.Spec.UserInfo = &v1.UserInfo{
Username: req.UserInfo.Username,
UID: req.UserInfo.UID,
Expand All @@ -57,9 +57,9 @@ func (s *ServiceBindingDefaulter) Handle(_ context.Context, req admission.Reques
}
}

marshaledInstance, err := json.Marshal(binding)
marshaledBinding, err := json.Marshal(binding)
if err != nil {
return admission.Errored(http.StatusInternalServerError, err)
}
return admission.PatchResponseFromRaw(req.Object.Raw, marshaledInstance)
return admission.PatchResponseFromRaw(req.Object.Raw, marshaledBinding)
}
52 changes: 25 additions & 27 deletions api/v1/webhooks/serviceinstance_mutating_webhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,42 +30,40 @@ func (s *ServiceInstanceDefaulter) Handle(_ context.Context, req admission.Reque
return admission.Errored(http.StatusBadRequest, err)
}

if req.Operation == v1admission.Create {
instance.Spec.UserInfo = &v1.UserInfo{
Username: req.UserInfo.Username,
UID: req.UserInfo.UID,
Groups: req.UserInfo.Groups,
Extra: req.UserInfo.Extra,
}
} else {
oldInstance := &servicesv1.ServiceInstance{}
err := s.Decoder.DecodeRaw(req.OldObject, oldInstance)
if err != nil {
return admission.Errored(http.StatusInternalServerError, err)
}

if !reflect.DeepEqual(instance.Spec.UserInfo, oldInstance.Spec.UserInfo) {
return admission.Errored(http.StatusBadRequest, fmt.Errorf("modifying spec.userInfo is not allowed"))
} else if !reflect.DeepEqual(oldInstance.Spec, instance.Spec) { //UserInfo is updated only when spec is changed
instance.Spec.UserInfo = &v1.UserInfo{
Username: req.UserInfo.Username,
UID: req.UserInfo.UID,
Groups: req.UserInfo.Groups,
Extra: req.UserInfo.Extra,
}
}
}
if len(instance.Spec.ExternalName) == 0 {
instancelog.Info(fmt.Sprintf("externalName not provided, defaulting to k8s name: %s", instance.Name))
instance.Spec.ExternalName = instance.Name
}

if err := s.setServiceInstanceUserInfo(req, instance); err != nil {
return admission.Errored(http.StatusInternalServerError, err)
}

marshaledInstance, err := json.Marshal(instance)
if err != nil {
return admission.Errored(http.StatusInternalServerError, err)
}

return admission.PatchResponseFromRaw(req.Object.Raw, marshaledInstance)
}

func (s *ServiceInstanceDefaulter) setServiceInstanceUserInfo(req admission.Request, instance *servicesv1.ServiceInstance) error {
userInfo := &v1.UserInfo{
Username: req.UserInfo.Username,
UID: req.UserInfo.UID,
Groups: req.UserInfo.Groups,
Extra: req.UserInfo.Extra,
}

if req.Operation == v1admission.Create || req.Operation == v1admission.Delete {
instance.Spec.UserInfo = userInfo
} else if req.Operation == v1admission.Update {
oldInstance := &servicesv1.ServiceInstance{}
err := s.Decoder.DecodeRaw(req.OldObject, oldInstance)
if err != nil {
return err
}
if !reflect.DeepEqual(oldInstance.Spec, instance.Spec) {
instance.Spec.UserInfo = userInfo
}
}
return nil
}
14 changes: 14 additions & 0 deletions controllers/servicebinding_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import (
"net/http"
"strings"

authv1 "k8s.io/api/authentication/v1"

"github.com/SAP/sap-btp-service-operator/api/common"
"github.com/SAP/sap-btp-service-operator/internal/utils"
"k8s.io/utils/pointer"
Expand Down Expand Up @@ -641,6 +643,18 @@ var _ = Describe("ServiceBinding controller", func() {
Expect(err.Error()).To(ContainSubstring("updating service bindings is not supported"))
})
})

When("UserInfo changed", func() {
It("should fail", func() {
createdBinding.Spec.UserInfo = &authv1.UserInfo{
Username: "aaa",
UID: "111",
}
err := k8sClient.Update(ctx, createdBinding)
Expect(err).To(HaveOccurred())
Expect(err.Error()).To(ContainSubstring("updating service bindings is not supported"))
})
})
})

Context("Delete", func() {
Expand Down
14 changes: 14 additions & 0 deletions controllers/serviceinstance_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import (
"net/http"
"strings"

authv1 "k8s.io/api/authentication/v1"

"github.com/SAP/sap-btp-service-operator/api/common"
v1 "github.com/SAP/sap-btp-service-operator/api/v1"
"github.com/SAP/sap-btp-service-operator/client/sm"
Expand Down Expand Up @@ -616,6 +618,18 @@ var _ = Describe("ServiceInstance controller", func() {
Expect(err.Error()).To(ContainSubstring("changing the btpAccessCredentialsSecret for an existing instance is not allowed"))
})
})

When("UserInfo changed", func() {
It("should fail", func() {
serviceInstance.Spec.UserInfo = &authv1.UserInfo{
Username: "a",
UID: "123",
}
err := k8sClient.Update(ctx, serviceInstance)
Expect(err).To(HaveOccurred())
Expect(err.Error()).To(ContainSubstring("modifying spec.userInfo is not allowed"))
})
})
})

Describe("Delete", func() {
Expand Down

0 comments on commit bb925b0

Please sign in to comment.