Skip to content

[BUG] Key Vault secret versions no longer list if at least one version is disabled #1069

Description

@paulojohnj

Describe the bug
When listing key vault secret versions, the list of versions fails to be retrieved if at least one of the version has been marked as disbabled

Exception or Stack Trace

OnErrorFailedException with message: null
rx.exceptions.OnErrorFailedException: null
at rx.observers.SafeSubscriber._onError(SafeSubscriber.java:194)
at rx.observers.SafeSubscriber.onError(SafeSubscriber.java:115)
at rx.internal.operators.OnSubscribeMap$MapSubscriber.onError(OnSubscribeMap.java:88)
at rx.internal.operators.OperatorMerge$MergeSubscriber.reportError(OperatorMerge.java:266)
at rx.internal.operators.OperatorMerge$MergeSubscriber.checkTerminate(OperatorMerge.java:818)
at rx.internal.operators.OperatorMerge$MergeSubscriber.emitLoop(OperatorMerge.java:579)
at rx.internal.operators.OperatorMerge$MergeSubscriber.emit(OperatorMerge.java:568)
at rx.internal.operators.OperatorMerge$InnerSubscriber.onError(OperatorMerge.java:855)
at rx.observers.Subscribers$5.onError(Subscribers.java:230)
at rx.exceptions.Exceptions.throwOrReport(Exceptions.java:212)
at rx.internal.operators.OnSubscribeToObservableFuture$ToObservableFuture.call(OnSubscribeToObservableFuture.java:86)
at rx.internal.operators.OnSubscribeToObservableFuture$ToObservableFuture.call(OnSubscribeToObservableFuture.java:43)
at rx.Observable.unsafeSubscribe(Observable.java:10327)
at rx.internal.operators.OnSubscribeDefer.call(OnSubscribeDefer.java:51)
at rx.internal.operators.OnSubscribeDefer.call(OnSubscribeDefer.java:35)
at rx.Observable.unsafeSubscribe(Observable.java:10327)
at rx.internal.operators.OperatorMerge$MergeSubscriber.onNext(OperatorMerge.java:248)
at rx.internal.operators.OperatorMerge$MergeSubscriber.onNext(OperatorMerge.java:148)
at rx.internal.operators.OnSubscribeMap$MapSubscriber.onNext(OnSubscribeMap.java:77)
at rx.internal.operators.OnSubscribeFilter$FilterSubscriber.onNext(OnSubscribeFilter.java:76)
at rx.internal.operators.OnSubscribeFromIterable$IterableProducer.fastPath(OnSubscribeFromIterable.java:173)
at rx.internal.operators.OnSubscribeFromIterable$IterableProducer.request(OnSubscribeFromIterable.java:86)
at rx.Subscriber.setProducer(Subscriber.java:211)
at rx.internal.operators.OnSubscribeMap$MapSubscriber.setProducer(OnSubscribeMap.java:102)
at rx.internal.operators.OnSubscribeFilter$FilterSubscriber.setProducer(OnSubscribeFilter.java:104)
at rx.internal.operators.OnSubscribeFromIterable.call(OnSubscribeFromIterable.java:63)
at rx.internal.operators.OnSubscribeFromIterable.call(OnSubscribeFromIterable.java:34)
at rx.Observable.unsafeSubscribe(Observable.java:10327)
at rx.internal.operators.OnSubscribeFilter.call(OnSubscribeFilter.java:45)
at rx.internal.operators.OnSubscribeFilter.call(OnSubscribeFilter.java:30)
at rx.Observable.unsafeSubscribe(Observable.java:10327)
at rx.internal.operators.OnSubscribeMap.call(OnSubscribeMap.java:48)
at rx.internal.operators.OnSubscribeMap.call(OnSubscribeMap.java:33)
at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:48)
at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:30)
at rx.Observable.unsafeSubscribe(Observable.java:10327)
at rx.internal.operators.OnSubscribeMap.call(OnSubscribeMap.java:48)
at rx.internal.operators.OnSubscribeMap.call(OnSubscribeMap.java:33)
at rx.Observable.subscribe(Observable.java:10423)
at rx.Observable.subscribe(Observable.java:10390)
at rx.observables.BlockingObservable.subscribe(BlockingObservable.java:477)
at com.microsoft.azure.management.resources.fluentcore.utils.PagedListConverter.loadConvertedList(PagedListConverter.java:100)
at com.microsoft.azure.management.resources.fluentcore.utils.PagedListConverter.convert(PagedListConverter.java:66)
at com.microsoft.azure.management.keyvault.implementation.SecretImpl.listVersions(SecretImpl.java:109)
at com.cons3rt.fap.virtualization.adapter.azure.AzureSharedTests.disableOldestKey(AzureSharedTests.java:151)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)
at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:89)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:41)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:541)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:763)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:463)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:209)
Caused by: java.lang.NullPointerException: null
at com.microsoft.rest.ServiceFuture.cancel(ServiceFuture.java:208)
at rx.internal.operators.OnSubscribeToObservableFuture$ToObservableFuture$1.call(OnSubscribeToObservableFuture.java:66)
at rx.subscriptions.BooleanSubscription.unsubscribe(BooleanSubscription.java:71)
at rx.internal.util.SubscriptionList.unsubscribeFromAll(SubscriptionList.java:136)
at rx.internal.util.SubscriptionList.unsubscribe(SubscriptionList.java:125)
at rx.Subscriber.unsubscribe(Subscriber.java:98)
at rx.subscriptions.CompositeSubscription.unsubscribeFromAll(CompositeSubscription.java:186)
at rx.subscriptions.CompositeSubscription.unsubscribe(CompositeSubscription.java:175)
at rx.internal.util.SubscriptionList.unsubscribeFromAll(SubscriptionList.java:136)
at rx.internal.util.SubscriptionList.unsubscribe(SubscriptionList.java:125)
at rx.Subscriber.unsubscribe(Subscriber.java:98)
at rx.internal.util.SubscriptionList.unsubscribeFromAll(SubscriptionList.java:136)
at rx.internal.util.SubscriptionList.unsubscribe(SubscriptionList.java:125)
at rx.Subscriber.unsubscribe(Subscriber.java:98)
at rx.internal.util.SubscriptionList.unsubscribeFromAll(SubscriptionList.java:136)
at rx.internal.util.SubscriptionList.unsubscribe(SubscriptionList.java:125)
at rx.Subscriber.unsubscribe(Subscriber.java:98)
at rx.observers.SafeSubscriber._onError(SafeSubscriber.java:191)
... 70 common frames omitted

