Skip to content

Commit

Permalink
[keyvault] CAE support (#31140)
Browse files Browse the repository at this point in the history
### Packages impacted by this PR

- `@azure/keyvault-common`
- Downstream Key Vault packages

### Issues associated with this PR

- Private

### Describe the problem that is addressed by this PR

In future, the Key Vault service will be adding support for Continuous
Access Evaluation (CAE). This PR adds the necessary support to the SDK's
challenge-based authentication policy to enable this feature.

After the initial challenge, with CAE enabled, any future request may
result in a 401 response, even if the access token used is valid. This
PR adds a new policy that handles this CAE challenge alongside the
normal challenge. The new policy replaces the existing use of Core's
`bearerTokenAuthenticationPolicy`, which is no longer suitable for this
use case since it cannot handle a CAE challenge that comes immediately
after a regular challenge.

### Are there test cases added in this PR? _(If not, why?)_

Yes, added test cases with mock requests and responses to cover a number
of different scenarios, ensuring the policy is doing the right thing.

I also manually tested against a test resource provided by the Key Vault
team which returns a CAE challenge in response to any authorized request
to the vault, and got the expected result (a normal challenge handled
successfully, followed by a CAE challenge handled successfully, followed
by another CAE challenge which the policy does not handle).

### Provide a list of related PRs _(if any)_

- Java PR for same feature:
Azure/azure-sdk-for-java#41814
  • Loading branch information
timovv authored Oct 8, 2024
1 parent 3a0deb8 commit dbc12ec
Show file tree
Hide file tree
Showing 37 changed files with 760 additions and 448 deletions.
4 changes: 3 additions & 1 deletion sdk/keyvault/keyvault-admin/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
# Release History

## 4.5.1 (Unreleased)
## 4.6.0 (Unreleased)

### Features Added

- Add support for Continuous Access Evaluation (CAE). [#31140](https://github.com/Azure/azure-sdk-for-js/pull/31140)

### Breaking Changes

### Bugs Fixed
Expand Down
4 changes: 2 additions & 2 deletions sdk/keyvault/keyvault-admin/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "@azure/keyvault-admin",
"sdk-type": "client",
"author": "Microsoft Corporation",
"version": "4.5.1",
"version": "4.6.0",
"license": "MIT",
"description": "Isomorphic client library for Azure KeyVault's administrative functions.",
"homepage": "https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/keyvault/keyvault-admin/README.md",
Expand Down Expand Up @@ -99,7 +99,7 @@
"@azure/core-rest-pipeline": "^1.1.0",
"@azure/core-tracing": "^1.0.0",
"@azure/core-util": "^1.0.0",
"@azure/keyvault-common": "^1.0.0",
"@azure/keyvault-common": "^2.0.0",
"@azure/logger": "^1.0.0",
"tslib": "^2.2.0"
},
Expand Down
17 changes: 6 additions & 11 deletions sdk/keyvault/keyvault-admin/src/accessControlClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,7 @@ import { LATEST_API_VERSION } from "./constants.js";
import { PagedAsyncIterableIterator } from "@azure/core-paging";
import { RoleAssignmentsListForScopeOptionalParams } from "./generated/models/index.js";
import { TokenCredential } from "@azure/core-auth";
import { bearerTokenAuthenticationPolicy } from "@azure/core-rest-pipeline";
import { createKeyVaultChallengeCallbacks } from "@azure/keyvault-common";
import { keyVaultAuthenticationPolicy } from "@azure/keyvault-common";
import { logger } from "./log.js";
import { mappings } from "./mappings.js";
import { tracingClient } from "./tracing.js";
Expand Down Expand Up @@ -87,15 +86,11 @@ export class KeyVaultAccessControlClient {

this.client = new KeyVaultClient(serviceVersion, clientOptions);

this.client.pipeline.addPolicy(
bearerTokenAuthenticationPolicy({
credential,
// The scopes will be populated in the challenge callbacks based on the WWW-authenticate header
// returned by the challenge, so pass an empty array as a placeholder.
scopes: [],
challengeCallbacks: createKeyVaultChallengeCallbacks(options),
}),
);
// The authentication policy must come after the deserialization policy since the deserialization policy
// converts 401 responses to an Error, and we don't want to deal with that.
this.client.pipeline.addPolicy(keyVaultAuthenticationPolicy(credential, clientOptions), {
afterPolicies: ["deserializationPolicy"],
});
}

/**
Expand Down
17 changes: 6 additions & 11 deletions sdk/keyvault/keyvault-admin/src/backupClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,7 @@ import { KeyVaultSelectiveKeyRestorePoller } from "./lro/selectiveKeyRestore/pol
import { LATEST_API_VERSION } from "./constants.js";
import { PollerLike } from "@azure/core-lro";
import { TokenCredential } from "@azure/core-auth";
import { bearerTokenAuthenticationPolicy } from "@azure/core-rest-pipeline";
import { createKeyVaultChallengeCallbacks } from "@azure/keyvault-common";
import { keyVaultAuthenticationPolicy } from "@azure/keyvault-common";
import { logger } from "./log.js";
import { mappings } from "./mappings.js";

Expand Down Expand Up @@ -89,15 +88,11 @@ export class KeyVaultBackupClient {
};

this.client = new KeyVaultClient(apiVersion, clientOptions);
this.client.pipeline.addPolicy(
bearerTokenAuthenticationPolicy({
credential,
// The scopes will be populated in the challenge callbacks based on the WWW-authenticate header
// returned by the challenge, so pass an empty array as a placeholder.
scopes: [],
challengeCallbacks: createKeyVaultChallengeCallbacks(options),
}),
);
// The authentication policy must come after the deserialization policy since the deserialization policy
// converts 401 responses to an Error, and we don't want to deal with that.
this.client.pipeline.addPolicy(keyVaultAuthenticationPolicy(credential, clientOptions), {
afterPolicies: ["deserializationPolicy"],
});
}

/**
Expand Down
2 changes: 1 addition & 1 deletion sdk/keyvault/keyvault-admin/src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
/**
* Current version of the Key Vault Admin SDK.
*/
export const SDK_VERSION: string = "4.5.1";
export const SDK_VERSION: string = "4.6.0";

/**
* The latest supported Key Vault service API version.
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 7 additions & 9 deletions sdk/keyvault/keyvault-admin/src/settingsClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@
// Licensed under the MIT License.

import { TokenCredential } from "@azure/core-auth";
import { bearerTokenAuthenticationPolicy } from "@azure/core-rest-pipeline";
import { createKeyVaultChallengeCallbacks } from "@azure/keyvault-common";
import { keyVaultAuthenticationPolicy } from "@azure/keyvault-common";
import { LATEST_API_VERSION } from "./constants.js";
import { KeyVaultClient, Setting as GeneratedSetting } from "./generated/index.js";
import { logger } from "./log.js";
Expand Down Expand Up @@ -92,13 +91,12 @@ export class KeyVaultSettingsClient {
};

this.client = new KeyVaultClient(apiVersion, clientOptions);
this.client.pipeline.addPolicy(
bearerTokenAuthenticationPolicy({
credential,
scopes: [],
challengeCallbacks: createKeyVaultChallengeCallbacks(options),
}),
);

// The authentication policy must come after the deserialization policy since the deserialization policy
// converts 401 responses to an Error, and we don't want to deal with that.
this.client.pipeline.addPolicy(keyVaultAuthenticationPolicy(credential, clientOptions), {
afterPolicies: ["deserializationPolicy"],
});
}

/**
Expand Down
2 changes: 1 addition & 1 deletion sdk/keyvault/keyvault-admin/swagger/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ input-file:
- https://raw.githubusercontent.com/Azure/azure-rest-api-specs/7452e1cc7db72fbc6cd9539b390d8b8e5c2a1864/specification/keyvault/data-plane/Microsoft.KeyVault/stable/7.5/settings.json
output-folder: ../
source-code-folder-path: ./src/generated
package-version: 4.5.1
package-version: 4.6.0
use-extension:
"@autorest/typescript": "6.0.0-beta.15"
```
Expand Down
4 changes: 3 additions & 1 deletion sdk/keyvault/keyvault-certificates/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
# Release History

## 4.8.1 (Unreleased)
## 4.9.0 (Unreleased)

### Features Added

- Add support for Continuous Access Evaluation (CAE). [#31140](https://github.com/Azure/azure-sdk-for-js/pull/31140)

### Breaking Changes

### Bugs Fixed
Expand Down
4 changes: 2 additions & 2 deletions sdk/keyvault/keyvault-certificates/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "@azure/keyvault-certificates",
"sdk-type": "client",
"author": "Microsoft Corporation",
"version": "4.8.1",
"version": "4.9.0",
"license": "MIT",
"description": "Isomorphic client library for Azure KeyVault's certificates.",
"homepage": "https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/keyvault/keyvault-certificates/README.md",
Expand Down Expand Up @@ -103,7 +103,7 @@
"@azure/core-rest-pipeline": "^1.8.0",
"@azure/core-tracing": "^1.0.0",
"@azure/core-util": "^1.6.1",
"@azure/keyvault-common": "^1.0.0",
"@azure/keyvault-common": "^2.0.0",
"@azure/logger": "^1.0.0",
"tslib": "^2.2.0"
},
Expand Down
2 changes: 1 addition & 1 deletion sdk/keyvault/keyvault-certificates/src/constants.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

export const SDK_VERSION: string = "4.8.1";
export const SDK_VERSION: string = "4.9.0";

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 7 additions & 9 deletions sdk/keyvault/keyvault-certificates/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
/// <reference lib="esnext.asynciterable" />

import { InternalClientPipelineOptions } from "@azure/core-client";
import { bearerTokenAuthenticationPolicy } from "@azure/core-rest-pipeline";

import { TokenCredential } from "@azure/core-auth";

Expand Down Expand Up @@ -100,7 +99,7 @@ import {
} from "./generated/models/index.js";
import { KeyVaultClient } from "./generated/keyVaultClient.js";
import { PageSettings, PagedAsyncIterableIterator } from "@azure/core-paging";
import { createKeyVaultChallengeCallbacks } from "@azure/keyvault-common";
import { keyVaultAuthenticationPolicy } from "@azure/keyvault-common";
import { CreateCertificatePoller } from "./lro/create/poller.js";
import { CertificateOperationPoller } from "./lro/operation/poller.js";
import { DeleteCertificatePoller } from "./lro/delete/poller.js";
Expand Down Expand Up @@ -247,12 +246,6 @@ export class CertificateClient {
) {
this.vaultUrl = vaultUrl;

const authPolicy = bearerTokenAuthenticationPolicy({
credential,
scopes: [],
challengeCallbacks: createKeyVaultChallengeCallbacks(clientOptions),
});

const internalClientPipelineOptions: InternalClientPipelineOptions = {
...clientOptions,
loggingOptions: {
Expand All @@ -269,7 +262,12 @@ export class CertificateClient {
clientOptions.serviceVersion || LATEST_API_VERSION,
internalClientPipelineOptions,
);
this.client.pipeline.addPolicy(authPolicy);

// The authentication policy must come after the deserialization policy since the deserialization policy
// converts 401 responses to an Error, and we don't want to deal with that.
this.client.pipeline.addPolicy(keyVaultAuthenticationPolicy(credential, clientOptions), {
afterPolicies: ["deserializationPolicy"],
});
}

private async *listPropertiesOfCertificatesPage(
Expand Down
2 changes: 1 addition & 1 deletion sdk/keyvault/keyvault-certificates/swagger/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ input-file: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/7452e1c
output-folder: ../
source-code-folder-path: ./src/generated
hide-clients: true
package-version: 4.8.1
package-version: 4.9.0
openapi-type: data-plane
```
Expand Down
7 changes: 6 additions & 1 deletion sdk/keyvault/keyvault-common/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
# Release History

## 1.0.1 (Unreleased)
## 2.0.0 (Unreleased)

### Features Added

- Add support for Continuous Access Evaluation (CAE).
- To take advantage of this support, the newly added `keyVaultAuthenticationPolicy` should be used in place of `bearerTokenAuthenticationPolicy`.

### Breaking Changes

- Removed `createKeyVaultChallengeCallbacks`, which was used to add Key Vault specific handling to Core's `bearerTokenAuthenticationPolicy`. The new `keyVaultAuthenticationPolicy` should be used instead.

### Bugs Fixed

### Other Changes
Expand Down
6 changes: 4 additions & 2 deletions sdk/keyvault/keyvault-common/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@azure/keyvault-common",
"version": "1.0.1",
"version": "2.0.0",
"description": "Common internal functionality for all of the Azure Key Vault clients in the Azure SDK for JavaScript",
"sdk-type": "client",
"author": "Microsoft Corporation",
Expand Down Expand Up @@ -59,7 +59,9 @@
"@azure/core-client": "^1.5.0",
"@azure/core-rest-pipeline": "^1.8.0",
"@azure/core-tracing": "^1.0.0",
"tslib": "^2.2.0"
"@azure/logger": "^1.1.5",
"tslib": "^2.2.0",
"@azure/core-util": "^1.10.1"
},
"devDependencies": {
"@azure-tools/test-utils-vitest": "^1.0.0",
Expand Down
14 changes: 9 additions & 5 deletions sdk/keyvault/keyvault-common/review/keyvault-common.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,19 @@
```ts

import { ChallengeCallbacks } from '@azure/core-rest-pipeline';
import { PipelinePolicy } from '@azure/core-rest-pipeline';
import { TokenCredential } from '@azure/core-auth';

// @public
export interface CreateChallengeCallbacksOptions {
disableChallengeResourceVerification?: boolean;
}
export function keyVaultAuthenticationPolicy(credential: TokenCredential, options?: KeyVaultAuthenticationPolicyOptions): PipelinePolicy;

// @public
export const keyVaultAuthenticationPolicyName = "keyVaultAuthenticationPolicy";

// @public
export function createKeyVaultChallengeCallbacks(options?: CreateChallengeCallbacksOptions): ChallengeCallbacks;
export interface KeyVaultAuthenticationPolicyOptions {
disableChallengeResourceVerification?: boolean;
}

// @public
export interface KeyVaultEntityIdentifier {
Expand Down
2 changes: 1 addition & 1 deletion sdk/keyvault/keyvault-common/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

export * from "./challengeBasedAuthenticationPolicy.js";
export * from "./keyVaultAuthenticationPolicy.js";
export * from "./parseKeyVaultIdentifier.js";
Loading

0 comments on commit dbc12ec

Please sign in to comment.