Skip to content

Commit

Permalink
[Identity] Add manual integration tests for VM, Cloudshell, Kuberneti…
Browse files Browse the repository at this point in the history
…es, and Web Jobs (#7416)

Add manual integration tests for identity for VM, Cloudshell, Kubernetes, and Web jobs
  • Loading branch information
Jonathan Turner committed Mar 1, 2020
1 parent 5d67c21 commit 6477047
Show file tree
Hide file tree
Showing 26 changed files with 994 additions and 1 deletion.
1 change: 1 addition & 0 deletions eng/.docsettings.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ omitted_paths:
- sdk/*/arm-*
- sdk/cognitiveservices/*
- sdk/identity/identity/test/manual/*
- sdk/identity/identity/test/manual-integration/*
- sdk/keyvault/*/test/**
- sdk/**/samples/*
- sdk/**/swagger/*
Expand Down
126 changes: 126 additions & 0 deletions sdk/identity/identity/test/manual-integration/AzureVM/INSTRUCTIONS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
# prerequisite tools
- Azure CLI

# Azure resources
This test requires instances of these Azure resources:
- Azure Key Vault
- Azure Managed Identity
- with secrets/set and secrets/delete permission for the Key Vault
- Azure Virtual Machine with system-assigned identity
- Azure Virtual Machine with user-assigned identity
- don't use the same VM twice

The rest of this section is a walkthrough of deploying these resources.

## Set environment variables to simplify copy-pasting
- RESOURCE_GROUP
- name of an Azure resource group
- must be unique in the Azure subscription
- e.g. 'identity-test-rg'
- VM_NAME_SYSTEM_ASSIGNED
- name of an Azure Virtual machine with a system-assigned identity
- must be unique in the resource group
- e.g. 'identity-test-vm-system'
- VM_NAME_USER_ASSIGNED
- name of an Azure Virtual machine with a user-assigned identity
- must be unique in the resource group
- e.g. 'identity-test-vm-user'
- MANAGED_IDENTITY_NAME
- name of the user-assigned identity
- 3-128 alphanumeric characters
- must be unique in the resource group
- KEY_VAULT_NAME
- 3-24 alphanumeric characters
- must begin with a letter
- must be globally unique

## Run inside of PowerShell

These instructions assume you're running inside of PowerShell.

## resource group
```sh
az group create -n $RESOURCE_GROUP --location westus2
```

## Managed identity
Create the identity:
```sh
az identity create -n $MANAGED_IDENTITY_NAME -g $RESOURCE_GROUP -l westus2
```

## Virtual machines
With system-assigned identity:
```sh
az vm create -n $VM_NAME_SYSTEM_ASSIGNED -g $RESOURCE_GROUP --image UbuntuLTS --assign-identity --size Standard_DS1_v2 -l westus2 --generate-ssh-keys
```

With user-assigned identity:
```sh
az vm create -n $VM_NAME_USER_ASSIGNED -g $RESOURCE_GROUP --image UbuntuLTS --assign-identity $(az identity show -g $RESOURCE_GROUP -n $MANAGED_IDENTITY_NAME -o tsv --query id) --size Standard_DS1_v2 -l westus2 --generate-ssh-keys
```

## Key Vault:
```sh
az keyvault create -g $RESOURCE_GROUP -n $KEY_VAULT_NAME --sku standard
```

Allow the VM with system-assigned identity to access the Key Vault's secrets:
```sh
az keyvault set-policy -n $KEY_VAULT_NAME --object-id $(az vm show -n $VM_NAME_SYSTEM_ASSIGNED -g $RESOURCE_GROUP --query identity.principalId -o tsv) --secret-permissions set delete
```

Do the same for the user-assigned identity:
```sh
az keyvault set-policy -n $KEY_VAULT_NAME --object-id $(az identity show -g $RESOURCE_GROUP -n $MANAGED_IDENTITY_NAME --query principalId -o tsv) --secret-permissions set delete
```

# Install dependencies

## get user-assigned client id
```sh
$VM_ID_USER_ASSIGNED = az vm show -g $RESOURCE_GROUP -n $VM_NAME_USER_ASSIGNED -o tsv --query "identity.userAssignedIdentities.*.{clientId: clientId}"
```

### Build the webapp

```
cd azure-sdk-for-js\sdk\identity\identity\test\manual-integration\AzureVM
```

Install the requirements:
```
npm install
```

Build the job:
```
tsc -p .
```


## Build and run the tests
```sh
az vm run-command invoke -g $RESOURCE_GROUP -n $VM_NAME_USER_ASSIGNED --command-id RunShellScript --parameters "KEY_VAULT_NAME=$($KEY_VAULT_NAME) VM_ID_USER_ASSIGNED=$($VM_ID_USER_ASSIGNED)"--scripts '"sudo apt update && (yes | sudo apt install npm) && npm install -g typescript && git clone https://github.com/azure/azure-sdk-for-js --single-branch --branch master --depth 1 && cd azure-sdk-for-js/sdk/identity/identity/test/manual-integration/AzureVM && npm install && tsc -p ."'
```

```sh
az vm run-command invoke -g $RESOURCE_GROUP -n $VM_NAME_SYSTEM_ASSIGNED --command-id RunShellScript --parameters "KEY_VAULT_NAME=$($KEY_VAULT_NAME)" --scripts '"sudo apt update && (yes | sudo apt install npm) && sudo npm install -g typescript && git clone https://github.com/azure/azure-sdk-for-js --single-branch --branch master --depth 1 && cd azure-sdk-for-js/sdk/identity/identity/test/manual-integration/AzureVM && npm install && tsc -p . && node index"'
```

Note, if you see a message like "Could not get lock /var/lib/apt/lists/lock - open", you may need to re-run the command.

# Verify success

```
az keyvault secret show -n "secret-name-system" --vault-name "$($KEY_VAULT_NAME)"
```

```
az keyvault secret show -n "secret-name-user" --vault-name "$($KEY_VAULT_NAME)"
```

# Delete Azure resources
```sh
az group delete -n $RESOURCE_GROUP -y --no-wait
```
20 changes: 20 additions & 0 deletions sdk/identity/identity/test/manual-integration/AzureVM/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
import { SecretClient } from "@azure/keyvault-secrets";
import { DefaultAzureCredential } from "@azure/identity";

async function main(): Promise<void> {
// This will use the system managed identity
const credential = new DefaultAzureCredential();

const url = "https://" + process.env.KEY_VAULT_NAME + ".vault.azure.net";
const client = new SecretClient(url, credential);

await client.setSecret("secret-name-system", "secret-value-system");
}

main().catch((err) => {
console.log("error code: ", err.code);
console.log("error message: ", err.message);
console.log("error stack: ", err.stack);
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
import { SecretClient } from "@azure/keyvault-secrets";
import { ManagedIdentityCredential } from "@azure/identity";

async function main(): Promise<void> {
// Managed identity will use the managed identity in the environment called VM_ID_USER_ASSIGNED
const credential = new ManagedIdentityCredential(process.env.VM_ID_USER_ASSIGNED!);

const url = "https://" + process.env.KEY_VAULT_NAME + ".vault.azure.net";
const client = new SecretClient(url, credential);

await client.setSecret("secret-name-user", "secret-value-user");
}

main().catch((err) => {
console.log("error code: ", err.code);
console.log("error message: ", err.message);
console.log("error stack: ", err.stack);
});
15 changes: 15 additions & 0 deletions sdk/identity/identity/test/manual-integration/AzureVM/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"name": "azurevmtest",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"@azure/identity": "^1.0.0",
"@azure/keyvault-secrets": "^4.0.2"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"compilerOptions": {
"alwaysStrict": true,
"noImplicitAny": true,
"preserveConstEnums": true,
"sourceMap": true,
"newLine": "LF",
"target": "es5",
"moduleResolution": "node",
"noUnusedLocals": true,
"noUnusedParameters": true,
"strict": true,
"module": "commonjs",
/*"outDir": "./dist-esm",*/
"declaration": true,
"declarationMap": true,
"importHelpers": true,
"declarationDir": "./types",
"lib": ["dom", "es5", "es6", "es7", "esnext"],
"esModuleInterop": true
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
# Testing azure-identity in Azure Cloud Shell

# Open Azure Cloud Shell
https://shell.azure.com/

# Create an Azure Key Vault

## set environment variables to simplify copy-pasting
- RESOURCE_GROUP
- name of an Azure resource group
- must be unique in the Azure subscription
- e.g. 'cloudshell-identity-test'
- KEY_VAULT_NAME
- 3-24 alphanumeric characters
- must begin with a letter
- must be globally unique

## create a resource group
```sh
az group create -n $RESOURCE_GROUP --location westus2
```

## create the Key Vault
```sh
az keyvault create -g $RESOURCE_GROUP -n $KEY_VAULT_NAME --sku standard
```

# Run the tests (from inside Cloudshell)

### Build the webapp
```
git clone https://github.com/azure/azure-sdk-for-js --single-branch --branch master --depth 1
```

```
cd azure-sdk-for-js/sdk/identity/identity/test/manual-integration/Cloudshell
```

Install the requirements:
```
npm install
```

```
npm install typescript
```

Build the job:
```
node_modules/typescript/bin/tsc -p .
```

### Run test
The tests expect the vault's URI in an environment variable. Replace `<put key vault name here>` with the name of the keyvault you created earlier :
```sh
export KEY_VAULT_NAME=<put key vault name here>
```

```sh
node index
```

### Deactivate
```sh
deactivate
```

# Verify success

```
az keyvault secret show -n "secret-name-cloudshell" --vault-name "$($KEY_VAULT_NAME)"
```

# Delete Azure resources
After running tests, delete the resources provisioned earlier:
```sh
az group delete -n $RESOURCE_GROUP -y --no-wait
```
19 changes: 19 additions & 0 deletions sdk/identity/identity/test/manual-integration/Cloudshell/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
import { SecretClient } from "@azure/keyvault-secrets";
import { DefaultAzureCredential } from "@azure/identity";

async function main(): Promise<void> {
const credential = new DefaultAzureCredential();

const url = "https://" + process.env.KEY_VAULT_NAME + ".vault.azure.net";
const client = new SecretClient(url, credential);

await client.setSecret("secret-name-cloudshell", "secret-value-cloudshell");
}

main().catch((err) => {
console.log("error code: ", err.code);
console.log("error message: ", err.message);
console.log("error stack: ", err.stack);
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"name": "cloudshelltest",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"@azure/identity": "^1.0.0",
"@azure/keyvault-secrets": "^4.0.2"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"compilerOptions": {
"alwaysStrict": true,
"noImplicitAny": true,
"preserveConstEnums": true,
"sourceMap": true,
"newLine": "LF",
"target": "es5",
"moduleResolution": "node",
"noUnusedLocals": true,
"noUnusedParameters": true,
"strict": true,
"module": "commonjs",
/*"outDir": "./dist-esm",*/
"declaration": true,
"declarationMap": true,
"importHelpers": true,
"declarationDir": "./types",
"lib": ["dom", "es5", "es6", "es7", "esnext"],
"esModuleInterop": true
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# ------------------------------------
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.
# ------------------------------------
ARG NODE_VERSION=10

# docker can't tell when the repo has changed and will therefore cache this layer
FROM alpine/git as repo
RUN git clone https://github.com/azure/azure-sdk-for-js --single-branch --branch master --depth 1 /azure-sdk-for-js

FROM node:${NODE_VERSION}-slim

COPY --from=repo /azure-sdk-for-js/sdk/identity /sdk/identity
COPY --from=repo /azure-sdk-for-js/sdk/core /sdk/core
COPY --from=repo /azure-sdk-for-js/sdk/keyvault/keyvault-secrets /sdk/keyvault/keyvault-secrets

WORKDIR /sdk/identity/identity/test/manual-integration/Kubernetes
RUN npm install
RUN npm install -g typescript
RUN tsc -p .
CMD ["node", "index"]
Loading

0 comments on commit 6477047

Please sign in to comment.