To Reproduce
Steps to reproduce the behavior:

Create key vault

  • create secret in vault
  • create multiple versions of secret
  • disable one of the versions
  • attempt to list versions of the secret

Code Snippet

final Vault vault = adapter.getItsAzure().vaults().getByResourceGroup(resourceGroupName, vaultName);

        final Secret secret = vault.secrets().getByName(secretName);
        LOGGER.info("secret: {}", secret.value());

        LOGGER.info("Fetching versions");
        final PagedList<Secret> versions = secret.listVersions();
        LOGGER.info("Versions fetched");
        versions.loadAll();
        LOGGER.info("All fetched");

        final Set<Secret> enabledSecrets = versions.stream().filter(s -> s.attributes().enabled()).collect(Collectors.toSet());

        if (enabledSecrets.size() > 1) {
            final Secret oldest = enabledSecrets.stream().sorted(AzureComparators.getOldestSecret()).findFirst().get();

            LOGGER.info("Oldest secret found to be: {} - id: {} disabling", oldest.name(), oldest.id());

            final SecretAttributes attributes = oldest.attributes();
            attributes.withEnabled(false);

            vault.client().updateSecret(new UpdateSecretRequest.Builder(oldest.id()).withAttributes(attributes).build());

            LOGGER.info("Disabled");
        } else {
            LOGGER.warn("There are only {} enabled secrets", enabledSecrets.size());
        }
    } catch (Exception e) {
        LOGGER.warn("caught: {} with message: {}", e.getClass().getSimpleName(), e.getMessage(), e);
    }

Expected behavior
I would expect the list of versions to be returned with the attributes of the disabled secret version to be set to enabled=false

Screenshots
If applicable, add screenshots to help explain your problem.

Setup (please complete the following information):

  • OS: [e.g. iOS]
  • IDE : [e.g. IntelliJ]
  • Version of the Library used

Additional context
Sidenote: in order to update a secret's attributes I had to use an alternative path to the secret.update().withAttributes(attributes).apply() than I would expect as this lead to an npe, due to the createRequest in the impl being null when requesting an update.

Information Checklist
Kindly make sure that you have added all the following information above and checkoff the required fields otherwise we will treat the issuer as an incomplete report

  • Bug Description Added
  • Repro Steps Added
  • Setup information Added

Metadata

Metadata

Assignees

Labels

Type

No type

Fields

No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions