Skip to content

Commit

Permalink
[ContainerRegistry][Test] Add weekly tests for USGov Cloud and China …
Browse files Browse the repository at this point in the history
…Cloud (#16292)

- Update test resource deployment

- Allow passing authority host and authentication scope to test client

- Use CONTAINER_REGISTRY_ prefix for client secrets

- Update pluginForClientSecretCredentialTests to take an optional tenant id parameter

with a default value of `env.AZURE_TENANT_ID`.

As found in ACR weekly-tests pipeline with multi-clouds enabled, AZURE_TENANT_ID
and service-specific CONTAINERREGISTRY_TENANT_ID are different so we need to be
able to specify which one to handle (while investigating whether it's by-design
to have different tenant ids.)
  • Loading branch information
jeremymeng authored Jul 13, 2021
1 parent a616f67 commit baef757
Show file tree
Hide file tree
Showing 10 changed files with 92 additions and 29 deletions.
6 changes: 3 additions & 3 deletions sdk/containerregistry/container-registry/karma.conf.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,9 @@ module.exports = function(config) {
"TEST_MODE",
"CONTAINER_REGISTRY_ENDPOINT",
"CONTAINER_REGISTRY_ANONYMOUS_ENDPOINT",
"AZURE_CLIENT_ID",
"AZURE_CLIENT_SECRET",
"AZURE_TENANT_ID"
"CONTAINERREGISTRY_CLIENT_ID",
"CONTAINERREGISTRY_CLIENT_SECRET",
"CONTAINERREGISTRY_TENANT_ID"
],

// test results reporter to use
Expand Down
6 changes: 3 additions & 3 deletions sdk/containerregistry/container-registry/sample.env
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ REPOSITORY_NAME="<repository name>"
# See the documentation for `EnvironmentCredential` at the following link:
# https://docs.microsoft.com/javascript/api/@azure/identity/environmentcredential

AZURE_TENANT_ID="<AD tenant id or name>"
AZURE_CLIENT_ID="<ID of the user/service principal to authenticate as>"
AZURE_CLIENT_SECRET="<client secret used to authenticate to Azure AD>"
CONTAINERREGISTRY_TENANT_ID="<AD tenant id or name>"
CONTAINERREGISTRY_CLIENT_ID="<ID of the user/service principal to authenticate as>"
CONTAINERREGISTRY_CLIENT_SECRET="<client secret used to authenticate to Azure AD>"

# Our tests assume that TEST_MODE is "playback" by default. You can change it
# to "record" to generate new recordings, or "live" to bypass the recorder
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ REPOSITORY_NAME="<repository name>"
# See the documentation for `EnvironmentCredential` at the following link:
# https://docs.microsoft.com/javascript/api/@azure/identity/environmentcredential

AZURE_TENANT_ID="<AD tenant id or name>"
AZURE_CLIENT_ID="<ID of the user/service principal to authenticate as>"
AZURE_CLIENT_SECRET="<client secret used to authenticate to Azure AD>"
CONTAINERREGISTRY_TENANT_ID="<AD tenant id or name>"
CONTAINERREGISTRY_CLIENT_ID="<ID of the user/service principal to authenticate as>"
CONTAINERREGISTRY_CLIENT_SECRET="<client secret used to authenticate to Azure AD>"

# Our tests assume that TEST_MODE is "playback" by default. You can change it
# to "record" to generate new recordings, or "live" to bypass the recorder
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ REPOSITORY_NAME="<repository name>"
# See the documentation for `EnvironmentCredential` at the following link:
# https://docs.microsoft.com/javascript/api/@azure/identity/environmentcredential

AZURE_TENANT_ID="<AD tenant id or name>"
AZURE_CLIENT_ID="<ID of the user/service principal to authenticate as>"
AZURE_CLIENT_SECRET="<client secret used to authenticate to Azure AD>"
CONTAINERREGISTRY_TENANT_ID="<AD tenant id or name>"
CONTAINERREGISTRY_CLIENT_ID="<ID of the user/service principal to authenticate as>"
CONTAINERREGISTRY_CLIENT_SECRET="<client secret used to authenticate to Azure AD>"

# Our tests assume that TEST_MODE is "playback" by default. You can change it
# to "record" to generate new recordings, or "live" to bypass the recorder
Expand Down
75 changes: 64 additions & 11 deletions sdk/containerregistry/container-registry/test/utils/utils.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import { ClientSecretCredential } from "@azure/identity";
import { env, RecorderEnvironmentSetup } from "@azure/test-utils-recorder";
import { AzureAuthorityHosts, ClientSecretCredential } from "@azure/identity";
import {
env,
RecorderEnvironmentSetup,
pluginForClientSecretCredentialTests
} from "@azure/test-utils-recorder";
import { ContainerRegistryClient } from "../../src";

// When the recorder observes the values of these environment variables in any
Expand All @@ -11,9 +15,9 @@ import { ContainerRegistryClient } from "../../src";
const replaceableVariables: Record<string, string> = {
CONTAINER_REGISTRY_ENDPOINT: "https://myregistry.azurecr.io",
CONTAINER_REGISTRY_ANONYMOUS_ENDPOINT: "https://myregistry.azurecr.io",
AZURE_TENANT_ID: "12345678-1234-1234-1234-123456789012",
AZURE_CLIENT_ID: "azure_client_id",
AZURE_CLIENT_SECRET: "azure_client_secret",
CONTAINERREGISTRY_TENANT_ID: "12345678-1234-1234-1234-123456789012",
CONTAINERREGISTRY_CLIENT_ID: "azure_client_id",
CONTAINERREGISTRY_CLIENT_SECRET: "azure_client_secret",
SUBSCRIPTION_ID: "subscription_id",
RESOURCE_GROUP: "resource_group_id",
REGISTRY: "myregistry"
Expand Down Expand Up @@ -47,15 +51,63 @@ export const recorderEnvSetup: RecorderEnvironmentSetup = {
/refresh_token=([^&]+?)(&|")/,
`refresh_token=sanitized.${expiryReplacement}.sanitized$2`
)
]
],
onLoadCallbackForPlayback: () => {
pluginForClientSecretCredentialTests(env.CONTAINERREGISTRY_TENANT_ID);
}
};

