diff --git a/sdk/containerregistry/container-registry/CHANGELOG.md b/sdk/containerregistry/container-registry/CHANGELOG.md index a8a2086b49e8..b14e9b3c29d4 100644 --- a/sdk/containerregistry/container-registry/CHANGELOG.md +++ b/sdk/containerregistry/container-registry/CHANGELOG.md @@ -6,6 +6,8 @@ ### Breaking Changes +- Replace `authenticationScope` with `audience` in `ContainerRegistryClientOptions`. An extensible enum `KnownContainerRegistryAudience` is introduced which has known audience values. + ### Bugs Fixed ### Other Changes diff --git a/sdk/containerregistry/container-registry/README.md b/sdk/containerregistry/container-registry/README.md index 27a0375e7882..a38c15010bb6 100644 --- a/sdk/containerregistry/container-registry/README.md +++ b/sdk/containerregistry/container-registry/README.md @@ -59,12 +59,17 @@ To use this client library in the browser, first you need to use a bundler. For The [Azure Identity library][identity] provides easy Azure Active Directory support for authentication. ```javascript -const { ContainerRegistryClient } = require("@azure/container-registry"); +const { + ContainerRegistryClient, + KnownContainerRegistryAudience +} = require("@azure/container-registry"); const { DefaultAzureCredential } = require("@azure/identity"); const endpoint = process.env.CONTAINER_REGISTRY_ENDPOINT; // Create a ContainerRegistryClient that will authenticate through Active Directory -const client = new ContainerRegistryClient(endpoint, new DefaultAzureCredential()); +const client = new ContainerRegistryClient(endpoint, new DefaultAzureCredential(), { + audience: KnownContainerRegistryAudience.AzureResourceManagerPublicCloud +}); ``` Note that these samples assume you have a `CONTAINER_REGISTRY_ENDPOINT` environment variable set, which is the URL including the name of the login server and the `https://` prefix. @@ -74,10 +79,13 @@ Note that these samples assume you have a `CONTAINER_REGISTRY_ENDPOINT` environm To authenticate with a registry in a [National Cloud](https://docs.microsoft.com/azure/active-directory/develop/authentication-national-cloud), you will need to make the following additions to your configuration: - Set the `authorityHost` in the credential options or via the `AZURE_AUTHORITY_HOST` environment variable -- Set the `authenticationScope` in `ContainerRegistryClientOptions` +- Set the `audience` in `ContainerRegistryClientOptions` ```javascript -const { ContainerRegistryClient } = require("@azure/container-registry"); +const { + ContainerRegistryClient, + KnownContainerRegistryAudience +} = require("@azure/container-registry"); const { DefaultAzureCredential, AzureAuthorityHosts } = require("@azure/identity"); const endpoint = process.env.CONTAINER_REGISTRY_ENDPOINT; @@ -86,7 +94,7 @@ const client = new ContainerRegistryClient( endpoint, new DefaultAzureCredential({ authorityHost: AzureAuthorityHosts.AzureChina }), { - authenticationScope: "https://management.chinacloudapi.cn/.default" + audience: KnownContainerRegistryAudience.AzureResourceManagerChina } ); ``` @@ -106,14 +114,19 @@ For more information please see [Container Registry Concepts](https://docs.micro Iterate through the collection of repositories in the registry. ```javascript -const { ContainerRegistryClient } = require("@azure/container-registry"); +const { + ContainerRegistryClient, + KnownContainerRegistryAudience +} = require("@azure/container-registry"); const { DefaultAzureCredential } = require("@azure/identity"); async function main() { // endpoint should be in the form of "https://myregistryname.azurecr.io" // where "myregistryname" is the actual name of your registry const endpoint = process.env.CONTAINER_REGISTRY_ENDPOINT || ""; - const client = new ContainerRegistryClient(endpoint, new DefaultAzureCredential()); + const client = new ContainerRegistryClient(endpoint, new DefaultAzureCredential(), { + audience: KnownContainerRegistryAudience.AzureResourceManagerPublicCloud + }); console.log("Listing repositories"); const iterator = client.listRepositoryNames(); @@ -130,14 +143,19 @@ main().catch((err) => { ### List tags with anonymous access ```javascript -const { ContainerRegistryClient } = require("@azure/container-registry"); +const { + ContainerRegistryClient, + KnownContainerRegistryAudience +} = require("@azure/container-registry"); async function main() { // Get the service endpoint from the environment const endpoint = process.env.CONTAINER_REGISTRY_ENDPOINT || ""; // Create a new ContainerRegistryClient for anonymous access - const client = new ContainerRegistryClient(endpoint); + const client = new ContainerRegistryClient(endpoint, { + audience: KnownContainerRegistryAudience.AzureResourceManagerPublicCloud + }); // Obtain a RegistryArtifact object to get access to image operations const image = client.getArtifact("library/hello-world", "latest"); @@ -160,7 +178,10 @@ main().catch((err) => { ### Set artifact properties ```javascript -const { ContainerRegistryClient } = require("@azure/container-registry"); +const { + ContainerRegistryClient, + KnownContainerRegistryAudience +} = require("@azure/container-registry"); const { DefaultAzureCredential } = require("@azure/identity"); async function main() { @@ -168,7 +189,9 @@ async function main() { const endpoint = process.env.CONTAINER_REGISTRY_ENDPOINT || ""; // Create a new ContainerRegistryClient and RegistryArtifact to access image operations - const client = new ContainerRegistryClient(endpoint, new DefaultAzureCredential()); + const client = new ContainerRegistryClient(endpoint, new DefaultAzureCredential(), { + audience: KnownContainerRegistryAudience.AzureResourceManagerPublicCloud + }); const image = client.getArtifact("library/hello-world", "v1"); // Set permissions on the image's "latest" tag @@ -183,14 +206,19 @@ main().catch((err) => { ### Delete images ```javascript -const { ContainerRegistryClient } = require("@azure/container-registry"); +const { + ContainerRegistryClient, + KnownContainerRegistryAudience +} = require("@azure/container-registry"); const { DefaultAzureCredential } = require("@azure/identity"); async function main() { // Get the service endpoint from the environment const endpoint = process.env.CONTAINER_REGISTRY_ENDPOINT || ""; // Create a new ContainerRegistryClient - const client = new ContainerRegistryClient(endpoint, new DefaultAzureCredential()); + const client = new ContainerRegistryClient(endpoint, new DefaultAzureCredential(), { + audience: KnownContainerRegistryAudience.AzureResourceManagerPublicCloud + }); // Iterate through repositories const repositoryNames = client.listRepositoryNames(); diff --git a/sdk/containerregistry/container-registry/review/container-registry.api.md b/sdk/containerregistry/container-registry/review/container-registry.api.md index 31962b1508ce..742d081912be 100644 --- a/sdk/containerregistry/container-registry/review/container-registry.api.md +++ b/sdk/containerregistry/container-registry/review/container-registry.api.md @@ -61,7 +61,7 @@ export class ContainerRegistryClient { // @public export interface ContainerRegistryClientOptions extends PipelineOptions { - authenticationScope?: string; + audience?: string; } // @public @@ -149,6 +149,14 @@ export enum KnownArtifactOperatingSystem { Windows = "windows" } +// @public +export enum KnownContainerRegistryAudience { + AzureResourceManagerChina = "https://management.chinacloudapi.cn", + AzureResourceManagerGermany = "https://management.microsoftazure.de", + AzureResourceManagerGovernment = "https://management.usgovcloudapi.net", + AzureResourceManagerPublicCloud = "https://management.azure.com" +} + // @public export interface ListManifestPropertiesOptions extends OperationOptions { orderBy?: ManifestOrderBy; diff --git a/sdk/containerregistry/container-registry/samples-dev/anonymousListTags.ts b/sdk/containerregistry/container-registry/samples-dev/anonymousListTags.ts index 6edeff60e9d4..9a31bd1b1788 100644 --- a/sdk/containerregistry/container-registry/samples-dev/anonymousListTags.ts +++ b/sdk/containerregistry/container-registry/samples-dev/anonymousListTags.ts @@ -11,7 +11,7 @@ // in a public registry that belongs to someone else. In this case, the user would need to access // the registry anonymously. Anonymous access allows a user to list all the collections there, but // they wouldn't have permissions to modify or delete any of the images in the registry. -import { ContainerRegistryClient } from "@azure/container-registry"; +import { ContainerRegistryClient, KnownContainerRegistryAudience } from "@azure/container-registry"; import * as dotenv from "dotenv"; dotenv.config(); @@ -20,7 +20,9 @@ async function main() { const endpoint = process.env.CONTAINER_REGISTRY_ENDPOINT || ""; // Create a new ContainerRegistryClient for anonymous access - const client = new ContainerRegistryClient(endpoint); + const client = new ContainerRegistryClient(endpoint, { + audience: KnownContainerRegistryAudience.AzureResourceManagerPublicCloud + }); // Obtain a RegistryArtifact object to get access to image operations const image = client.getArtifact("library/hello-world", "latest"); diff --git a/sdk/containerregistry/container-registry/samples-dev/containerRegistryClient.ts b/sdk/containerregistry/container-registry/samples-dev/containerRegistryClient.ts index 27891c9a2a5e..70453919ce56 100644 --- a/sdk/containerregistry/container-registry/samples-dev/containerRegistryClient.ts +++ b/sdk/containerregistry/container-registry/samples-dev/containerRegistryClient.ts @@ -6,7 +6,7 @@ * @azsdk-weight 10 */ -import { ContainerRegistryClient } from "@azure/container-registry"; +import { ContainerRegistryClient, KnownContainerRegistryAudience } from "@azure/container-registry"; import { DefaultAzureCredential } from "@azure/identity"; import * as dotenv from "dotenv"; dotenv.config(); @@ -15,7 +15,9 @@ export async function main() { // endpoint should be in the form of "https://myregistryname.azurecr.io" // where "myregistryname" is the actual name of your registry const endpoint = process.env.CONTAINER_REGISTRY_ENDPOINT || ""; - const client = new ContainerRegistryClient(endpoint, new DefaultAzureCredential()); + const client = new ContainerRegistryClient(endpoint, new DefaultAzureCredential(), { + audience: KnownContainerRegistryAudience.AzureResourceManagerPublicCloud + }); await listRepositoryNames(client); // Advanced: listing by pages diff --git a/sdk/containerregistry/container-registry/samples-dev/deleteImages.ts b/sdk/containerregistry/container-registry/samples-dev/deleteImages.ts index 0551cdc67dac..25b12e8bd2c0 100644 --- a/sdk/containerregistry/container-registry/samples-dev/deleteImages.ts +++ b/sdk/containerregistry/container-registry/samples-dev/deleteImages.ts @@ -9,7 +9,7 @@ // A common use case for Azure Container Registries is to scan the repositories // in a registry and delete all but the most recent n images, or all images // older than a certain date. -import { ContainerRegistryClient } from "@azure/container-registry"; +import { ContainerRegistryClient, KnownContainerRegistryAudience } from "@azure/container-registry"; import { DefaultAzureCredential } from "@azure/identity"; import * as dotenv from "dotenv"; dotenv.config(); @@ -18,7 +18,9 @@ async function main() { // Get the service endpoint from the environment const endpoint = process.env.CONTAINER_REGISTRY_ENDPOINT || ""; // Create a new ContainerRegistryClient - const client = new ContainerRegistryClient(endpoint, new DefaultAzureCredential()); + const client = new ContainerRegistryClient(endpoint, new DefaultAzureCredential(), { + audience: KnownContainerRegistryAudience.AzureResourceManagerPublicCloud + }); // Iterate through repositories const repositoryNames = client.listRepositoryNames(); diff --git a/sdk/containerregistry/container-registry/samples-dev/repositoryAndArtifact.ts b/sdk/containerregistry/container-registry/samples-dev/repositoryAndArtifact.ts index 825581678cac..4235d2597f56 100644 --- a/sdk/containerregistry/container-registry/samples-dev/repositoryAndArtifact.ts +++ b/sdk/containerregistry/container-registry/samples-dev/repositoryAndArtifact.ts @@ -10,7 +10,8 @@ import { ContainerRepository, ArtifactManifestProperties, ContainerRegistryClient, - RegistryArtifact + RegistryArtifact, + KnownContainerRegistryAudience } from "@azure/container-registry"; import { DefaultAzureCredential } from "@azure/identity"; import * as dotenv from "dotenv"; @@ -23,7 +24,9 @@ export async function main() { const repositoryName = process.env.REPOSITORY_NAME || ""; const pageSize = 1; - const client = new ContainerRegistryClient(endpoint, new DefaultAzureCredential()); + const client = new ContainerRegistryClient(endpoint, new DefaultAzureCredential(), { + audience: KnownContainerRegistryAudience.AzureResourceManagerPublicCloud + }); const repository = client.getRepository(repositoryName); await getProperties(repository); diff --git a/sdk/containerregistry/container-registry/samples-dev/setImageProperties.ts b/sdk/containerregistry/container-registry/samples-dev/setImageProperties.ts index 52d7c1ca63c8..98ece68736ae 100644 --- a/sdk/containerregistry/container-registry/samples-dev/setImageProperties.ts +++ b/sdk/containerregistry/container-registry/samples-dev/setImageProperties.ts @@ -8,7 +8,7 @@ // This sample assumes the registry has a repository `hello-world` with image tagged `v1`. -import { ContainerRegistryClient } from "@azure/container-registry"; +import { ContainerRegistryClient, KnownContainerRegistryAudience } from "@azure/container-registry"; import { DefaultAzureCredential } from "@azure/identity"; import * as dotenv from "dotenv"; dotenv.config(); @@ -17,7 +17,9 @@ async function main() { // Get the service endpoint from the environment const endpoint = process.env.CONTAINER_REGISTRY_ENDPOINT || ""; // Create a new ContainerRegistryClient - const client = new ContainerRegistryClient(endpoint, new DefaultAzureCredential()); + const client = new ContainerRegistryClient(endpoint, new DefaultAzureCredential(), { + audience: KnownContainerRegistryAudience.AzureResourceManagerPublicCloud + }); const image = client.getArtifact("library/hello-world", "v1"); // Set permissions on the image's "latest" tag diff --git a/sdk/containerregistry/container-registry/samples/v1/javascript/anonymousListTags.js b/sdk/containerregistry/container-registry/samples/v1/javascript/anonymousListTags.js index 318849a0ccb4..97811eeb2a59 100644 --- a/sdk/containerregistry/container-registry/samples/v1/javascript/anonymousListTags.js +++ b/sdk/containerregistry/container-registry/samples/v1/javascript/anonymousListTags.js @@ -9,7 +9,10 @@ // in a public registry that belongs to someone else. In this case, the user would need to access // the registry anonymously. Anonymous access allows a user to list all the collections there, but // they wouldn't have permissions to modify or delete any of the images in the registry. -const { ContainerRegistryClient } = require("@azure/container-registry"); +const { + ContainerRegistryClient, + KnownContainerRegistryAudience +} = require("@azure/container-registry"); const dotenv = require("dotenv"); dotenv.config(); @@ -18,7 +21,9 @@ async function main() { const endpoint = process.env.CONTAINER_REGISTRY_ENDPOINT || ""; // Create a new ContainerRegistryClient for anonymous access - const client = new ContainerRegistryClient(endpoint); + const client = new ContainerRegistryClient(endpoint, { + audience: KnownContainerRegistryAudience.AzureResourceManagerPublicCloud + }); // Obtain a RegistryArtifact object to get access to image operations const image = client.getArtifact("library/hello-world", "latest"); diff --git a/sdk/containerregistry/container-registry/samples/v1/javascript/containerRegistryClient.js b/sdk/containerregistry/container-registry/samples/v1/javascript/containerRegistryClient.js index 1722300726aa..502ce4f7e648 100644 --- a/sdk/containerregistry/container-registry/samples/v1/javascript/containerRegistryClient.js +++ b/sdk/containerregistry/container-registry/samples/v1/javascript/containerRegistryClient.js @@ -5,7 +5,10 @@ * @summary Lists repository names and deletes a repository. */ -const { ContainerRegistryClient } = require("@azure/container-registry"); +const { + ContainerRegistryClient, + KnownContainerRegistryAudience +} = require("@azure/container-registry"); const { DefaultAzureCredential } = require("@azure/identity"); const dotenv = require("dotenv"); dotenv.config(); @@ -14,7 +17,9 @@ async function main() { // endpoint should be in the form of "https://myregistryname.azurecr.io" // where "myregistryname" is the actual name of your registry const endpoint = process.env.CONTAINER_REGISTRY_ENDPOINT || ""; - const client = new ContainerRegistryClient(endpoint, new DefaultAzureCredential()); + const client = new ContainerRegistryClient(endpoint, new DefaultAzureCredential(), { + audience: KnownContainerRegistryAudience.AzureResourceManagerPublicCloud + }); await listRepositoryNames(client); // Advanced: listing by pages diff --git a/sdk/containerregistry/container-registry/samples/v1/javascript/deleteImages.js b/sdk/containerregistry/container-registry/samples/v1/javascript/deleteImages.js index 5512ce1b3085..77475b3d418c 100644 --- a/sdk/containerregistry/container-registry/samples/v1/javascript/deleteImages.js +++ b/sdk/containerregistry/container-registry/samples/v1/javascript/deleteImages.js @@ -8,7 +8,10 @@ // A common use case for Azure Container Registries is to scan the repositories // in a registry and delete all but the most recent n images, or all images // older than a certain date. -const { ContainerRegistryClient } = require("@azure/container-registry"); +const { + ContainerRegistryClient, + KnownContainerRegistryAudience +} = require("@azure/container-registry"); const { DefaultAzureCredential } = require("@azure/identity"); const dotenv = require("dotenv"); dotenv.config(); @@ -17,7 +20,9 @@ async function main() { // Get the service endpoint from the environment const endpoint = process.env.CONTAINER_REGISTRY_ENDPOINT || ""; // Create a new ContainerRegistryClient - const client = new ContainerRegistryClient(endpoint, new DefaultAzureCredential()); + const client = new ContainerRegistryClient(endpoint, new DefaultAzureCredential(), { + audience: KnownContainerRegistryAudience.AzureResourceManagerPublicCloud + }); // Iterate through repositories const repositoryNames = client.listRepositoryNames(); diff --git a/sdk/containerregistry/container-registry/samples/v1/javascript/repositoryAndArtifact.js b/sdk/containerregistry/container-registry/samples/v1/javascript/repositoryAndArtifact.js index f1779a64f1c6..a31d6282bb44 100644 --- a/sdk/containerregistry/container-registry/samples/v1/javascript/repositoryAndArtifact.js +++ b/sdk/containerregistry/container-registry/samples/v1/javascript/repositoryAndArtifact.js @@ -5,7 +5,10 @@ * @summary Uses ContainerRepository and RegistryArtifact to work with manifests, tags, and artifacts. */ -const { ContainerRegistryClient } = require("@azure/container-registry"); +const { + ContainerRegistryClient, + KnownContainerRegistryAudience +} = require("@azure/container-registry"); const { DefaultAzureCredential } = require("@azure/identity"); const dotenv = require("dotenv"); dotenv.config(); @@ -17,7 +20,9 @@ async function main() { const repositoryName = process.env.REPOSITORY_NAME || ""; const pageSize = 1; - const client = new ContainerRegistryClient(endpoint, new DefaultAzureCredential()); + const client = new ContainerRegistryClient(endpoint, new DefaultAzureCredential(), { + audience: KnownContainerRegistryAudience.AzureResourceManagerPublicCloud + }); const repository = client.getRepository(repositoryName); await getProperties(repository); diff --git a/sdk/containerregistry/container-registry/samples/v1/javascript/setImageProperties.js b/sdk/containerregistry/container-registry/samples/v1/javascript/setImageProperties.js index 493361529435..4e7c3b8f97d8 100644 --- a/sdk/containerregistry/container-registry/samples/v1/javascript/setImageProperties.js +++ b/sdk/containerregistry/container-registry/samples/v1/javascript/setImageProperties.js @@ -7,7 +7,10 @@ // This sample assumes the registry has a repository `hello-world` with image tagged `v1`. -const { ContainerRegistryClient } = require("@azure/container-registry"); +const { + ContainerRegistryClient, + KnownContainerRegistryAudience +} = require("@azure/container-registry"); const { DefaultAzureCredential } = require("@azure/identity"); const dotenv = require("dotenv"); dotenv.config(); @@ -16,7 +19,9 @@ async function main() { // Get the service endpoint from the environment const endpoint = process.env.CONTAINER_REGISTRY_ENDPOINT || ""; // Create a new ContainerRegistryClient - const client = new ContainerRegistryClient(endpoint, new DefaultAzureCredential()); + const client = new ContainerRegistryClient(endpoint, new DefaultAzureCredential(), { + audience: KnownContainerRegistryAudience.AzureResourceManagerPublicCloud + }); const image = client.getArtifact("library/hello-world", "v1"); // Set permissions on the image's "latest" tag diff --git a/sdk/containerregistry/container-registry/samples/v1/typescript/src/anonymousListTags.ts b/sdk/containerregistry/container-registry/samples/v1/typescript/src/anonymousListTags.ts index ba1f6857822b..9f312c0c4239 100644 --- a/sdk/containerregistry/container-registry/samples/v1/typescript/src/anonymousListTags.ts +++ b/sdk/containerregistry/container-registry/samples/v1/typescript/src/anonymousListTags.ts @@ -9,7 +9,7 @@ // in a public registry that belongs to someone else. In this case, the user would need to access // the registry anonymously. Anonymous access allows a user to list all the collections there, but // they wouldn't have permissions to modify or delete any of the images in the registry. -import { ContainerRegistryClient } from "@azure/container-registry"; +import { ContainerRegistryClient, KnownContainerRegistryAudience } from "@azure/container-registry"; import * as dotenv from "dotenv"; dotenv.config(); @@ -18,7 +18,9 @@ async function main() { const endpoint = process.env.CONTAINER_REGISTRY_ENDPOINT || ""; // Create a new ContainerRegistryClient for anonymous access - const client = new ContainerRegistryClient(endpoint); + const client = new ContainerRegistryClient(endpoint, { + audience: KnownContainerRegistryAudience.AzureResourceManagerPublicCloud + }); // Obtain a RegistryArtifact object to get access to image operations const image = client.getArtifact("library/hello-world", "latest"); diff --git a/sdk/containerregistry/container-registry/samples/v1/typescript/src/containerRegistryClient.ts b/sdk/containerregistry/container-registry/samples/v1/typescript/src/containerRegistryClient.ts index 04b413ad19ba..bb4da3cff64b 100644 --- a/sdk/containerregistry/container-registry/samples/v1/typescript/src/containerRegistryClient.ts +++ b/sdk/containerregistry/container-registry/samples/v1/typescript/src/containerRegistryClient.ts @@ -5,7 +5,7 @@ * @summary Lists repository names and deletes a repository. */ -import { ContainerRegistryClient } from "@azure/container-registry"; +import { ContainerRegistryClient, KnownContainerRegistryAudience } from "@azure/container-registry"; import { DefaultAzureCredential } from "@azure/identity"; import * as dotenv from "dotenv"; dotenv.config(); @@ -14,7 +14,9 @@ export async function main() { // endpoint should be in the form of "https://myregistryname.azurecr.io" // where "myregistryname" is the actual name of your registry const endpoint = process.env.CONTAINER_REGISTRY_ENDPOINT || ""; - const client = new ContainerRegistryClient(endpoint, new DefaultAzureCredential()); + const client = new ContainerRegistryClient(endpoint, new DefaultAzureCredential(), { + audience: KnownContainerRegistryAudience.AzureResourceManagerPublicCloud + }); await listRepositoryNames(client); // Advanced: listing by pages diff --git a/sdk/containerregistry/container-registry/samples/v1/typescript/src/deleteImages.ts b/sdk/containerregistry/container-registry/samples/v1/typescript/src/deleteImages.ts index 099232ed42fc..912f8609106c 100644 --- a/sdk/containerregistry/container-registry/samples/v1/typescript/src/deleteImages.ts +++ b/sdk/containerregistry/container-registry/samples/v1/typescript/src/deleteImages.ts @@ -8,7 +8,7 @@ // A common use case for Azure Container Registries is to scan the repositories // in a registry and delete all but the most recent n images, or all images // older than a certain date. -import { ContainerRegistryClient } from "@azure/container-registry"; +import { ContainerRegistryClient, KnownContainerRegistryAudience } from "@azure/container-registry"; import { DefaultAzureCredential } from "@azure/identity"; import * as dotenv from "dotenv"; dotenv.config(); @@ -17,7 +17,9 @@ async function main() { // Get the service endpoint from the environment const endpoint = process.env.CONTAINER_REGISTRY_ENDPOINT || ""; // Create a new ContainerRegistryClient - const client = new ContainerRegistryClient(endpoint, new DefaultAzureCredential()); + const client = new ContainerRegistryClient(endpoint, new DefaultAzureCredential(), { + audience: KnownContainerRegistryAudience.AzureResourceManagerPublicCloud + }); // Iterate through repositories const repositoryNames = client.listRepositoryNames(); diff --git a/sdk/containerregistry/container-registry/samples/v1/typescript/src/repositoryAndArtifact.ts b/sdk/containerregistry/container-registry/samples/v1/typescript/src/repositoryAndArtifact.ts index 4d6bef4f7c25..0988bb43c1bc 100644 --- a/sdk/containerregistry/container-registry/samples/v1/typescript/src/repositoryAndArtifact.ts +++ b/sdk/containerregistry/container-registry/samples/v1/typescript/src/repositoryAndArtifact.ts @@ -9,7 +9,8 @@ import { ContainerRepository, ArtifactManifestProperties, ContainerRegistryClient, - RegistryArtifact + RegistryArtifact, + KnownContainerRegistryAudience } from "@azure/container-registry"; import { DefaultAzureCredential } from "@azure/identity"; import * as dotenv from "dotenv"; @@ -22,7 +23,9 @@ export async function main() { const repositoryName = process.env.REPOSITORY_NAME || ""; const pageSize = 1; - const client = new ContainerRegistryClient(endpoint, new DefaultAzureCredential()); + const client = new ContainerRegistryClient(endpoint, new DefaultAzureCredential(), { + audience: KnownContainerRegistryAudience.AzureResourceManagerPublicCloud + }); const repository = client.getRepository(repositoryName); await getProperties(repository); diff --git a/sdk/containerregistry/container-registry/samples/v1/typescript/src/setImageProperties.ts b/sdk/containerregistry/container-registry/samples/v1/typescript/src/setImageProperties.ts index b8475d450996..aabb13d665d5 100644 --- a/sdk/containerregistry/container-registry/samples/v1/typescript/src/setImageProperties.ts +++ b/sdk/containerregistry/container-registry/samples/v1/typescript/src/setImageProperties.ts @@ -7,7 +7,7 @@ // This sample assumes the registry has a repository `hello-world` with image tagged `v1`. -import { ContainerRegistryClient } from "@azure/container-registry"; +import { ContainerRegistryClient, KnownContainerRegistryAudience } from "@azure/container-registry"; import { DefaultAzureCredential } from "@azure/identity"; import * as dotenv from "dotenv"; dotenv.config(); @@ -16,7 +16,9 @@ async function main() { // Get the service endpoint from the environment const endpoint = process.env.CONTAINER_REGISTRY_ENDPOINT || ""; // Create a new ContainerRegistryClient - const client = new ContainerRegistryClient(endpoint, new DefaultAzureCredential()); + const client = new ContainerRegistryClient(endpoint, new DefaultAzureCredential(), { + audience: KnownContainerRegistryAudience.AzureResourceManagerPublicCloud + }); const image = client.getArtifact("library/hello-world", "v1"); // Set permissions on the image's "latest" tag diff --git a/sdk/containerregistry/container-registry/src/containerRegistryClient.ts b/sdk/containerregistry/container-registry/src/containerRegistryClient.ts index ca7b62b36f44..f7ffcab48f7b 100644 --- a/sdk/containerregistry/container-registry/src/containerRegistryClient.ts +++ b/sdk/containerregistry/container-registry/src/containerRegistryClient.ts @@ -34,15 +34,11 @@ import { ContainerRegistryRefreshTokenCredential } from "./containerRegistryToke */ export interface ContainerRegistryClientOptions extends PipelineOptions { /** - * Gets or sets the authentication scope to use for authentication with AAD. - * This defaults to the Azure Resource Manager "Azure Global" scope. To - * connect to a different cloud, set this value to "<resource-id>/.default", - * where <resource-id> is one of the Resource IDs listed at - * https://docs.microsoft.com/azure/active-directory/managed-identities-azure-resources/services-support-managed-identities#azure-resource-manager. - * For example, to connect to the Azure Germany cloud, create a client with - * this set to "https://management.microsoftazure.de/.default". + * Gets or sets the audience to use for authentication with Azure Active Directory. + * The authentication scope will be set from this audience. + * See {@link KnownContainerRegistryAudience} for known audience values. */ - authenticationScope?: string; + audience?: string; } /** @@ -132,15 +128,21 @@ export class ContainerRegistryClient { additionalAllowedQueryParameters: ["last", "n", "orderby", "digest"] } }; - const authScope = options.authenticationScope ?? "https://management.azure.com/.default"; + // Require audience now until we have a default ACR audience from the service. + if (!options.audience) { + throw new Error( + "ContainerRegistryClientOptions.audience must be set to initialize ContainerRegistryClient." + ); + } + const defaultScope = `${options.audience}/.default`; const authClient = new GeneratedClient(endpoint, internalPipelineOptions); this.client = new GeneratedClient(endpoint, internalPipelineOptions); this.client.pipeline.addPolicy( bearerTokenAuthenticationPolicy({ credential, - scopes: [authScope], + scopes: [defaultScope], challengeCallbacks: new ChallengeHandler( - new ContainerRegistryRefreshTokenCredential(authClient, authScope, credential) + new ContainerRegistryRefreshTokenCredential(authClient, defaultScope, credential) ) }) ); diff --git a/sdk/containerregistry/container-registry/src/models.ts b/sdk/containerregistry/container-registry/src/models.ts index b9ade9e8f848..2d2ace40fb0b 100644 --- a/sdk/containerregistry/container-registry/src/models.ts +++ b/sdk/containerregistry/container-registry/src/models.ts @@ -5,6 +5,20 @@ export { ContainerRepositoryProperties, ArtifactTagProperties } from "./generate import { ArtifactTagProperties } from "./generated"; +/** + * Defines known cloud audiences for Azure Container Registry. + */ +export enum KnownContainerRegistryAudience { + /** Azure China */ + AzureResourceManagerChina = "https://management.chinacloudapi.cn", + /** Azure Gemany */ + AzureResourceManagerGermany = "https://management.microsoftazure.de", + /** Azure Government */ + AzureResourceManagerGovernment = "https://management.usgovcloudapi.net", + /** Azure Public Cloud */ + AzureResourceManagerPublicCloud = "https://management.azure.com" +} + /** * Defines known artifact architectures that the service supports. */ diff --git a/sdk/containerregistry/container-registry/test/internal/basic.spec.ts b/sdk/containerregistry/container-registry/test/internal/basic.spec.ts index fa5c611918d4..5b0a2c6e6916 100644 --- a/sdk/containerregistry/container-registry/test/internal/basic.spec.ts +++ b/sdk/containerregistry/container-registry/test/internal/basic.spec.ts @@ -3,7 +3,7 @@ // Chai is the Azure SDK Team's preferred assertion library, and it is included // as part of our template project. -import { ContainerRegistryClient } from "../../src"; +import { ContainerRegistryClient, KnownContainerRegistryAudience } from "../../src"; import { assert } from "chai"; describe("ContainerRegistryClient functional test", async function() { @@ -17,7 +17,9 @@ describe("ContainerRegistryClient functional test", async function() { ["", null, undefined].forEach((value) => { it("deleteRepository should throw for invalid repository name", async function() { - const client = new ContainerRegistryClient("https://endpoint"); + const client = new ContainerRegistryClient("https://endpoint", { + audience: KnownContainerRegistryAudience.AzureResourceManagerPublicCloud + }); try { await client.deleteRepository(value as any); assert.fail("should have thrown already"); @@ -29,7 +31,9 @@ describe("ContainerRegistryClient functional test", async function() { ["", null, undefined].forEach((value) => { it("getRepository should throw for invalid endpoint", () => { - const client = new ContainerRegistryClient("https://endpoint"); + const client = new ContainerRegistryClient("https://endpoint", { + audience: KnownContainerRegistryAudience.AzureResourceManagerPublicCloud + }); assert.throws(() => { client.getRepository(value as any); }, "invalid repositoryName"); @@ -38,14 +42,18 @@ describe("ContainerRegistryClient functional test", async function() { ["", null, undefined].forEach((value) => { it("getArtifact should throw for invalid repository name", () => { - const client = new ContainerRegistryClient("https://endpoint"); + const client = new ContainerRegistryClient("https://endpoint", { + audience: KnownContainerRegistryAudience.AzureResourceManagerPublicCloud + }); assert.throws(() => { client.getArtifact(value as any, "digest"); }, "invalid repositoryName"); }); - it("getArtifact should throw for invalid tagORDigest", () => { - const client = new ContainerRegistryClient("https://endpoint"); + it("getArtifact should throw for invalid tagOrDigest", () => { + const client = new ContainerRegistryClient("https://endpoint", { + audience: KnownContainerRegistryAudience.AzureResourceManagerPublicCloud + }); assert.throws(() => { client.getArtifact("repositoryName", value as any); }, "invalid tagOrDigest"); @@ -54,7 +62,9 @@ describe("ContainerRegistryClient functional test", async function() { }); describe("ContainerRepository functional test", async function() { - const client = new ContainerRegistryClient("https://endpoint"); + const client = new ContainerRegistryClient("https://endpoint", { + audience: KnownContainerRegistryAudience.AzureResourceManagerPublicCloud + }); const repository = client.getRepository("repositoryName"); ["", null, undefined].forEach((value) => { it("getArtifact should throw for invalid tagOrDigest", () => { @@ -66,7 +76,9 @@ describe("ContainerRepository functional test", async function() { }); describe("RegistryArtifact functional test", async function() { - const client = new ContainerRegistryClient("https://endpoint"); + const client = new ContainerRegistryClient("https://endpoint", { + audience: KnownContainerRegistryAudience.AzureResourceManagerPublicCloud + }); const artifact = client.getArtifact("repositoryName", "digest"); ["", null, undefined].forEach((value) => { it("deleteTag should throw for invalid tag", async function() { diff --git a/sdk/containerregistry/container-registry/test/utils/utils.ts b/sdk/containerregistry/container-registry/test/utils/utils.ts index 4db1f74f20c0..ed6cf59051f3 100644 --- a/sdk/containerregistry/container-registry/test/utils/utils.ts +++ b/sdk/containerregistry/container-registry/test/utils/utils.ts @@ -7,7 +7,7 @@ import { RecorderEnvironmentSetup, pluginForClientSecretCredentialTests } from "@azure-tools/test-recorder"; -import { ContainerRegistryClient } from "../../src"; +import { ContainerRegistryClient, KnownContainerRegistryAudience } from "../../src"; // When the recorder observes the values of these environment variables in any // recorded HTTP request or response, it will replace them with the values they @@ -70,30 +70,16 @@ function getAuthority(endpoint: string): AzureAuthorityHosts | undefined { return undefined; } -/** - * Defines known authentication scopes that the service supports for national clouds. - */ -export enum KnownAuthScope { - /** Audience for Azure Public Cloud. */ - AzurePublicCloud = "https://management.azure.com/", - /** Audience for Azure China Cloud. */ - AzureChina = "https://management.chinacloudapi.cn/", - /** Audience for US Government Cloud. */ - AzureGovernment = "https://management.usgovcloudapi.net/", - /** Audience for Azure Germany Cloud. */ - AzureGermany = "https://management.microsoftazure.de/" -} - -function getAuthScope(authority?: AzureAuthorityHosts): KnownAuthScope { +function getAudience(authority?: AzureAuthorityHosts): KnownContainerRegistryAudience { switch (authority) { case AzureAuthorityHosts.AzureChina: - return KnownAuthScope.AzureChina; + return KnownContainerRegistryAudience.AzureResourceManagerChina; case AzureAuthorityHosts.AzureGermany: - return KnownAuthScope.AzureGermany; + return KnownContainerRegistryAudience.AzureResourceManagerGermany; case AzureAuthorityHosts.AzureGovernment: - return KnownAuthScope.AzureGovernment; + return KnownContainerRegistryAudience.AzureResourceManagerGovernment; default: - return KnownAuthScope.AzurePublicCloud; + return KnownContainerRegistryAudience.AzureResourceManagerPublicCloud; } } @@ -102,9 +88,9 @@ export function createRegistryClient( options: { anonymous: boolean } = { anonymous: false } ): ContainerRegistryClient { const authorityHost = getAuthority(endpoint); - const authenticationScope = getAuthScope(authorityHost); + const audience = getAudience(authorityHost); const tokenCredentialOptions = authorityHost ? { authorityHost } : undefined; - const clientOptions = { authenticationScope: `${authenticationScope}.default` }; + const clientOptions = { audience }; if (options.anonymous) { return new ContainerRegistryClient(endpoint, clientOptions);