Skip to content

Commit 53bc2b6

Browse files
authored
Merge pull request #98 from SAP/issue/90
2 parents 8742581 + 9530ebc commit 53bc2b6

2 files changed

Lines changed: 40 additions & 26 deletions

File tree

internal/controller/serviceinstance/controller.go

Lines changed: 34 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,13 @@
11
package serviceinstance
22

33
import (
4+
"bytes"
45
"context"
6+
"crypto/sha256"
57
"encoding/json"
68
"time"
79

810
"github.com/cloudfoundry/go-cfclient/v3/client"
9-
"github.com/nsf/jsondiff"
10-
"github.com/pkg/errors"
11-
12-
ctrl "sigs.k8s.io/controller-runtime"
13-
k8s "sigs.k8s.io/controller-runtime/pkg/client"
14-
1511
xpv1 "github.com/crossplane/crossplane-runtime/apis/common/v1"
1612
"github.com/crossplane/crossplane-runtime/pkg/connection"
1713
"github.com/crossplane/crossplane-runtime/pkg/controller"
@@ -20,6 +16,10 @@ import (
2016
"github.com/crossplane/crossplane-runtime/pkg/ratelimiter"
2117
"github.com/crossplane/crossplane-runtime/pkg/reconciler/managed"
2218
"github.com/crossplane/crossplane-runtime/pkg/resource"
19+
"github.com/nsf/jsondiff"
20+
"github.com/pkg/errors"
21+
ctrl "sigs.k8s.io/controller-runtime"
22+
k8s "sigs.k8s.io/controller-runtime/pkg/client"
2323

2424
"github.com/SAP/crossplane-provider-cloudfoundry/apis/resources/v1alpha1"
2525
apisv1alpha1 "github.com/SAP/crossplane-provider-cloudfoundry/apis/v1alpha1"
@@ -175,21 +175,29 @@ func (c *external) Observe(ctx context.Context, mg resource.Managed) (managed.Ex
175175
case v1alpha1.LastOperationSucceeded:
176176
// If the last operation succeeded, set the CR to available
177177
cr.SetConditions(xpv1.Available())
178+
var credentialsUpToDate bool
179+
desiredCredentials, err := extractCredentialSpec(ctx, c.kube, cr.Spec.ForProvider)
180+
if err != nil {
181+
return managed.ExternalObservation{}, errors.Wrap(err, errSecret)
182+
}
178183
// If parameter drift detection is enable, get actual credentials from the service instance
179184
if cr.Spec.EnableParameterDriftDetection {
180185
// Get the parameters of the service instance for drift detection
181186
cred, err := c.serviceinstance.GetServiceCredentials(ctx, r)
182187
if err != nil {
183188
return managed.ExternalObservation{ResourceExists: true}, errors.Wrap(err, errGetParameters)
184189
}
185-
cr.Status.AtProvider.Credentials = cred
190+
cr.Status.AtProvider.Credentials = iSha256(cred)
191+
192+
credentialsUpToDate = jsonContain(cred, desiredCredentials)
193+
} else {
194+
desiredHash := iSha256(desiredCredentials)
195+
196+
credentialsUpToDate = bytes.Equal(desiredHash, cr.Status.AtProvider.Credentials)
186197
}
198+
187199
// Check if the credentials in the spec match the credentials in the external resource
188-
desiredCredentials, err := extractCredentialSpec(ctx, c.kube, cr.Spec.ForProvider)
189-
if err != nil {
190-
return managed.ExternalObservation{}, errors.Wrap(err, errSecret)
191-
}
192-
upToDate := serviceinstance.IsUpToDate(&cr.Spec.ForProvider, r) && jsonContain(cr.Status.AtProvider.Credentials, desiredCredentials)
200+
upToDate := credentialsUpToDate && serviceinstance.IsUpToDate(&cr.Spec.ForProvider, r)
193201

194202
return managed.ExternalObservation{ResourceExists: true, ResourceUpToDate: upToDate}, nil
195203
default:
@@ -236,8 +244,8 @@ func (c *external) Create(ctx context.Context, mg resource.Managed) (managed.Ext
236244
return managed.ExternalCreation{}, errors.Wrap(err, errUpdateCR)
237245
}
238246

239-
// Save credentials in the status of the CR
240-
cr.Status.AtProvider.Credentials = creds
247+
// Save hash value of credentials in the status of the CR
248+
cr.Status.AtProvider.Credentials = iSha256(creds)
241249
if err = c.kube.Status().Update(ctx, cr); err != nil {
242250
return managed.ExternalCreation{}, errors.Wrap(err, errUpdateCR)
243251
}
@@ -265,13 +273,8 @@ func (c *external) Update(ctx context.Context, mg resource.Managed) (managed.Ext
265273
return managed.ExternalUpdate{}, errors.Wrap(err, errUpdate)
266274
}
267275

268-
if err := c.kube.Update(ctx, cr); err != nil {
269-
return managed.ExternalUpdate{}, errors.Wrap(err, errUpdateCR)
270-
}
271-
272-
// Save credentials in the status of the CR
273276
if creds != nil {
274-
cr.Status.AtProvider.Credentials = creds
277+
cr.Status.AtProvider.Credentials = iSha256(creds)
275278
if err := c.kube.Status().Update(ctx, cr); err != nil {
276279
return managed.ExternalUpdate{}, errors.Wrap(err, errUpdateCR)
277280
}
@@ -403,3 +406,14 @@ func (s servicePlanInitializer) Initialize(ctx context.Context, mg resource.Mana
403406

404407
return s.kube.Update(ctx, cr)
405408
}
409+
410+
// Small wrapper around sha256.Sum256()
411+
// info: if creds == nil, it will result in a hash value anyway (e3b0c44298...).
412+
// This should not be a security problem.
413+
func iSha256(data []byte) []byte {
414+
if len(data) == 0 || string(data) == "{}" {
415+
return nil
416+
}
417+
s := sha256.Sum256(data)
418+
return s[:]
419+
}

internal/controller/serviceinstance/controller_test.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -386,7 +386,7 @@ func TestObserve(t *testing.T) {
386386
mg: serviceInstance("managed",
387387
withExternalName(guid),
388388
withServicePlan(v1alpha1.ServicePlanParameters{ID: &servicePlan}),
389-
withStatus(v1alpha1.ServiceInstanceObservation{ID: &guid, ServicePlan: &servicePlan}),
389+
withStatus(v1alpha1.ServiceInstanceObservation{ID: &guid, ServicePlan: &servicePlan, Credentials: iSha256(*fake.JSONRawMessage("{\"foo\":\"bar\"}"))}),
390390
withConditions(xpv1.Available()),
391391
withParameters("{\"foo\":\"bar\", \"baz\": 1}"),
392392
withDriftDetection(true),
@@ -413,13 +413,13 @@ func TestObserve(t *testing.T) {
413413
},
414414
"DriftDetectionBreak": {
415415
args: args{
416-
mg: serviceInstance("managed", withExternalName(guid), withSpace(spaceGUID), withServicePlan(v1alpha1.ServicePlanParameters{ID: &servicePlan}), withParameters("{\"foo\":\"bar\", \"baz\": 1}"), withDriftDetection(false)),
416+
mg: serviceInstance("managed", withExternalName(guid), withSpace(spaceGUID), withServicePlan(v1alpha1.ServicePlanParameters{ID: &servicePlan}), withParameters("{\"foo\":\"bar\", \"baz\": 1}"), withDriftDetection(false), withStatus(v1alpha1.ServiceInstanceObservation{Credentials: iSha256([]byte("{\"foo\":\"bar\", \"baz\": 1}"))})),
417417
},
418418
want: want{
419419
mg: serviceInstance("managed",
420420
withExternalName(guid),
421421
withServicePlan(v1alpha1.ServicePlanParameters{ID: &servicePlan}),
422-
withStatus(v1alpha1.ServiceInstanceObservation{ID: &guid, ServicePlan: &servicePlan}),
422+
withStatus(v1alpha1.ServiceInstanceObservation{ID: &guid, ServicePlan: &servicePlan, Credentials: iSha256([]byte("{\"foo\":\"bar\", \"baz\": 1}"))}),
423423
withConditions(xpv1.Available()),
424424
withParameters("{\"foo\":\"bar\", \"baz\": 1}"),
425425
withDriftDetection(false),
@@ -532,7 +532,7 @@ func TestCreate(t *testing.T) {
532532
mg: serviceInstance("managed", withSpace(spaceGUID), withServicePlan(v1alpha1.ServicePlanParameters{ID: &servicePlan}), withCredentials(&jsonCredentials)),
533533
},
534534
want: want{
535-
mg: serviceInstance("managed", withSpace(spaceGUID), withServicePlan(v1alpha1.ServicePlanParameters{ID: &servicePlan}), withCredentials(&jsonCredentials), withConditions(xpv1.Creating()), withExternalName(guid), withStatus(v1alpha1.ServiceInstanceObservation{Credentials: []byte(jsonCredentials)})),
535+
mg: serviceInstance("managed", withSpace(spaceGUID), withServicePlan(v1alpha1.ServicePlanParameters{ID: &servicePlan}), withCredentials(&jsonCredentials), withConditions(xpv1.Creating()), withExternalName(guid), withStatus(v1alpha1.ServiceInstanceObservation{Credentials: iSha256([]byte(jsonCredentials))})),
536536
obs: managed.ExternalCreation{},
537537
err: nil,
538538
},
@@ -713,7 +713,7 @@ func TestUpdate(t *testing.T) {
713713
mg: serviceInstance("managed", withSpace(spaceGUID), withServicePlan(v1alpha1.ServicePlanParameters{ID: &servicePlan}), withExternalName(guid), withStatus(v1alpha1.ServiceInstanceObservation{ID: &guid}), withCredentials(&jsonCredentials)),
714714
},
715715
want: want{
716-
mg: serviceInstance("managed", withSpace(spaceGUID), withServicePlan(v1alpha1.ServicePlanParameters{ID: &servicePlan}), withCredentials(&jsonCredentials), withExternalName(guid), withStatus(v1alpha1.ServiceInstanceObservation{ID: &guid, Credentials: *fake.JSONRawMessage(jsonCredentials)})),
716+
mg: serviceInstance("managed", withSpace(spaceGUID), withServicePlan(v1alpha1.ServicePlanParameters{ID: &servicePlan}), withCredentials(&jsonCredentials), withExternalName(guid), withStatus(v1alpha1.ServiceInstanceObservation{ID: &guid, Credentials: iSha256([]byte(jsonCredentials))})),
717717
obs: managed.ExternalUpdate{},
718718
err: nil,
719719
},
@@ -894,7 +894,7 @@ func TestJSONContain(t *testing.T) {
894894
"Superset": {
895895
args: args{
896896
a: `{ "bar": 1, "baz": "baz", "foo":"foo"}`,
897-
b: `{"foo":"foo",
897+
b: `{"foo":"foo",
898898
"bar": 1}`,
899899
},
900900
want: want{

0 commit comments

Comments
 (0)