Skip to content

Commit 83422cb

Browse files
Merge pull request #581 from fmount/pwd_validation
Move to VerifySecretFields to reject invalid passwords
2 parents 942777d + 2fa1733 commit 83422cb

File tree

3 files changed

+57
-22
lines changed

3 files changed

+57
-22
lines changed

internal/controller/octavia_controller.go

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -338,38 +338,32 @@ func (r *OctaviaReconciler) reconcileInit(
338338
//
339339
// check for required OpenStack secret holding passwords for service/admin user and add hash to the vars map
340340
//
341-
ospSecretHash, result, err := oko_secret.VerifySecret(
341+
// Associate to PasswordSelectors.Service field a password validator to
342+
// ensure pwd invalid detected patterns are rejected.
343+
validateFields := map[string]oko_secret.Validator{
344+
instance.Spec.PasswordSelectors.Service: oko_secret.PasswordValidator{},
345+
}
346+
ospSecretHash, result, err := oko_secret.VerifySecretFields(
342347
ctx,
343-
types.NamespacedName{Namespace: instance.Namespace, Name: instance.Spec.Secret},
344-
[]string{instance.Spec.PasswordSelectors.Service},
348+
types.NamespacedName{
349+
Namespace: instance.Namespace,
350+
Name: instance.Spec.Secret,
351+
},
352+
validateFields,
345353
helper.GetClient(),
346354
time.Duration(10)*time.Second,
347355
)
348-
349356
if err != nil {
350-
if k8s_errors.IsNotFound(err) {
351-
// Since the OpenStack secret should have been manually created by the user and referenced in the spec,
352-
// we treat this as a warning because it means that the service will not be able to start.
353-
Log.Info(fmt.Sprintf("OpenStack secret %s not found", instance.Spec.Secret))
354-
instance.Status.Conditions.Set(condition.FalseCondition(
355-
condition.InputReadyCondition,
356-
condition.ErrorReason,
357-
condition.SeverityWarning,
358-
condition.InputReadyWaitingMessage))
359-
return ctrl.Result{RequeueAfter: time.Second * 10}, nil
360-
}
361357
instance.Status.Conditions.Set(condition.FalseCondition(
362358
condition.InputReadyCondition,
363359
condition.ErrorReason,
364360
condition.SeverityWarning,
365361
condition.InputReadyErrorMessage,
366362
err.Error()))
367-
return ctrl.Result{}, err
363+
return result, err
368364
} else if (result != ctrl.Result{}) {
369-
// We can only get here if the secret is not found, thus we treat this the same
370-
// as we do above if there was an actual "not found" error returned.
371-
// See https://github.com/openstack-k8s-operators/lib-common/blob/4c240245107747327c5f67256f8d9d76cdd25c7a/modules/common/secret/secret.go#L423-L428
372-
// for further details.
365+
// Since the OpenStack secret should have been manually created by the user and referenced in the spec,
366+
// we treat this as a warning because it means that the service will not be able to start.
373367
instance.Status.Conditions.Set(condition.FalseCondition(
374368
condition.InputReadyCondition,
375369
condition.ErrorReason,
@@ -379,10 +373,16 @@ func (r *OctaviaReconciler) reconcileInit(
379373
}
380374
secretsVars[instance.Spec.Secret] = env.SetValue(ospSecretHash)
381375

382-
transportURLSecretHash, result, err := oko_secret.VerifySecret(
376+
// transportURLFields are not pure password fields. We do not associate a
377+
// password validator and we only verify that the entry exists in the
378+
// secret
379+
transportValidateFields := map[string]oko_secret.Validator{
380+
"transport_url": oko_secret.NoOpValidator{},
381+
}
382+
transportURLSecretHash, result, err := oko_secret.VerifySecretFields(
383383
ctx,
384384
types.NamespacedName{Namespace: instance.Namespace, Name: instance.Status.TransportURLSecret},
385-
[]string{"transport_url"},
385+
transportValidateFields,
386386
helper.GetClient(),
387387
time.Duration(10)*time.Second,
388388
)

test/functional/base_test.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -311,3 +311,13 @@ func CreateSSHPubKey() client.Object {
311311
"key": "public key",
312312
})
313313
}
314+
315+
// CreateOctaviaInvalidSecret creates a secret with an invalid password for testing
316+
func CreateOctaviaInvalidSecret(namespace string, name string) *corev1.Secret {
317+
return th.CreateSecret(
318+
types.NamespacedName{Namespace: namespace, Name: name},
319+
map[string][]byte{
320+
"OctaviaPassword": []byte("c^sometext02%text%text02$someText&"),
321+
},
322+
)
323+
}

test/functional/octavia_controller_test.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,31 @@ var _ = Describe("Octavia controller", func() {
218218
})
219219
})
220220

221+
// An invalid password is provided
222+
When("An Octavia instance is created with an invalid password", func() {
223+
BeforeEach(func() {
224+
// Create the secret containing the wrong password with the expected secret name
225+
DeferCleanup(k8sClient.Delete, ctx,
226+
CreateOctaviaInvalidSecret(namespace, "invalid-osp-secret"))
227+
spec = GetDefaultOctaviaSpec()
228+
spec["secret"] = "invalid-osp-secret"
229+
DeferCleanup(th.DeleteInstance, CreateOctavia(octaviaName, spec))
230+
createAndSimulateOctaviaSecrets(octaviaName)
231+
createAndSimulateTransportURL(transportURLName, transportURLSecretName)
232+
createAndSimulateKeystone(octaviaName)
233+
})
234+
It("rejects the password and reports InputReadyCondition as False", func() {
235+
expectedErrMsg := "Input data error occurred password does not meet the requirements"
236+
th.ExpectConditionWithDetails(
237+
octaviaName,
238+
ConditionGetterFunc(OctaviaConditionGetter),
239+
condition.InputReadyCondition,
240+
corev1.ConditionFalse,
241+
condition.ErrorReason,
242+
expectedErrMsg,
243+
)
244+
})
245+
})
221246
// TransportURL
222247
When("a proper secret is provider, TransportURL is created", func() {
223248
BeforeEach(func() {

0 commit comments

Comments
 (0)