function getAuthority(endpoint: string): AzureAuthorityHosts | undefined {
if (endpoint.endsWith(".azurecr.cn")) {
return AzureAuthorityHosts.AzureChina;
}
if (endpoint.endsWith("azurecr.de")) {
return AzureAuthorityHosts.AzureGermany;
}
if (endpoint.endsWith(".azurecr.us")) {
return AzureAuthorityHosts.AzureGovernment;
}
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 {
switch (authority) {
case AzureAuthorityHosts.AzureChina:
return KnownAuthScope.AzureChina;
case AzureAuthorityHosts.AzureGermany:
return KnownAuthScope.AzureGermany;
case AzureAuthorityHosts.AzureGovernment:
return KnownAuthScope.AzureGovernment;
default:
return KnownAuthScope.AzurePublicCloud;
}
}

export function createRegistryClient(
endpoint: string,
options: { anonymous: boolean } = { anonymous: false }
): ContainerRegistryClient {
const authorityHost = getAuthority(endpoint);
const authenticationScope = getAuthScope(authorityHost);
const tokenCredentialOptions = authorityHost ? { authorityHost } : undefined;
const clientOptions = { authenticationScope: `${authenticationScope}.default` };

if (options.anonymous) {
return new ContainerRegistryClient(endpoint);
return new ContainerRegistryClient(endpoint, clientOptions);
}

// We use ClientSecretCredential instead of DefaultAzureCredential in order
Expand All @@ -64,10 +116,11 @@ export function createRegistryClient(
// than on others, depending on which credentials are available (such as
// Managed Identity or developer credentials).
const credential = new ClientSecretCredential(
env.AZURE_TENANT_ID,
env.AZURE_CLIENT_ID,
env.AZURE_CLIENT_SECRET
env.CONTAINERREGISTRY_TENANT_ID,
env.CONTAINERREGISTRY_CLIENT_ID,
env.CONTAINERREGISTRY_CLIENT_SECRET,
tokenCredentialOptions
);

return new ContainerRegistryClient(endpoint, credential);
return new ContainerRegistryClient(endpoint, credential, clientOptions);
}
2 changes: 2 additions & 0 deletions sdk/containerregistry/container-registry/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ stages:
ServiceDirectory: containerregistry
MatrixFilters:
- DependencyVersion=^$
- Pool=.*mms-ubuntu-2004.*
SupportedClouds: 'Public,UsGov,China'
EnvVars:
AZURE_CLIENT_ID: $(aad-azure-sdk-test-client-id)
AZURE_TENANT_ID: $(aad-azure-sdk-test-tenant-id)
Expand Down
8 changes: 6 additions & 2 deletions sdk/containerregistry/test-resources.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,17 @@
"metadata": {
"description": "The location of the resource. By default, this is the same as the resource group."
}
},
"containerRegistryEndpointSuffix": {
"defaultValue": ".azurecr.io",
"type": "string"
}
},
"variables": {
"apiVersion": "2020-11-01-preview",
"endpointValue": "[format('https://{0}.azurecr.io', parameters('baseName'))]",
"endpointValue": "[format('https://{0}{1}', parameters('baseName'), parameters('containerRegistryEndpointSuffix'))]",
"anonRegistryName": "[format('{0}anon', parameters('baseName'))]",
"anonEndpointValue": "[format('https://{0}.azurecr.io', variables('anonRegistryName'))]"
"anonEndpointValue": "[format('https://{0}{1}', variables('anonRegistryName'), parameters('containerRegistryEndpointSuffix'))]"
},
"resources": [
{
Expand Down
4 changes: 4 additions & 0 deletions sdk/test-utils/recorder/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

## 1.0.0 (Unreleased)

## 2021-07-13

- `pluginForClientSecretCredentialTests` now is exported, and takes an optional `tenantId` parameter with a default value of `env.AZURE_TENANT_ID` to allow handling other tenant Ids.

## 2021-05-12

- Extended the `requestBodyTransformations` from [#14897](https://github.com/Azure/azure-sdk-for-js/pull/14897) to handle browser tests as well.
Expand Down
2 changes: 1 addition & 1 deletion sdk/test-utils/recorder/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,5 @@ export {
isSoftRecordMode,
RecorderEnvironmentSetup
} from "./utils";
export { pluginForIdentitySDK } from "./utils/msalAuth.node";
export { pluginForIdentitySDK, pluginForClientSecretCredentialTests } from "./utils/msalAuth.node";
export { jsonRecordingFilterFunction } from "./basekarma.conf";
6 changes: 3 additions & 3 deletions sdk/test-utils/recorder/src/utils/msalAuth.node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,11 @@ export function mockMsalAuth(importNock: NockType, plugin: (() => void) | undefi
*
* If msal ever changes its behavior, this needs to change - for example path/url/reply have to be updated accordingly
*/
const pluginForClientSecretCredentialTests = () => {
if (env.AZURE_TENANT_ID) {
export const pluginForClientSecretCredentialTests = (tenantId: string = env.AZURE_TENANT_ID) => {
if (tenantId) {
nock("https://login.microsoftonline.com:443")
.persist()
.post(`/${env.AZURE_TENANT_ID}/oauth2/v2.0/token`)
.post(`/${tenantId}/oauth2/v2.0/token`)
.reply(200, {
token_type: "Bearer",
expires_in: 86399,
Expand Down

0 comments on commit baef757

Please sign in to comment.