diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile
deleted file mode 100644
index 222779e5af..0000000000
--- a/.devcontainer/Dockerfile
+++ /dev/null
@@ -1,78 +0,0 @@
-FROM debian:10
-
-# This Dockerfile adds a non-root 'vscode' user with sudo access. However, for Linux,
-# this user's GID/UID must match your local user UID/GID to avoid permission issues
-# with bind mounts. Update USER_UID / USER_GID if yours is not 1000. See
-# https://aka.ms/vscode-remote/containers/non-root-user for details.
-ARG USERNAME=azure-sdk-for-cpp
-ARG USER_UID=1000
-ARG USER_GID=$USER_UID
-ARG PORT=4000
-
-# Install packages as root
-USER root
-
-# Install needed packages and setup non-root user. Use a separate RUN statement to add your own dependencies.
-RUN apt-get update \
- && export DEBIAN_FRONTEND=noninteractive \
- && LANG=C LC_ALL=C apt-get -y install --no-install-recommends \
- apt-utils \
- dialog \
- sudo \
- #
- # Install vim, git, process tools, lsb-release
- git \
- openssh-client \
- less \
- #
- # Azure SDK for C++ dev env
- make \
- cmake \
- ninja-build \
- build-essential \
- zlib1g-dev \
- libcurl4-openssl-dev \
- libssl-dev \
- libxml2-dev \
- gdb \
- # clang format 10 req
- gnupg2 \
- wget \
- ca-certificates \
- # vcpkg reqs
- curl \
- zip \
- unzip \
- tar \
- pkg-config \
-
- #
- # Add en_US.UTF-8 locale
- && echo 'en_US.UTF-8 UTF-8' >> /etc/locale.gen \
- && wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | apt-key add - \
- && echo 'deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic-10 main' | tee -a /etc/apt/sources.list \
- && echo 'deb-src http://apt.llvm.org/bionic/ llvm-toolchain-bionic-10 main' | tee -a /etc/apt/sources.list \
- && apt-get update \
- && apt-get -y install --no-install-recommends clang-format-10 \
- #
- # Create a non-root user to use if preferred - see https://aka.ms/vscode-remote/containers/non-root-user.
- && groupadd --gid $USER_GID $USERNAME \
- && useradd -s /bin/bash --uid $USER_UID --gid $USER_GID -m $USERNAME \
- #
- # Add sudo support for the non-root user
- && echo $USERNAME ALL=\(root\) NOPASSWD:ALL > /etc/sudoers.d/$USERNAME\
- && chmod 0440 /etc/sudoers.d/$USERNAME \
- #
- # Clean up
- && apt-get autoremove -y \
- && apt-get clean -y \
- && rm -rf /var/lib/apt/lists/*
-
-RUN cd / \
- && git clone https://github.com/microsoft/vcpkg.git \
- && cd vcpkg \
- && ./bootstrap-vcpkg.sh \
- && ./vcpkg install curl
-
-# Switch back to the non-root user
-USER ${USERNAME}
diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json
deleted file mode 100644
index dbfa1099a5..0000000000
--- a/.devcontainer/devcontainer.json
+++ /dev/null
@@ -1,32 +0,0 @@
-{
- "name": "Ubuntu-20.04.VCPKG",
- "dockerFile": "Dockerfile",
- "settings": {
- "terminal.integrated.shell.linux": "/bin/bash"
- },
- "extensions": [
- "ms-vscode.cpptools-themes",
- "bbenoist.doxygen",
- "streetsidesoftware.code-spell-checker",
- "ms-vscode.cpptools",
- "xaver.clang-format",
- "twxs.cmake",
- "ms-vscode.cmake-tools",
- "eamodio.gitlens",
- "davidschuldenfrei.gtest-adapter"
- ],
- // Do not run as root. See https://aka.ms/vscode-remote/containers/non-root.
- "remoteUser": "azure-sdk-for-cpp",
- "containerEnv": {
- "AZURE_CLIENT_ID": "",
- "AZURE_CLIENT_SECRET": "",
- "AZURE_KEYVAULT_HSM_URL": "",
- "AZURE_KEYVAULT_URL": "",
- "AZURE_LOG_LEVEL": "1",
- "AZURE_TENANT_ID": "",
- "AZURE_TEST_MODE": "PLAYBACK",
- "CLIENT_OBJECTID": "",
- // set or unset to run using vcpkg or not
- "VCPKG_ROOT": "/vcpkg"
- }
-}
diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
index a31ee36f7c..811541570b 100644
--- a/.github/CODEOWNERS
+++ b/.github/CODEOWNERS
@@ -23,14 +23,14 @@
/sdk/core/ @rickwinter @ahsonkhan @antkmsft @vhvb1989 @gearama @LarryOsterman
# PRLabel: %Azure.Identity
-/sdk/identity/ @antkmsft @schaabs @ahsonkhan @rickwinter @vhvb1989 @gearama
+/sdk/identity/ @antkmsft @schaabs @ahsonkhan @rickwinter @vhvb1989 @gearama @LarryOsterman
###########
# Client SDKs
###########
# PRLabel: %Attestation
-/sdk/attestation/ @LarryOsterman @gkostal @anilba06 @kroshkina-ms
+/sdk/attestation/ @LarryOsterman @gkostal @anilba06 @kroshkina-ms @ahmadmsft @rickwinter @ahsonkhan @antkmsft @vhvb1989 @gearama
# PRLabel: %KeyVault
/sdk/keyvault/ @vhvb1989 @gearama @antkmsft @rickwinter
diff --git a/.vscode/cspell.json b/.vscode/cspell.json
index b522f7d9c6..5b01ec946c 100644
--- a/.vscode/cspell.json
+++ b/.vscode/cspell.json
@@ -19,6 +19,7 @@
"Dockerfile",
"*nlohmann-json*",
"eng/docs/api/assets/**/*",
+ "eng/CredScanSuppression.json",
"**/test/ut/recordings/*.json"
],
// * Unless configured otherwise, these words are not case sensitive
@@ -42,9 +43,11 @@
"cuse",
"CUSEUAP",
"DCMAKE",
+ "DDISABLE",
"deserializers",
"Deserializes",
"DFETCH",
+ "DMSVC",
"docfx",
"DPAPI",
"DRUN",
@@ -81,6 +84,7 @@
"ncus",
"Niels",
"nlohmann",
+ "nostd",
"noclean",
"NOCLOSE",
"NOCRLF",
@@ -89,6 +93,8 @@
"northcentralus",
"NTSTATUS",
"okhttp",
+ "opentelemetry",
+ "otel",
"PBYTE",
"pdbs",
"Piotrowski",
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 6b64d46954..8b8ff1fa3e 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -55,21 +55,31 @@ if(MSVC_USE_STATIC_CRT AND MSVC)
#
# 5. We "replace with empty string" (i.e. remove) first, then add, so that '/MT'
# will be present (and present once) even if '/MD' was not.
-
+ message(STATUS "Configuring Static Runtime Library.")
+ if(${CMAKE_CXX_FLAGS} MATCHES ".*/MD.*")
string(REGEX REPLACE "/MD" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MT")
+ endif()
+ if(${CMAKE_CXX_FLAGS_RELEASE} MATCHES ".*/MD.*")
string(REGEX REPLACE "/MD" "" CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MT")
-
+ endif()
+
+ if(${CMAKE_CXX_FLAGS_RELWITHDEBINFO} MATCHES ".*/MD.*")
string(REGEX REPLACE "/MD" "" CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO}")
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} /MT")
+ endif()
+ if(${CMAKE_CXX_FLAGS_MINSIZEREL} MATCHES ".*/MD.*")
string(REGEX REPLACE "/MD" "" CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL}")
set(CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL} /MT")
+ endif()
+ if(${CMAKE_CXX_FLAGS_DEBUG} MATCHES ".*/MD.*")
string(REGEX REPLACE "/MDd" "" CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MTd")
+ endif()
endif()
if(BUILD_TESTING)
@@ -103,6 +113,5 @@ add_subdirectory(sdk/storage)
add_subdirectory(sdk/template)
if(BUILD_SAMPLES)
- add_subdirectory(samples/integration/vcpkg-keyvault)
add_subdirectory(samples/integration/vcpkg-all-smoke)
endif()
diff --git a/CMakeSettings.json b/CMakeSettings.json
index 6141da95da..445a2b6952 100644
--- a/CMakeSettings.json
+++ b/CMakeSettings.json
@@ -15,7 +15,13 @@
"name": "VCPKG_TARGET_TRIPLET",
"value": "x64-windows-static",
"type": "STRING"
+ },
+ {
+ "name": "MSVC_USE_STATIC_CRT",
+ "value": "True",
+ "type": "BOOL"
}
+
]
},
{
@@ -33,6 +39,11 @@
"name": "VCPKG_TARGET_TRIPLET",
"value": "x64-windows-static",
"type": "STRING"
+ },
+ {
+ "name": "MSVC_USE_STATIC_CRT",
+ "value": "True",
+ "type": "BOOL"
}
]
},
@@ -51,6 +62,11 @@
"name": "VCPKG_TARGET_TRIPLET",
"value": "x86-windows-static",
"type": "STRING"
+ },
+ {
+ "name": "MSVC_USE_STATIC_CRT",
+ "value": "True",
+ "type": "BOOL"
}
]
},
@@ -70,6 +86,11 @@
"value": "True",
"type": "BOOL"
},
+ {
+ "name": "MSVC_USE_STATIC_CRT",
+ "value": "True",
+ "type": "BOOL"
+ },
{
"name": "BUILD_TRANSPORT_CURL",
"value": "True",
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 39d54cffcd..6eab9f5cab 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -1,4 +1,4 @@
-## Azure SDK for C++ Contributing Guide
+# Azure SDK for C++ Contributing Guide
Thank you for your interest in contributing to Azure SDK for C++.
@@ -39,9 +39,9 @@ Thank you for your interest in contributing to Azure SDK for C++.
- Contributor is using an e-mail address other than the primary GitHub address and wants that preserved in the history. Contributor must be willing to squash
the commits manually before acceptance.
-## Developer Guide
+# Developer Guide
-### Codespaces
+## Codespaces
Codespaces is new technology that allows you to use a container as your development environment. This repo provides a Codespaces container which is supported by both GitHub Codespaces and VS Code Codespaces.
@@ -50,54 +50,54 @@ Codespaces is new technology that allows you to use a container as your developm
1. From the Azure SDK GitHub repo, click on the "Code -> Open with Codespaces" button.
1. Open a Terminal. The development environment will be ready for you. Continue to [Building and Testing](https://github.com/Azure/azure-sdk-for-cpp/blob/main/CONTRIBUTING.md#building-and-testing).
-#### VS Code Codespaces
+### VS Code Codespaces
1. Install the [VS Code Remote Extension Pack](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.vscode-remote-extensionpack)
1. When you open the Azure SDK for C++ repo in VS Code, it will prompt you to open the project in the Dev Container. If it does not prompt you, then hit CTRL+P, and select "Remote-Containers: Open Folder in Container..."
1. Open a Terminal. The development environment will be ready for you. Continue to [Building and Testing](https://github.com/Azure/azure-sdk-for-cpp/blob/main/CONTRIBUTING.md#building-and-testing).
-### Full Local Setup
+## Full Local Setup
-#### Pre-requisites
+### Pre-requisites
-##### CMake
+#### CMake
CMake version 3.13 or higher is required to build these libraries. Download and install CMake from the project's
[website](https://cmake.org/download/).
-##### Third Party Dependencies
+### Third Party Dependencies
-- curl
-- libxml2
-- clang-format (min version 10)
+Azure SDK uses Vcpkg manifest mode to declare the [list of required 3rd party dependencies](https://github.com/Azure/azure-sdk-for-cpp/blob/main/vcpkg.json) for building the SDK service libraries. It will also get and set up Vcpkg automatically. **You can move on to [Building the project](#building-the-project)** and skip the next part if you are not interested in learning about alternatives for setting up dependencies.
-Vcpkg can be used to install the Azure SDK for CPP dependencies into a specific folder on the system instead of globally installing them.
-Follow [vcpkg install guide](https://github.com/microsoft/vcpkg#getting-started) to get vcpkg and install the following dependencies:
+#### Customize the Vcpkg dependency integration
-```sh
-./vcpkg install curl libxml2
-```
-
-When using vcpkg, you can set the `VCPKG_ROOT` environment variable to the vcpkg Git repository folder. This would automatically set the CMake variable `CMAKE_TOOLCHAIN_FILE` for you, enabling the project to use any library installed with vcpkg.
+If the CMake option _-DCMAKE_TOOLCHAIN_FILE=..._ is not defined to generate the project, the Azure SDK project will automatically get Vcpkg and link it to get its dependencies. You can use the next environment variables to change this behavior:
-The Azure SDK for C++ uses [this vcpkg release version](https://github.com/Azure/azure-sdk-for-cpp/blob/main/eng/vcpkg-commit.txt) for continuous integration (CI) building and testing. Make sure to checkout this version when following the next steps for building and running the Azure SDK for C++. Using a newer vcpkg version might still work, however, if it is tested.
-
-```sh
-# Checking out vcpkg release version before installing dependencies
+
-git clone https://github.com/Microsoft/vcpkg.git
-cd vcpkg
-# Checkout the vcpkg commit from the vcpkg-commit.txt file (link above)
-git checkout
+
+
+| Environment Variable |
+Description |
+
+
+| AZURE_SDK_DISABLE_AUTO_VCPKG |
+When defined, Vcpkg won't be automatically cloned and linked. Use this setting, for example, if your dependencies are installed on the system and you don't need to get them. |
+
+
+| AZURE_SDK_VCPKG_COMMIT |
+This variable can set the git commit id to be used when automatically cloning Vcpkg. |
+
+
+| VCPKG_ROOT |
+Use this variable to set an existing Vcpkg folder from your system to be linked for building. Use this, for example, when working with Vcpkg classic mode, to switch between different Vcpkg folders. |
+
+
-# build vcpkg (showing Linux command, see vcpkg getting started for Windows)
-./bootstrap-vcpkg.sh
-./vcpkg install curl libxml2
-```
+
-### Building and Testing
-#### Building the project
+## Building the project
Generate the CMake files and build as you would with any standard CMake project. From the
repo root, run:
diff --git a/Dockerfile b/Dockerfile
deleted file mode 100644
index 2152112551..0000000000
--- a/Dockerfile
+++ /dev/null
@@ -1,79 +0,0 @@
-FROM debian:10
-
-# This Dockerfile adds a non-root 'vscode' user with sudo access. However, for Linux,
-# this user's GID/UID must match your local user UID/GID to avoid permission issues
-# with bind mounts. Update USER_UID / USER_GID if yours is not 1000. See
-# https://aka.ms/vscode-remote/containers/non-root-user for details.
-ARG USERNAME=azure-sdk-for-cpp
-ARG USER_UID=1000
-ARG USER_GID=$USER_UID
-ARG PORT=4000
-
-# Install packages as root
-USER root
-
-# Install needed packages and setup non-root user. Use a separate RUN statement to add your own dependencies.
-RUN apt-get update \
- && export DEBIAN_FRONTEND=noninteractive \
- && LANG=C LC_ALL=C apt-get -y install --no-install-recommends \
- apt-utils \
- dialog \
- sudo \
- #
- # Install vim, git, process tools, lsb-release
- git \
- openssh-client \
- less \
- #
- # Azure SDK for C++ dev env
- make \
- #cmake \
- ninja-build \
- build-essential \
- zlib1g-dev \
- libcurl4-openssl-dev \
- libssl-dev \
- libxml2-dev \
- gdb \
- # clang format 10 req
- gnupg2 \
- wget \
- ca-certificates \
- # vcpkg reqs
- curl \
- zip \
- unzip \
- tar \
- pkg-config \
-
- #
- # Add en_US.UTF-8 locale
- && echo 'en_US.UTF-8 UTF-8' >> /etc/locale.gen \
- && wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | apt-key add - \
- && echo 'deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic-10 main' | tee -a /etc/apt/sources.list \
- && echo 'deb-src http://apt.llvm.org/bionic/ llvm-toolchain-bionic-10 main' | tee -a /etc/apt/sources.list \
- && apt-get update \
- && apt-get -y install --no-install-recommends clang-format-10 \
- #
- # Create a non-root user to use if preferred - see https://aka.ms/vscode-remote/containers/non-root-user.
- && groupadd --gid $USER_GID $USERNAME \
- && useradd -s /bin/bash --uid $USER_UID --gid $USER_GID -m $USERNAME \
- #
- # Add sudo support for the non-root user
- && echo $USERNAME ALL=\(root\) NOPASSWD:ALL > /etc/sudoers.d/$USERNAME\
- && chmod 0440 /etc/sudoers.d/$USERNAME \
- #
- # Clean up
- && apt-get autoremove -y \
- && apt-get clean -y \
- && rm -rf /var/lib/apt/lists/*
-
-RUN wget https://github.com/Kitware/CMake/releases/download/v3.20.2/cmake-3.20.2.tar.gz \
- && tar -zxvf cmake-3.20.2.tar.gz \
- && cd cmake-3.20.2 \
- && ./bootstrap \
- && make \
- && make install
-
-# Switch back to the non-root user
-USER ${USERNAME}
diff --git a/Dockerfile.src b/Dockerfile.src
deleted file mode 100644
index 7db38f2cdd..0000000000
--- a/Dockerfile.src
+++ /dev/null
@@ -1,15 +0,0 @@
-FROM base:latest
-ARG USERNAME=azure-sdk-for-cpp
-# Install packages as root
-USER root
-
-WORKDIR /home/azure-sdk-for-cpp/src
-
-COPY ./sdk/keyvault/azure-security-keyvault-certificates ./sdk/keyvault/azure-security-keyvault-certificates
-COPY ./sdk/keyvault/azure-security-keyvault-shared ./sdk/keyvault/azure-security-keyvault-shared
-COPY ./cmake-modules ./cmake-modules
-
-WORKDIR /home/azure-sdk-for-cpp/src/sdk/keyvault/azure-security-keyvault-certificates
-
-USER ${USERNAME}
-
diff --git a/README.md b/README.md
index 23a00e568f..d15cca613c 100644
--- a/README.md
+++ b/README.md
@@ -14,63 +14,146 @@ For API reference docs, tutorials, samples, quick starts, and other documentatio
### Download & Install the SDK
-The easiest way to acquire the C++ SDK is leveraging vcpkg package manager. You will need to install [Git](https://git-scm.com/downloads) before getting started.
+Here are some alternatives, from easiest to advanced, how you can get, build and integrate Azure SDK clients to your application.
-First clone and bootstrap vcpkg itself. You can install it anywhere on your machine, but **make note** of the directory where you clone the vcpkg repo.
+#### CMake Project + Vcpkg - manifest mode
-```cmd
-> git clone https://github.com/microsoft/vcpkg
+The easiest way to acquire the C++ SDK is leveraging [vcpkg](https://github.com/microsoft/vcpkg#getting-started) package manager. You will need to install [Git](https://git-scm.com/downloads) before getting started.
+
+##### 1. Create a [CMake](https://cmake.org/cmake/help/latest/) project
+
+CMake will take care of cross-operating system support.
+
+> Visual Studio installs CMake without adding it to the path. You need to [install CMake](https://cmake.org/download/) if you are not using Visual Studio or if you want to use a command line outside Visual Studio.
+
+Visual Studio:
+
+If you are using Visual Studio and you installed [support for CMake](https://docs.microsoft.com/cpp/build/cmake-projects-in-visual-studio?view=vs-2019), you can create a new CMake Project from Visual Studio, new project menu.
+
+-IMAGE HERE Visual Studio-
+
+Visual Studio Code:
+
+Install the VSCode extensions: [CMake](https://marketplace.visualstudio.com/items?itemName=twxs.cmake) and [CMake Tools](https://marketplace.visualstudio.com/items?itemName=ms-vscode.cmake-tools). Then, create folder for your project and open it with VSCode. Press `F1` and type _CMake: Quick Start_, follow the steps to give a name to your project, to select a compiler and any other initial configuration.
+
+-IMAGE HERE VSCode-
+
+> You can also manually create the root `CMakeLists.txt` with your own initial configuration and source.
+
+##### 2. Link the Vcpkg toolchain file to your CMake project
+
+Azure SDK provides a CMake module that you can use for your application. You only need to create a folder called _cmake-modules_ on the top level of your CMake project and copy [AzureVcpkg.cmake](https://github.com/Azure/azure-sdk-for-cpp/blob/main/cmake-modules/AzureVcpkg.cmake) to this folder.
+
+The AzureVcpkg module supports three scenarios:
+
+1. Getting and setting up Vcpkg automatically (default case). You can set the env var `AZURE_SDK_DISABLE_AUTO_VCPKG` to disable this bahavior.
+2. Automatically linking your application to an existing Vcpkg folder. Set the environment variable `VCPKG_ROOT` to the Vcpkg folder you want to link.
+3. Manually setting a toolchain file with cmake command option. `AzureVcpkg.cmake` module will respect the option.
+
+Add the next lines to your root `CMakeLists.txt` to use `AzureVcpkg.cmake` module:
+
+```cmake
+# Add this lines on the top, before the call to `project(name VERSION 0.0.0)
+list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake-modules")
+include(AzureVcpkg)
+az_vcpkg_integrate()
```
-On Windows:
+##### 3. Add Vcpkg manifest
+
+Add a new file called `vcpkg.json` on the root of your CMake project and add the Azure SDK clients you want to use in your application. For example, the next manifest defines Azure Identity and Blobs.
-```cmd
-> .\vcpkg\bootstrap-vcpkg.bat
+```json
+{
+ "name": "your-app-name",
+ "version-string": "",
+ "dependencies": [
+ "azure-identity-cpp",
+ "azure-storage-blobs-cpp"
+ ]
+}
```
-On Linux:
+##### 4. Link Azure SDK libraries to your application
-```sh
-> ./vcpkg/bootstrap-vcpkg.sh
+Add the next lines to your `CMakeLists.txt` file. It must be added after the cmake target name is defined.
+
+```cmake
+find_package(azure-identity-cpp CONFIG REQUIRED)
+find_package(azure-storage-blobs-cpp CONFIG REQUIRED)
+target_link_libraries(quick-sample PRIVATE Azure::azure-identity Azure::azure-storage-blobs)
```
-To install the libraries for your project, run the following, optionally specifying the triplet. For example, the following will install packages for the `x64-windows` triplet. On Windows, not specifying a triplet will default to `x86-windows`:
+> See the list of available SDK clients for C++ [here](https://azure.github.io/azure-sdk/releases/latest/cpp.html)
-```cmd
-> .\vcpkg\vcpkg install azure-storage-blobs-cpp:x64-windows
+
+##### 5. Generate project and compile
+
+At this point, you can press F7 on Visual Studio or VSCode to generate and build the project. Or you can also run the following commands from a command line:
+
+```bash
+# Create a build folder (if there's not one already there)
+mkdir build
+cd build
+cmake ..
+cmake --build .
```
-See the [list of packages](https://github.com/Azure/azure-sdk-for-cpp#vcpkg) available via vcpkg below. All Azure C++ SDK package names start with `azure-`. You can also search for the libraries you need with the `search` command. For example:
+> Using Vcpkg manifest makes easy to define multiple dependencies and delegate building them to Vcpkg.
+
+#### CMake Project + fetch content
+
+For this scenario, CMake will fetch the Azure SDK source code and make it part of your project. THe SDK client libraries will be compiled at the same time as your application.
+
+Follow the step 1 from above to create a CMake project first.
-```cmd
-> .\vcpkg\vcpkg search azure-
+###### 2. Define CMake fetch content
+
+Add the following code to your root `CMakeLists.txt` file:
+
+```cmake
+# Add this code before creating and linking your application
+
+include(FetchContent)
+FetchContent_Declare(
+ azuresdk
+ GIT_REPOSITORY https://github.com/Azure/azure-sdk-for-cpp.git
+ GIT_TAG
+)
+FetchContent_GetProperties(azuresdk)
+if(NOT azuresdk_POPULATED)
+ FetchContent_Populate(azuresdk)
+ # Adding all Azure SDK libraries
+ add_subdirectory(${azuresdk_SOURCE_DIR} ${azuresdk_BINARY_DIR} EXCLUDE_FROM_ALL)
+ # Adding one Azure SDK Library only (Storage blobs)
+ # add_subdirectory(${azuresdk_SOURCE_DIR}/sdk/storage/azure-storage-blobs ${azuresdk_BINARY_DIR} EXCLUDE_FROM_ALL)
+endif()
```
-Once the library is installed, follow the instructions from the console output to include the library in your `CMake` application. For example, to include `azure-storage-blobs-cpp`, add the following to your `CMakeLists.txt` file:
+##### 3. Link Azure SDK libraries to your application
-```CMake
-find_package(azure-storage-blobs-cpp CONFIG REQUIRED)
-target_link_libraries( PRIVATE Azure::azure-storage-blobs)
+The only difference from the previous scenario is that you don't need to call `find_package()`, since the cmake targets are integrated to your project. So you only need:
+
+```cmake
+# After creating the cmake target
+target_link_libraries(quick-sample PRIVATE Azure::azure-identity Azure::azure-storage-blobs)
```
-> NOTE: All the Azure client libraries take a dependency on `azure-core-cpp` which provides functionality commonly needed by all Azure clients. When you install any client library via vcpkg, it will bring in all the necessary dependencies as well. You don't need to install those individually to get started.
+> Note: You need to take care of getting the Azure SDK dependencies on your own. Either manually installing them or by integrating the source code to your project as well.
-You can reference this [vcpkg Quick Start](https://github.com/microsoft/vcpkg#quick-start-windows) for more details.
+Use step 5 from previous scenario to generate and build your project.
-#### Getting Beta Releases in Vcpkg
+> This scenario requires extra manual configuration to get dependencies, but it is useful as an alternative when Vcpkg is not available
-Official vcpkg registry may have beta versions of Azure SDK client libraries, up until a given library gets released as stable. After that, we don't publish post-first-stable beta releases of that library in the official registry.
+#### Other combinations
-If you are interested in both stable releases and post-first-stable beta releases, see [Azure SDK Beta Vcpkg Registry](https://github.com/Azure/azure-sdk-vcpkg-betas/).
+It should be possible to create your application without a CMake project. For example, manually cloning Azure SDK, building libraries and finally linking them to your application. However, this is considered an advanced scenario and it is not either described or maintained (The other scenarios described below are validated with CI pipelines).
-### Building your Application
+#### Getting Beta Releases in Vcpkg
-In order to use the SDK installed via vcpkg with CMake, you can use the toolchain file from vcpkg:
+Official vcpkg registry may have beta versions of Azure SDK client libraries, up until a given library gets released as stable. After that, we don't publish post-first-stable beta releases of that library in the official registry.
-```cmd
-> cmake -B [build directory] -S . -DCMAKE_TOOLCHAIN_FILE=[path to vcpkg repo]/scripts/buildsystems/vcpkg.cmake
-> cmake --build [build directory]
-```
+If you are interested in both stable releases and post-first-stable beta releases, see [Azure SDK Beta Vcpkg Registry](https://github.com/Azure/azure-sdk-vcpkg-betas/). You can update the `AzureVcpkg.cmake` module to use the beta registry.
#### Using the SDK within your Application
@@ -230,12 +313,14 @@ The following SDK library releases are available on [vcpkg](https://github.com/m
* `azure-core-cpp`
* `azure-identity-cpp`
+* `azure-security-attestation-cpp`
+* `azure-security-keyvault-certificates-cpp`
+* `azure-security-keyvault-keys-cpp`
+* `azure-security-keyvault-secrets-cpp`
* `azure-storage-blobs-cpp`
* `azure-storage-files-datalake-cpp`
* `azure-storage-files-shares-cpp`
-* `azure-security-keyvault-keys-cpp`
-* `azure-security-keyvault-secrets-cpp`
-* `azure-security-keyvault-certificates-cpp`
+* `azure-storage-queues-cpp`
> NOTE: In case of getting linker errors when consuming the SDK on Windows, make sure that [vcpkg triplet](https://vcpkg.readthedocs.io/en/latest/users/triplets/) being consumed matches the [CRT link flags](https://docs.microsoft.com/cpp/build/reference/md-mt-ld-use-run-time-library?view=msvc-160) being set for your app or library build. See also `MSVC_USE_STATIC_CRT` build flag.
diff --git a/cmake-modules/AzureVcpkg.cmake b/cmake-modules/AzureVcpkg.cmake
index 85d0289018..2789241fb5 100644
--- a/cmake-modules/AzureVcpkg.cmake
+++ b/cmake-modules/AzureVcpkg.cmake
@@ -5,14 +5,45 @@
set(AZ_ROOT_DIR "${CMAKE_CURRENT_LIST_DIR}/..")
macro(az_vcpkg_integrate)
- # vcpkg Integration
- if(DEFINED ENV{VCPKG_ROOT} AND NOT DEFINED CMAKE_TOOLCHAIN_FILE)
- set(CMAKE_TOOLCHAIN_FILE "$ENV{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake"
- CACHE STRING "")
- elseif(DEFINED ENV{VCPKG_INSTALLATION_ROOT} AND NOT DEFINED CMAKE_TOOLCHAIN_FILE)
- set(CMAKE_TOOLCHAIN_FILE "$ENV{VCPKG_INSTALLATION_ROOT}/scripts/buildsystems/vcpkg.cmake"
- CACHE STRING "")
+ # AUTO CMAKE_TOOLCHAIN_FILE:
+ # User can call `cmake -DCMAKE_TOOLCHAIN_FILE="path_to_the_toolchain"` as the most specific scenario.
+ # An env var VCPKG_ROOT or VCPKG_INSTALLATION_ROOT can be set to let Azure SDK to set the VCPKG toolchain automatically.
+ # As the last alternative (default case), Azure SDK will automatically clone VCPKG folder and set toolchain from there.
+ if(NOT DEFINED CMAKE_TOOLCHAIN_FILE)
+ if(DEFINED ENV{VCPKG_ROOT})
+ set(CMAKE_TOOLCHAIN_FILE "$ENV{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake"
+ CACHE STRING "")
+ elseif(DEFINED ENV{VCPKG_INSTALLATION_ROOT})
+ set(CMAKE_TOOLCHAIN_FILE "$ENV{VCPKG_INSTALLATION_ROOT}/scripts/buildsystems/vcpkg.cmake"
+ CACHE STRING "")
+ else()
+ # Set AZURE_SDK_DISABLE_AUTO_VCPKG env var to avoid Azure SDK from cloning and setting VCPKG automatically
+ # This option delegate package's dependencies installation to user.
+ if(NOT DEFINED ENV{AZURE_SDK_DISABLE_AUTO_VCPKG})
+ # GET VCPKG FROM SOURCE
+ # User can set env var AZURE_SDK_VCPKG_COMMIT to pick the VCPKG commit to fetch
+ set(VCPKG_COMMIT_STRING f0aa678b7471497f1adedcc99f40e1599ad22f69) # default SDK tested commit
+ if(DEFINED ENV{AZURE_SDK_VCPKG_COMMIT})
+ set(VCPKG_COMMIT_STRING "$ENV{AZURE_SDK_VCPKG_COMMIT}") # default SDK tested commit
+ endif()
+ include(FetchContent)
+ FetchContent_Declare(
+ vcpkg
+ GIT_REPOSITORY https://github.com/microsoft/vcpkg.git
+ GIT_TAG ${VCPKG_COMMIT_STRING}
+ )
+ FetchContent_GetProperties(vcpkg)
+ # make sure to pull vcpkg only once.
+ if(NOT vcpkg_POPULATED)
+ FetchContent_Populate(vcpkg)
+ endif()
+ # use the vcpkg source path
+ set(CMAKE_TOOLCHAIN_FILE "${vcpkg_SOURCE_DIR}/scripts/buildsystems/vcpkg.cmake" CACHE STRING "")
+ endif()
+ endif()
endif()
+
+ # enable triplet customization
if(DEFINED ENV{VCPKG_DEFAULT_TRIPLET} AND NOT DEFINED VCPKG_TARGET_TRIPLET)
set(VCPKG_TARGET_TRIPLET "$ENV{VCPKG_DEFAULT_TRIPLET}" CACHE STRING "")
endif()
diff --git a/cmake-modules/FolderList.cmake b/cmake-modules/FolderList.cmake
index b9fb72c9b5..0cb3d37e60 100644
--- a/cmake-modules/FolderList.cmake
+++ b/cmake-modules/FolderList.cmake
@@ -16,7 +16,7 @@ macro(GetFolderList project)
DownloadDepVersion(sdk/core azure-core 1.5.0)
elseif(${project} STREQUAL STORAGE_BLOBS)
DownloadDepVersion(sdk/core azure-core 1.5.0)
- DownloadDepVersion(sdk/storage/azure-storage-common azure-storage-common 12.2.3)
+ DownloadDepVersion(sdk/storage/azure-storage-common azure-storage-common 12.2.4)
elseif(${project} STREQUAL STORAGE_FILES_DATALAKE)
DownloadDepVersion(sdk/core azure-core 1.3.1)
DownloadDepVersion(sdk/storage/azure-storage-common azure-storage-common 12.2.2)
diff --git a/doc/DistributedTracing.md b/doc/DistributedTracing.md
new file mode 100644
index 0000000000..0d3e4ee5d8
--- /dev/null
+++ b/doc/DistributedTracing.md
@@ -0,0 +1,248 @@
+---
+# cspell:words openetelemetry
+---
+# Distributed Tracing in the C++ SDK
+
+Azure has adopted [W3C Distributed Tracing](https://www.w3.org/TR/trace-context/) as a paradigm for correlating
+requests from clients across multiple services.
+
+This document explains how the Azure C++ SDK implements distributed tracing, how clients integrate with distributed tracing, how
+services should integrate with distributed tracing and finally how the network pipeline and other functionality should
+integrate with distributed tracing.
+
+## Tracing Overview
+
+The Azure SDK for C++ Tracing APIs are modeled after the opentelemetry-cpp API surface defined in the [OpenTelemetry Tracing Specification](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/api.md).
+Additional architectural information about OpenTelemetry can be found in [OpenTelemetry Concepts](https://opentelemetry.io/docs/concepts/).
+
+There are three major components which the Azure SDK components interact with:
+
+- `TracerProvider` - this is a factory which creates `Tracer` objects.
+- `Tracer` - this is a factory which creates `Span` objects.
+- `Span` - Span objects are the APIs which allow tracing an operation.
+Each `span` has a name, a type and a "status". `Spans` also contain "attributes" and "events" which describe an operation.
+
+There is typically a single `TracerProvider` for each application, and for the Azure SDK, each
+service will have a `Tracer` implementation which creates `Span` objects for each service client.
+
+A `Span` can be considered a "unit of work" for a service. Each service method (method which calls into the service) will have a single `Span` reflecting the client method which
+was called.
+
+`Span`'s are hierarchical and each span can have multiple children (each `Span` can only have a single parent). The typical way that this manifests itself during a
+service method call is:
+
+- Service Method "MyServiceMethod" creates a span named "MyServiceMethod" and starts an HTTP request to communicate with the service.
+ - The HTTP pipeline (specifically the `RequestActivityPolicy`) will create a child `span` under the service method `span` named `"HTTP #0"`. This span
+
+ reflects the HTTP call into the service.
+ - If the HTTP call needs to be retried, the existing `span` will be closed an a new span named `HTTP #1` will be created for the retry.
+
+## Distributed Tracing Client Integration
+
+Applications which wish to integrate Distributed Tracing are strongly encouraged
+to use the [opentelemetry-cpp](https://github.com/open-telemetry/opentelemetry-cpp) vcpkg package.
+
+There are numerous examples on the OpenTelemetry web site which demonstrate how to integrate
+opentelemetry into a customer application and integrate the generated traces
+with Azure monitoring infrastructure such as Geneva Monitoring.
+
+Following the examples from opentelemetry-cpp, the following can be used
+to establish an OpenTelemetry exporter which logs to the console or to an
+in-memory logger.
+
+```c++
+opentelemetry::nostd::shared_ptr
+CreateOpenTelemetryProvider()
+{
+#if USE_MEMORY_EXPORTER
+ auto exporter = std::make_unique();
+#else
+ auto exporter = std::make_unique();
+#endif
+
+ // simple processor
+ auto simple_processor = std::unique_ptr(
+ new opentelemetry::sdk::trace::SimpleSpanProcessor(std::move(exporter)));
+
+ auto always_on_sampler = std::unique_ptr(
+ new opentelemetry::sdk::trace::AlwaysOnSampler);
+
+ auto resource_attributes = opentelemetry::sdk::resource::ResourceAttributes{
+ {"service.name", "telemetryTest"}, {"service.instance.id", "instance-1"}};
+ auto resource = opentelemetry::sdk::resource::Resource::Create(resource_attributes);
+ // Create using SDK configurations as parameter
+ return opentelemetry::nostd::shared_ptr(
+ new opentelemetry::sdk::trace::TracerProvider(
+ std::move(simple_processor), resource, std::move(always_on_sampler)));
+}
+```
+
+Other exporters exist to export to [Jaeger](https://github.com/open-telemetry/opentelemetry-cpp/tree/main/exporters/jaeger),
+[Windows ETW](https://github.com/open-telemetry/opentelemetry-cpp/tree/main/exporters/etw) and others.
+
+Once the `opentelemetry::trace::TracerProvider` has been created, The client needs to create a new `Azure::Core::Tracing::OpenTelemetry::OpenTelemetryProvider` which
+functions as an abstract class integration between OpenTelemetry and Azure Core:
+
+```c++
+std::shared_ptr traceProvider
+ = std::make_shared(CreateOpenTelemetryProvider());
+```
+
+To finish the integration with Azure clients, there are two mechanisms to integrate OpenTelemetry into a client application:
+
+1) `Azure::Core::Context` integration.
+1) Service Client Options integration.
+
+### Integrate an OpenTelemetryProvider via the ApplicationContext
+
+To integrate OpenTelemetry for all Azure Clients in the application, the customer can call `Azure::Core::Context::ApplicationContext.SetTracerProvider` to establish the
+tracer provider for the application.
+
+```c++
+ Azure::Core::Context::ApplicationContext.SetTracerProvider(provider);
+```
+
+### Integrate an OpenTelemetryProvider via Service ClientOptions
+
+While using the ApplicationContext is the simplest mechanism for integration OpenTelemetry with a customer application, there may be times the customer needs more flexibility when creating service clients.
+To enable customers to further customize how tracing works, the application can set the `Telemetry.TracingProvider` field in the service client options, which will establish the tracer provider used by
+the service client.
+
+```c++
+auto tracerProvider(CreateOpenTelemetryProvider());
+auto provider(std::make_shared(tracerProvider));
+
+ServiceClientOptions clientOptions;
+clientOptions.Telemetry.TracingProvider = provider;
+clientOptions.Telemetry.ApplicationId = "MyApplication";
+ServiceClient myServiceClient(clientOptions);
+```
+
+## Distributed Tracing Service Integration
+
+There are two steps needed to integrate Distributed Tracing with a Service Client.
+
+1. Add a `DiagnosticTracingFactory` object to the ServiceClient object
+1. Update each service method as follows:
+ 1. Add a call to the `CreateSpan` method on the diagnostic tracing factory. This will create a new span for the client operation.
+ 1. Call `SetStatus` on the created span when the service method successfully completes.
+ 1. Wrap the client method code with a try/catch handler which catches exceptions and call AddEvent with the value of the exception.
+
+### Add a `DiagnosticTracingFactory` to the serviceClient class
+
+To add a new `DiagnosticTracingFactory` to the client, simply add the class as a member:
+
+```c++
+ Azure::Core::Tracing::_internal::TracingContextFactory m_tracingFactory;
+
+```
+
+And construct the new tracing factory in the service constructor:
+
+```c++
+ explicit ServiceClient(ServiceClientOptions const& clientOptions = ServiceClientOptions{})
+ : m_tracingFactory(clientOptions, "Azure.Core.OpenTelemetry.Test.Service", PackageVersion::ToString())
+ ```
+
+### Update Each Service Method
+
+ There are three methods of interest when updating the service method:
+
+ 1. `DiagnosticTracingFactory::CreateSpan` - this creates and returns a `Span` and `Context` object for the service method. The returned Context object must be used for subsequent service operations.
+ 1. `Span::AddEvent(std::exception&)` - This registers the exception with the distributed tracing infrastructure.
+ 1. `Span::SetStatus` - This sets the status of the operation in the trace.
+
+ ```c++
+ Azure::Response ServiceMethod(
+ std::string const&,
+ Azure::Core::Context const& context = Azure::Core::Context{})
+ {
+ // Create a new context and span for this request.
+ auto contextAndSpan = m_tracingFactory.CreateSpan("ServiceMethod", context);
+
+ // contextAndSpan.Context is the new context for the operation.
+ // contextAndSpan.Span is the new span for the operation.
+
+ try
+ {
+ //
+ Azure::Core::Http::Request requestToSend(
+ HttpMethod::Get, Azure::Core::Url(""));
+
+ std::unique_ptr response
+ = m_pipeline->Send(requestToSend, contextAndSpan.Context);
+ contextAndSpan.Span.SetStatus(Azure::Core::Tracing::_internal::SpanStatus::Ok);
+ return Azure::Response("", std::move(response));
+ }
+ catch (std::exception const& ex)
+ {
+ // Register that the exception has happened and that the span is now in error.
+ contextAndSpan.Span.AddEvent(ex);
+ throw;
+ }
+
+ // When contextAndSpan.second goes out of scope, it ends the span, which will record it.
+ }
+};
+```
+
+## Implementation Details
+
+### Distributed Tracing components
+
+In order to maintain flexibility, the opentelemetry-cpp APIs are implemented in a separate package - azure-core-tracing-opentelemetry.
+This is consistent with how opentelemetry is distributed for
+the other Azure SDKs.
+
+The Azure Core API surface interacts with a set of pure virtual base classes (aka "interfaces") in
+the `Azure::Core::Tracing` and `Azure::Core::Tracing::_internal` namespace. These allow a level of separation
+between the Azure Core API surface and the OpenTelemetry API surface - an alternative tracing mechanism needs
+to provide APIs consistent with the `Azure::Core::Tracing` APIs.
+
+The azure-core-tracing-openetelemetry-cpp package implements a set of APIs in the `Azure::Core::Tracing::OpenTelemetry`
+and `Azure::Core::Tracing::OpenTelemetry::_detail` namespace. These provide an Azure Core compatable API surface for distributed tracing.
+
+The core service client interface is the `DiagnosticTracingFactory` class which implements two APIs: `CreateSpan` and
+`CreateSpanFromContext`. `CreateSpan` is intended to be used by service methods which have direct access to a
+`DiagnosticTracingFactory` object, `CreateSpanFromContext` in intended to be used from code which does NOT have
+direct access to the `DiagnosticTracingFactory`.
+
+The final significant piece of the distributed tracing infrastructure is the `RequestActivityPolicy` - this policy MUST be
+inserted into the HTTP pipeline AFTER the `RetryPolicy`. It is responsible for creating the span associated with the HTTP request, it will
+also propagate the W3C distributed tracing headers from the span into the HTTP request.
+
+### Generated traces
+
+The Azure standards for distributed tracing are define in [Azure Distributed Tracing Conventions](https://github.com/Azure/azure-sdk/blob/main/docs/tracing/distributed-tracing-conventions.md).
+The actual tracing elements generated by Azure services are defined in [Azure Tracing Conventions YAML](https://github.com/Azure/azure-sdk/blob/main/docs/tracing/distributed-tracing-conventions.yml).
+
+In summary, these are the traces and attributes which should be generated
+for azure services:
+
+#### Spans
+
+The distributed tracing standards define the following traces:
+
+##### Public APIs
+
+All public APIs MUST create a span which will describes the API.
+The name of the span MUST be the API name.
+
+##### HTTP Calls
+
+Each HTTP request sent to the service MUST create a span describing the request to the service.
+The name of the span MUST be of the form `HTTP #`.
+
+#### Attributes
+
+Generated traces have the following attributes:
+
+| Attribute Name | Semantics | Where Used
+|-----------|--------|-------
+| `az.namespace` |Namespace of the azure service request| All spans.
+| `http.method`| HTTP Method ("GET", "PUT", etc)| HTTP Spans.
+| `http.url`| URL being retrieved (sanitized)| HTTP Spans.
+| `http.status_code` | HTTP status code returned by the service | HTTP Spans.
+| `http.user_agent` | The value of the `User-Agent` HTTP header sent to the service | HTTP Spans.
+| `requestId` | The value of the `x-ms-client-request-id` header sent by the client | HTTP Spans.
+| `serviceRequestId` | The value of the `x-ms-request-id` sent by the server | HTTP Spans.
diff --git a/eng/CredScanSuppression.json b/eng/CredScanSuppression.json
index 106f9fda51..993c1f35c4 100644
--- a/eng/CredScanSuppression.json
+++ b/eng/CredScanSuppression.json
@@ -1,11 +1,20 @@
{
- "tool": "Credential Scanner",
- "suppressions": [
- {
- "file":[
- "eng/common/testproxy/dotnet-devcert.pfx"
- ],
- "_justification": "File contains private key used by test code."
- }
- ]
+ "tool": "Credential Scanner",
+ "suppressions": [
+ {
+ "file": ["eng/common/testproxy/dotnet-devcert.pfx"],
+ "_justification": "File contains private key used by test code."
+ },
+ {
+ "placeholder": [
+ "MIICfzCCAWcCAQAwDjEMMAoGA1UEAxMDeHl6MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA84f7wzzkVTr2spQjn6wNnjo4oTMerlz5ocPku3bo2FsBku7GvkZXFHatAm3jq75avsxyFbs8Ln6VhW9tkixcEEZ0m6b28d+MZAmGQa1V86L77ym/Gzg5JmM04dbdh2oQwUgyJ3/ft+iqFDsFD8uTPyHIDpq7gRHPbeMJE7HVkiIP76w4RctakIvoV6A/NR4LYiH3T/wZn5R+2YRVgSDaHcvbMEOgsFk2k1+Z0wczLrO+y1IfPQZDWt9wvz339C5tB3pLPAEXrFMB0zYOKefEVwVQ6TRziiEMnM+J3061pFSK7gksWWYSZh2pN+ltgw1oFlsD2AqWif8RHKqN4IHEUQIDAQABoCwwKgYJKoZIhvcNAQkOMR0wGzAOBgNVHQ8BAf8EBAMCBaAwCQYDVR0TBAIwADANBgkqhkiG9w0BAQsFAAOCAQEAyZ+VwWpN/6AKlGjJpMgjsTqAb33TsYp60VmfIbLM+7/3p2q+z6jDv14aVTu42MFC0vKVXCq+6AQt9zWyVQWT2oJnmY6SMXbdiWDlOQ7IXuXr6EDLJ2yCT773cIRg6zVfaipxGdRAig5qGkBAWaaBZ3OgY64c3caruUrpyVWQsEgXhY4FoBDtaOrIjYb0Qqo9UEKHVasvPZHAMPHX8uhV0U3dHjBDjOC0qX3zl/OuddsgL6tmySX41jHw+QJ5gGq6ZaJbGOUA4USzHjc7VhurgExTa+s6msUXSjjbWaMOt+BeUCECxqK+S+VO/7T661iDQkWiiI7YH6W/yOMBHhswOg==",
+ "IIUSna-fuSY0fO7PoBydfzNaJ7I",
+ "MIIDAzCCAeugAwIBAgIQJVhZ0GxnRie6ZJw/NOQtbTANBgkqhkiG9w0BAQsFADAOMQwwCgYDVQQDEwN4eXowHhcNMjExMTA0MjA0NTAxWhcNMjIxMTA0MjA1NTAxWjAOMQwwCgYDVQQDEwN4eXowggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDzh/vDPORVOvaylCOfrA2eOjihMx6uXPmhw+S7dujYWwGS7sa+RlcUdq0CbeOrvlq+zHIVuzwufpWFb22SLFwQRnSbpvbx34xkCYZBrVXzovvvKb8bODkmYzTh1t2HahDBSDInf9+36KoUOwUPy5M/IcgOmruBEc9t4wkTsdWSIg/vrDhFy1qQi+hXoD81HgtiIfdP/BmflH7ZhFWBINody9swQ6CwWTaTX5nTBzMus77LUh89BkNa33C/Pff0Lm0Heks8AResUwHTNg4p58RXBVDpNHOKIQycz4nfTrWkVIruCSxZZhJmHak36W2DDWgWWwPYCpaJ/xEcqo3ggcRRAgMBAAGjXTBbMA4GA1UdDwEB/wQEAwIFoDAJBgNVHRMEAjAAMB8GA1UdIwQYMBaAFC2i7bXvQy2OoYCK1p3EcXB+Feq5MB0GA1UdDgQWBBQtou2170MtjqGAitadxHFwfhXquTANBgkqhkiG9w0BAQsFAAOCAQEAc/Rh8KIJPEX25cIdsKuJOqOlmqpqcdQrrHWnA31HDIWHLBanAzIJVd/BRtQHxueAl8cSUOfON2Ei8gIWAoCk3oVeIREbGW7z2SjppBUljAMbbIFCPQOwOPJn22k4CyVENyL/rBBoo/fRDPrZww8cBshcuBHPZiCtqOTgDuCgvHaW0l0QtcVrdNKuBfVN/LPXEj3q73UDNL6NHWAwGoQ5NVoniRy0ohNHIIDuvxBms9u2TzHCCjeuUxwZBhXW7skfpaX9OCw83l7X5PpyigP3/TLUoxwX5yqndhImSUaMEbmJN/DFY2aFDxoYcUKBWYVsUqShbv46SVHoqjKOSF6k6g==",
+ "-----BEGIN PRIVATE KEY-----\\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDzh/vDPORVOvay\\nlCOfrA2eOjihMx6uXPmhw+S7dujYWwGS7sa+RlcUdq0CbeOrvlq+zHIVuzwufpWF\\nb22SLFwQRnSbpvbx34xkCYZBrVXzovvvKb8bODkmYzTh1t2HahDBSDInf9+36KoU\\nOwUPy5M/IcgOmruBEc9t4wkTsdWSIg/vrDhFy1qQi+hXoD81HgtiIfdP/BmflH7Z\\nhFWBINody9swQ6CwWTaTX5nTBzMus77LUh89BkNa33C/Pff0Lm0Heks8AResUwHT\\nNg4p58RXBVDpNHOKIQycz4nfTrWkVIruCSxZZhJmHak36W2DDWgWWwPYCpaJ/xEc\\nqo3ggcRRAgMBAAECggEAKvLifc4xXq6lb10c4z4OsMcH0bYYRRv0kojfwAf6jJ2Q\\nK3+c4VW6act8O59xtYo+qsOXoymANZrxd7TtGAhmvCAQ1JqfloycT9A2M0MEk5E8\\n6TLtlzlVKuX4H5QrQYR9K/k1jy3IIMERrbuy6tQ2Rb4JcDnts5eWg4S0xxpn1ft/\\ny8qpWZtkcwUczV/n0nBNcp3+a/9ZifVc6VguvDC3FrVrSb6EZJEBeZqmU0Mumbl2\\nfgWuBBOWxTfAgXfWdLoI0hVV9KxGRfnEN/uomjW4VWzlCP4nStmYECYBOVryKaNu\\ncpZ+rcbajIHTQTJeys6RGLG+iSqnwJ4Wkt9c9s/42QKBgQD9Lvm/lGf1XW8mpkeS\\nBcB/wyeXOezfH2dIFrL+5xmxxuUH/ffGobs8nY7R1grJgUcs/CEkA34FELWcpnoU\\nk2IQDjxqtBD22tIjX95M1Wy+a/4/yJH+liFzVMf52B1unOoNnZ+DaxNDBYn2M1lv\\nv0f0vi8d4/KV2APPefzlOsEkRwKBgQD2PYUKVwDUjncVt0RF1FRgzvcpsCJU1Ed2\\nqvYD+h+JoZ8mfu/L/ZNYCU3WQRVbFU1g9a7JqQoyIlPfrQYpAKj6lZx/Vx28CL4V\\nvYuSPmmwwFdTRHITptr89VK02qs9zU45q47MUb1AcNN+gG3LD7Z62OI/SHSnifB3\\nK70fXPMWpwKBgCEckqcehpYNWSsJ1hRf0jQjVrstZTAtEDnaViCGItMgOvXXnh8J\\nKc6coIAK6TA/Swq0ErV+C24oKEhLcW3ddJa69eXSlOFj7tWXhSAxTV5+CytWVNmh\\n0tAdh2XCgN7lgKq1MZZjW4qJX+imAI1fy85TTSAwnppAPQdWYd+s1nOjAoGAX0MJ\\nlyh1j8XV2DbgWMt+IT2wbRZREdRWGVimeH9peAto0LHG/3oIaMSgskTXiDdDikFB\\n745P/Xk+TYhYm8A/n0IGG1WOkVIoh6yetGMk7FZc8j/GikfA7J/T8Veva+djXfg6\\n9FyjBK0hhQ0WbLqVdA036heT2cUJnHD1Z47EFH0CgYEA1Bop6A6T9ta60e/dWODe\\n5hxlDknscNp6VvF8JuKq/eN7NIuancYxk0bHolf2UIv89FWQOX8jfv3XPuxXnzNY\\n+Wi9F77jxnjWdQmbJc1E2VUbcUU3ublPUIOYOZKlI7AxVrm2RA7e7CDqagzDPfae\\nuPf2/pk4ieYkw8cQdGj/biQ=\\n-----END PRIVATE KEY-----\\n-----BEGIN CERTIFICATE-----\\nMIIDAzCCAeugAwIBAgIQJVhZ0GxnRie6ZJw/NOQtbTANBgkqhkiG9w0BAQsFADAO\\nMQwwCgYDVQQDEwN4eXowHhcNMjExMTA0MjA0NTAxWhcNMjIxMTA0MjA1NTAxWjAO\\nMQwwCgYDVQQDEwN4eXowggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDz\\nh/vDPORVOvaylCOfrA2eOjihMx6uXPmhw+S7dujYWwGS7sa+RlcUdq0CbeOrvlq+\\nzHIVuzwufpWFb22SLFwQRnSbpvbx34xkCYZBrVXzovvvKb8bODkmYzTh1t2HahDB\\nSDInf9+36KoUOwUPy5M/IcgOmruBEc9t4wkTsdWSIg/vrDhFy1qQi+hXoD81Hgti\\nIfdP/BmflH7ZhFWBINody9swQ6CwWTaTX5nTBzMus77LUh89BkNa33C/Pff0Lm0H\\neks8AResUwHTNg4p58RXBVDpNHOKIQycz4nfTrWkVIruCSxZZhJmHak36W2DDWgW\\nWwPYCpaJ/xEcqo3ggcRRAgMBAAGjXTBbMA4GA1UdDwEB/wQEAwIFoDAJBgNVHRME\\nAjAAMB8GA1UdIwQYMBaAFC2i7bXvQy2OoYCK1p3EcXB+Feq5MB0GA1UdDgQWBBQt\\nou2170MtjqGAitadxHFwfhXquTANBgkqhkiG9w0BAQsFAAOCAQEAc/Rh8KIJPEX2\\n5cIdsKuJOqOlmqpqcdQrrHWnA31HDIWHLBanAzIJVd/BRtQHxueAl8cSUOfON2Ei\\n8gIWAoCk3oVeIREbGW7z2SjppBUljAMbbIFCPQOwOPJn22k4CyVENyL/rBBoo/fR\\nDPrZww8cBshcuBHPZiCtqOTgDuCgvHaW0l0QtcVrdNKuBfVN/LPXEj3q73UDNL6N\\nHWAwGoQ5NVoniRy0ohNHIIDuvxBms9u2TzHCCjeuUxwZBhXW7skfpaX9OCw83l7X\\n5PpyigP3/TLUoxwX5yqndhImSUaMEbmJN/DFY2aFDxoYcUKBWYVsUqShbv46SVHo\\nqjKOSF6k6g==\\n-----END CERTIFICATE-----",
+ "h6WmZ7QZyelkKvNXLyuTxKzR00o",
+ "MIIKCAIBAzCCCcQGCSqGSIb3DQEHAaCCCbUEggmxMIIJrTCCBg4GCSqGSIb3DQEHAaCCBf8EggX7MIIF9zCCBfMGCyqGSIb3DQEMCgECoIIE9jCCBPIwHAYKKoZIhvcNAQwBAzAOBAigyh09Ai5eMQICB9AEggTQE1G2uXYj2W6vagnjiQiL78/GNdFgzi139t4ZL9Id0LAcSdwDtvy7ajm1rOZ2c+xZjYFNjATaQ5DMSC9W4UWnkkWmNSdOnERAqemaIw1xKRjDv3dY+/qCBKboNvcLzXF6JOy8RFSoIKp3IQn8mGEyumumotW/W/35bM6wHYP1SrLzG/YDfAuURA7Nc8+pp8EsY4HAn9w467U8qqXii2KGQRX2wI+vDWsWPq7ZGs02K3lgoDSYRv/eiwVJcYAYqCSjD+M3fqb3NQuBtgPwU/7lZmqcPQSiFJc3rDLw3cKUa8+qzWVTJnH+lo2FS9EvpFt9kqKOqc67yRp8+IEfL1fCnq5nlEzyV5POIeuzY4TpMuPJiVhFnd9yiMYMTeVMvYzKrkDISg/81AjjlQC1pJ+CtmOGH0BQwxLv42/YCbrQEg+XuvuP3PPWo6ecfzjX2DxV/qO39xZrR5rYQpDSrrr1AG8SaDGiKzR9UbKz1VsIO+YLx/r29zaoje9Aw73GEzWc3dfOeTIKRBHX9hhjYvtAK+cB6BhEhZFeOU+SE93CMMZPQMddvEOg0zQu0Ury0ha5vWOb4IHRqu5Wzq+vZCQSXoUqdnCZTZnZ57IGgzCkKRJ8BZs6vbuI8Yg2xPY7RszL+vR7m7mCgB1AmY3g0dJCnVtmwE/bJcTZPHE3MD/1e8+jncgTt3NPvowwVsKAjUl0ksrx1qgNBAQrtgXnrMEifquIO6KlRqqhqcE4Vsk5GThpSG+gg+V28GmQDxfqo54ZgFDEFQ/BCkqH2lieW56A/6p3X3YHzYu2XwU10qaTNZyVD/l/vdEKGGeHoQSsVlzXZeLzWUeccFtrQuo3iDz87zr+AFjuRXy1QN+aNlz5cWMw7xyygQ3nYxs5QUEo1GivnqvI+lH9jvMlxeeWIGxmRgsg/24McV3aFFNN6qEmxsjAH2wYqs7ZjfG5aQxjTLmDRlpt/evRWY+zHzat/UiVJ3aGu9t25es0mcSpj9aTeE7Deg1vsaU5k7fe6NmcsNjz/YPnbHMJF/A3/nEzL6eMH4mq3j8moMh4CylkdPHRC+NMt/Z2v9ClY2B3bC6ybEzcZlnB2jHaW+L53Si36taROwdlZul64nAiRIENlkXQICCfENAdfVgOn+/RHU8fhXajKYMPK85Y1PLgOtarRnfojVz0zIRkcDv0yCMUaa4+9ciVunwdOI8U+MQNmvlZlFUBgii/VXuGclQiVpWoart0hYi18R+LVbYh6wu/lN8eLOpPlwhAvYyEyD1E7GWEelcz6PyZKhVGOhkznq0OvqCPjByfC92nOwtsxnyRWV55noKJVMkN7rjd/FwnzW3MDgMwAlWOFkZL1x1/pThetzqEQ0ojxmut9EGPiGu/GzEjvqY6gP7/aKAx+6QM8zjA7xjpgHP8h4qgSCJp3DWTYY7lHsiwAtDa6+LdnsLlMqdvSYbgokqEHAiDLmGg0v02iq/LwdrpdJJVwJiS1oH1VH6w/jYJ8Tn3JshgqoKd3sFQzcpmwS1vGH+Kr/YeiuW1tNtDlk3vPWSGbCM3R9rtEiSgTEgobnNl7ZTwht4q+6Szvq7mRHnJrt8lPDc4qe+dTjeTuBGBAae0/KpCx0jNy7y2RkdkNTKkfq6xkxgIqvg5ByIxgekwEwYJKoZIhvcNAQkVMQYEBAEAAAAwVwYJKoZIhvcNAQkUMUoeSAAyAGMAMQBkAGUAYQAwAGEALQBjAGYAYwA0AC0ANABmAGIANAAtADkAYQAyAGIALQA4ADQAMwAzADkAZgBmADkAZgBiADYANTB5BgkrBgEEAYI3EQExbB5qAE0AaQBjAHIAbwBzAG8AZgB0ACAARQBuAGgAYQBuAGMAZQBkACAAUgBTAEEAIABhAG4AZAAgAEEARQBTACAAQwByAHkAcAB0AG8AZwByAGEAcABoAGkAYwAgAFAAcgBvAHYAaQBkAGUAcjCCA5cGCSqGSIb3DQEHBqCCA4gwggOEAgEAMIIDfQYJKoZIhvcNAQcBMBwGCiqGSIb3DQEMAQMwDgQITzGgH/jYZ18CAgfQgIIDUORKGdarVP/JSVDHN92vawaA7B7iim8yLabmQ3tMJetjAEo99SGD9ITV/lRR0DYA/1wBIPHEGoPp8Hw30K/KHDtF6WijE+Ftz8sCHGKn9q1GijWKv+dGcJ+HGu34PlSw1/7LGAQrwDLVvG/LcWB7SNAVc7p5f1b3FPKeF2leY5oOI4tfnfCZncGSbofxfKzJ8XLNHP9KgJ3NnApkmzwYROiLme7rgSYI5R7fxKmURWHDIqqaa30Ci6Jjamv+KL2qr3uBtP+Z2m2cJzPPkRgG9/+S4jpJZEUC72R1qBM5xoPR2W9nIicTKSlyUQjM1+ei/OIReBRyLmELZxXi/7FTJctYUxStwybNXb5Q2PwoixD5WXFJolgpts4AgtenNsqeOlvAAN7q8YtaDetIo4mJjItogi+Doh8KnEoZkHalOIfn/NPm/aljMZ0PmEZ8Z0HfUT6LFNXFGT8fZylyyhCU4eu/Vcy08RXT5lRZGqDRn96mqTfwAxkcKHKp0Gmz5SeJHA9MUb8Akt6X8A+ab0lLWMMSK1mscwKM6ktWvuY/3A1iGE91NY0DXSzv76/iL7CO6W2P7mIOr2LVTa6C/xOAa+GgPIeU1epicsNdhU9tquWI3G1hvOKcsLfli1usIcDf6p9cGdPw1GRYvYaEt6VHfcfLkXFgjby+3mz6x6WnX8qG6zmyJ41niG4wCbzlrllIYs7m61Clareu/vvKYItasxYNEhOYO1vNWYvx3fFWRHOTA0Rd9KSq/ycH/0hN1ZLqz3rB8exrU8qXXow5DydDF7B0rb9iQoz4O9kc1PJ3cHLEjxZeLTTFB832LeTKaI7qkcHtfwyVHZai+qICeR7YeE+xf7ntUp+E7mzzhe1NdUThVGHujify42OSvjaq90SbeHlhTydgLpOgw3mZYremtA7LxTv05quRZFtHuH+8LYEfZs76xz3cmmcEeQVaht/D8klg64ejj7Kq+aq2NpxlXm2YelKdt6aQRSVDohu0BJ10vBomSHNso7cQ2po01unLajmOXrEraye104Jw3PGbpLeAEsqgQEwcLGLYco6hFjhtx38cPgIKP48x1wSunkcP4/ajVg/kTFKqJoIxthHG/IBBi2Ni6+4riwA0t9+taku3MDswHzAHBgUrDgMCGgQUCwBpcm6ctOkAnYJMA4WfIGsPLaEEFG36m1eb+MJ1cPiHB99IqprAyLTCAgIH0A=="
+ ],
+ "_justification": "Test Playback certificates."
+ }
+ ]
}
diff --git a/eng/common/TestResources/New-TestResources.ps1 b/eng/common/TestResources/New-TestResources.ps1
index b7785df9dd..da01e8375a 100644
--- a/eng/common/TestResources/New-TestResources.ps1
+++ b/eng/common/TestResources/New-TestResources.ps1
@@ -63,6 +63,10 @@ param (
[ValidateSet('AzureCloud', 'AzureUSGovernment', 'AzureChinaCloud', 'Dogfood')]
[string] $Environment = 'AzureCloud',
+ [Parameter()]
+ [ValidateSet('test', 'perf')]
+ [string] $ResourceType = 'test',
+
[Parameter()]
[hashtable] $ArmTemplateParameters,
@@ -223,7 +227,7 @@ function BuildBicepFile([System.IO.FileSystemInfo] $file)
}
$tmp = $env:TEMP ? $env:TEMP : [System.IO.Path]::GetTempPath()
- $templateFilePath = Join-Path $tmp "test-resources.$(New-Guid).compiled.json"
+ $templateFilePath = Join-Path $tmp "$ResourceType-resources.$(New-Guid).compiled.json"
# Az can deploy bicep files natively, but by compiling here it becomes easier to parse the
# outputted json for mismatched parameter declarations.
@@ -349,7 +353,7 @@ try {
$root = [System.IO.Path]::Combine($repositoryRoot, "sdk", $ServiceDirectory) | Resolve-Path
$templateFiles = @()
- 'test-resources.json', 'test-resources.bicep' | ForEach-Object {
+ "$ResourceType-resources.json", "$ResourceType-resources.bicep" | ForEach-Object {
Write-Verbose "Checking for '$_' files under '$root'"
Get-ChildItem -Path $root -Filter "$_" -Recurse | ForEach-Object {
Write-Verbose "Found template '$($_.FullName)'"
@@ -586,9 +590,9 @@ try {
# Service principals in the Microsoft AAD tenant must end with an @microsoft.com domain; those in other tenants
# are not permitted to do so. Format the non-MS name so there's an assocation with the Azure SDK.
if ($TenantId -eq '72f988bf-86f1-41af-91ab-2d7cd011db47') {
- $displayName = "test-resources-$($baseName)$suffix.microsoft.com"
+ $displayName = "$ResourceType-resources-$($baseName)$suffix.microsoft.com"
} else {
- $displayName = "$($baseName)$suffix.test-resources.azure.sdk"
+ $displayName = "$($baseName)$suffix.$ResourceType-resources.azure.sdk"
}
$servicePrincipalWrapper = NewServicePrincipalWrapper -subscription $SubscriptionId -resourceGroup $ResourceGroupName -displayName $DisplayName
@@ -705,7 +709,7 @@ try {
}
}
- $preDeploymentScript = $templateFile.originalFilePath | Split-Path | Join-Path -ChildPath 'test-resources-pre.ps1'
+ $preDeploymentScript = $templateFile.originalFilePath | Split-Path | Join-Path -ChildPath "$ResourceType-resources-pre.ps1"
if (Test-Path $preDeploymentScript) {
Log "Invoking pre-deployment script '$preDeploymentScript'"
&$preDeploymentScript -ResourceGroupName $ResourceGroupName @PSBoundParameters
@@ -745,7 +749,7 @@ try {
$deploymentOutputs = SetDeploymentOutputs $serviceName $context $deployment $templateFile
- $postDeploymentScript = $templateFile.originalFilePath | Split-Path | Join-Path -ChildPath 'test-resources-post.ps1'
+ $postDeploymentScript = $templateFile.originalFilePath | Split-Path | Join-Path -ChildPath "$ResourceType-resources-post.ps1"
if (Test-Path $postDeploymentScript) {
Log "Invoking post-deployment script '$postDeploymentScript'"
&$postDeploymentScript -ResourceGroupName $ResourceGroupName -DeploymentOutputs $deploymentOutputs @PSBoundParameters
diff --git a/eng/common/TestResources/Remove-TestResources.ps1 b/eng/common/TestResources/Remove-TestResources.ps1
index 788dae63e6..069f2bf8a6 100644
--- a/eng/common/TestResources/Remove-TestResources.ps1
+++ b/eng/common/TestResources/Remove-TestResources.ps1
@@ -52,6 +52,10 @@ param (
[Parameter(ParameterSetName = 'ResourceGroup+Provisioner')]
[switch] $CI,
+ [Parameter()]
+ [ValidateSet('test', 'perf')]
+ [string] $ResourceType = 'test',
+
[Parameter()]
[switch] $Force,
@@ -198,7 +202,7 @@ Log "Selected subscription '$subscriptionName'"
if ($ServiceDirectory) {
$root = [System.IO.Path]::Combine("$PSScriptRoot/../../../sdk", $ServiceDirectory) | Resolve-Path
- $preRemovalScript = Join-Path -Path $root -ChildPath 'remove-test-resources-pre.ps1'
+ $preRemovalScript = Join-Path -Path $root -ChildPath "remove-$ResourceType-resources-pre.ps1"
if (Test-Path $preRemovalScript) {
Log "Invoking pre resource removal script '$preRemovalScript'"
@@ -210,7 +214,7 @@ if ($ServiceDirectory) {
}
# Make sure environment files from New-TestResources -OutFile are removed.
- Get-ChildItem -Path $root -Filter test-resources.json.env -Recurse | Remove-Item -Force:$Force
+ Get-ChildItem -Path $root -Filter "$ResourceType-resources.json.env" -Recurse | Remove-Item -Force:$Force
}
$verifyDeleteScript = {
diff --git a/eng/common/TestResources/deploy-test-resources.yml b/eng/common/TestResources/deploy-test-resources.yml
index 25c0823ac5..a0c68f33a3 100644
--- a/eng/common/TestResources/deploy-test-resources.yml
+++ b/eng/common/TestResources/deploy-test-resources.yml
@@ -4,6 +4,7 @@ parameters:
DeleteAfterHours: 8
Location: ''
SubscriptionConfiguration: $(sub-config-azure-cloud-test-resources)
+ ResourceType: test
# SubscriptionConfiguration will be splatted into the parameters of the test
# resources script. It should be JSON in the form:
@@ -48,6 +49,7 @@ steps:
# pass those in via the ArmTemplateParameters flag, and handle any
# additional parameters from the pipelines via AdditionalParameters
eng/common/TestResources/New-TestResources.ps1 `
+ -ResourceType '${{ parameters.ResourceType }}' `
-ServiceDirectory '${{ parameters.ServiceDirectory }}' `
-Location '${{ parameters.Location }}' `
-DeleteAfterHours '${{ parameters.DeleteAfterHours }}' `
diff --git a/eng/common/TestResources/remove-test-resources.yml b/eng/common/TestResources/remove-test-resources.yml
index cf5c0c5ac4..9675f58e06 100644
--- a/eng/common/TestResources/remove-test-resources.yml
+++ b/eng/common/TestResources/remove-test-resources.yml
@@ -4,6 +4,7 @@
parameters:
ServiceDirectory: ''
SubscriptionConfiguration: $(sub-config-azure-cloud-test-resources)
+ ResourceType: test
# SubscriptionConfiguration will be splat into the parameters of the test
# resources script. It should be JSON in the form:
@@ -29,6 +30,7 @@ steps:
eng/common/TestResources/Remove-TestResources.ps1 `
@subscriptionConfiguration `
+ -ResourceType '${{ parameters.ResourceType }}' `
-ServiceDirectory "${{ parameters.ServiceDirectory }}" `
-CI `
-Force `
diff --git a/eng/common/docgeneration/templates/matthews/partials/class.header.tmpl.partial b/eng/common/docgeneration/templates/matthews/partials/class.header.tmpl.partial
index 49a27d8273..db73a4bddb 100644
--- a/eng/common/docgeneration/templates/matthews/partials/class.header.tmpl.partial
+++ b/eng/common/docgeneration/templates/matthews/partials/class.header.tmpl.partial
@@ -87,14 +87,14 @@
{{/syntax.typeParameters.0}}
-{{#remarks}}
-
-
-{{/remarks}}
-
{{#example.0}}
-{{__global.examples}}
+{{__global.examples}}
{{/example.0}}
{{#example}}
{{{.}}}
{{/example}}
+
+{{#remarks}}
+
+
+{{/remarks}}
\ No newline at end of file
diff --git a/eng/common/docgeneration/templates/matthews/partials/class.tmpl.partial b/eng/common/docgeneration/templates/matthews/partials/class.tmpl.partial
index 5f00b822cc..37a69fa1c4 100644
--- a/eng/common/docgeneration/templates/matthews/partials/class.tmpl.partial
+++ b/eng/common/docgeneration/templates/matthews/partials/class.tmpl.partial
@@ -132,11 +132,6 @@
{{/definition}}
{{/implements}}
-{{#remarks}}
-
-
-{{/remarks}}
-
{{#example.0}}
{{__global.examples}}
{{/example.0}}
@@ -144,6 +139,11 @@
{{{.}}}
{{/example}}
+{{#remarks}}
+
+
+{{/remarks}}
+
{{#exceptions.0}}
{{__global.exceptions}}
diff --git a/eng/common/pipelines/templates/steps/check-spelling.yml b/eng/common/pipelines/templates/steps/check-spelling.yml
index f9f0cf2704..77c68e1d89 100644
--- a/eng/common/pipelines/templates/steps/check-spelling.yml
+++ b/eng/common/pipelines/templates/steps/check-spelling.yml
@@ -5,6 +5,9 @@
# TargetBranch - Target ref (e.g. main) to compare to create file change
# list.
# CspellConfigPath - Path to cspell.json config location
+#
+# This check recognizes the setting of variable "Skip.SpellCheck"
+# if set to 'true', spellchecking will not be invoked.
parameters:
ContinueOnError: true
@@ -13,12 +16,14 @@ parameters:
steps:
- ${{ if eq(variables['Build.Reason'], 'PullRequest') }}:
- task: NodeTool@0
+ condition: and(succeededOrFailed(), ne(variables['Skip.SpellCheck'],'true'))
inputs:
versionSpec: 16.x
displayName: Use Node.js 16.x
- task: PowerShell@2
displayName: Check spelling (cspell)
+ condition: and(succeededOrFailed(), ne(variables['Skip.SpellCheck'],'true'))
continueOnError: ${{ parameters.ContinueOnError }}
inputs:
targetType: filePath
diff --git a/eng/common/pipelines/templates/steps/create-apireview.yml b/eng/common/pipelines/templates/steps/create-apireview.yml
index cd658132de..e850069437 100644
--- a/eng/common/pipelines/templates/steps/create-apireview.yml
+++ b/eng/common/pipelines/templates/steps/create-apireview.yml
@@ -24,4 +24,11 @@ steps:
pwsh: true
workingDirectory: $(Pipeline.Workspace)
displayName: Create API Review for ${{ artifact.name}}
- condition: and(succeededOrFailed(), ne(variables['Skip.CreateApiReview'], 'true') , ne(variables['Build.Reason'],'PullRequest'), eq(variables['System.TeamProject'], 'internal'))
+ condition: >-
+ and(
+ succeededOrFailed(),
+ ne(variables['Skip.CreateApiReview'], 'true'),
+ ne(variables['Build.Reason'],'PullRequest'),
+ eq(variables['System.TeamProject'], 'internal'),
+ not(endsWith(variables['Build.Repository.Name'], '-pr'))
+ )
diff --git a/eng/common/pipelines/templates/steps/credscan.yml b/eng/common/pipelines/templates/steps/credscan.yml
index 0171c79d0d..8a2e53748a 100644
--- a/eng/common/pipelines/templates/steps/credscan.yml
+++ b/eng/common/pipelines/templates/steps/credscan.yml
@@ -28,6 +28,8 @@ steps:
Write-Host "##vso[task.setvariable variable=SKIP_CREDSCAN]true"
}
displayName: CredScan setup
+ condition: succeededOrFailed()
+
- task: securedevelopmentteam.vss-secure-development-tools.build-task-credscan.CredScan@3
displayName: CredScan running
condition: and(succeededOrFailed(), ne(variables['SKIP_CREDSCAN'], true))
diff --git a/eng/common/pipelines/templates/steps/sparse-checkout.yml b/eng/common/pipelines/templates/steps/sparse-checkout.yml
index 69db80fc82..49f9eb553b 100644
--- a/eng/common/pipelines/templates/steps/sparse-checkout.yml
+++ b/eng/common/pipelines/templates/steps/sparse-checkout.yml
@@ -59,8 +59,9 @@ steps:
# sparse-checkout commands after initial checkout will auto-checkout again
if (!$hasInitialized) {
- Write-Host "git checkout $($repository.Commitish)"
- git checkout $($repository.Commitish) # this will use the default branch if repo.Commitish is empty
+ Write-Host "git -c advice.detachedHead=false checkout $($repository.Commitish)"
+ # This will use the default branch if repo.Commitish is empty
+ git -c advice.detachedHead=false checkout $($repository.Commitish)
} else {
Write-Host "Skipping checkout as repo has already been initialized"
}
diff --git a/eng/common/scripts/Delete-RemoteBranches.ps1 b/eng/common/scripts/Delete-RemoteBranches.ps1
index 4ee3f1b05d..2d1c3c3033 100644
--- a/eng/common/scripts/Delete-RemoteBranches.ps1
+++ b/eng/common/scripts/Delete-RemoteBranches.ps1
@@ -1,3 +1,4 @@
+[CmdletBinding(SupportsShouldProcess)]
param(
# The repo owner: e.g. Azure
$RepoOwner,
@@ -5,8 +6,11 @@ param(
$RepoName,
# Please use the RepoOwner/RepoName format: e.g. Azure/azure-sdk-for-java
$RepoId="$RepoOwner/$RepoName",
- [Parameter(Mandatory = $true)]
- $BranchPrefix,
+ # CentralRepoId the original PR to generate sync PR. E.g Azure/azure-sdk-tools for eng/common
+ $CentralRepoId,
+ # We start from the sync PRs, use the branch name to get the PR number of central repo. E.g. sync-eng/common-()-(). Have group name on PR number.
+ # For sync-eng/common work, we use regex as "^sync-eng/common.*-(?\d+).*$".
+ $BranchRegex,
# Date format: e.g. Tuesday, April 12, 2022 1:36:02 PM. Allow to use other date format.
[AllowNull()]
[DateTime]$LastCommitOlderThan,
@@ -19,7 +23,8 @@ param(
LogDebug "Operating on Repo [ $RepoId ]"
try{
- $responses = Get-GitHubSourceReferences -RepoId $RepoId -Ref "heads/$BranchPrefix" -AuthToken $AuthToken
+ # pull all branches.
+ $responses = Get-GitHubSourceReferences -RepoId $RepoId -Ref "heads" -AuthToken $AuthToken
}
catch {
LogError "Get-GitHubSourceReferences failed with exception:`n$_"
@@ -29,11 +34,16 @@ catch {
foreach ($res in $responses)
{
if (!$res -or !$res.ref) {
- LogDebug "No branch returned from the branch prefix $BranchPrefix on $Repo. Skipping..."
+ LogDebug "No branch returned from the branch prefix $BranchRegex on $Repo. Skipping..."
continue
}
$branch = $res.ref
$branchName = $branch.Replace("refs/heads/","")
+ if (!($branchName -match $BranchRegex)) {
+ continue
+ }
+
+ # Get all open sync PRs associate with branch.
try {
$head = "${RepoId}:${branchName}"
LogDebug "Operating on branch [ $branchName ]"
@@ -44,16 +54,44 @@ foreach ($res in $responses)
LogError "Get-GitHubPullRequests failed with exception:`n$_"
exit 1
}
-
$openPullRequests = $pullRequests | ? { $_.State -eq "open" }
- if ($openPullRequests.Count -gt 0)
- {
- LogDebug "Branch [ $branchName ] in repo [ $RepoId ] has open pull Requests. Skipping"
- LogDebug $openPullRequests.url
+
+ if (!$CentralRepoId -and $openPullRequests.Count -gt 0) {
+ LogDebug "CentralRepoId is not configured and found open PRs associate with branch [ $branchName ]. Skipping..."
continue
}
- LogDebug "Branch [ $branchName ] in repo [ $RepoId ] has no associated open Pull Request. "
+ # check central PR
+ if ($CentralRepoId) {
+ $pullRequestNumber = $Matches["PrNumber"]
+ # If central PR number found, then skip
+ if (!$pullRequestNumber) {
+ LogError "No PR number found in the branch name. Please check the branch name [ $branchName ]. Skipping..."
+ continue
+ }
+
+ try {
+ $centralPR = Get-GitHubPullRequest -RepoId $CentralRepoId -PullRequestNumber $pullRequestNumber -AuthToken $AuthToken
+ LogDebug "Found central PR pull request: $($centralPR.html_url)"
+ if ($centralPR.state -ne "closed") {
+ # Skipping if there open central PR number for the branch.
+ continue
+ }
+ }
+ catch
+ {
+ # If there is no central PR for the PR number, log error and skip.
+ LogError "Get-GitHubPullRequests failed with exception:`n$_"
+ LogError "Not found PR number [ $pullRequestNumber ] from [ $CentralRepoId ]. Skipping..."
+ continue
+ }
+ }
+
+ foreach ($openPullRequest in $openPullRequests) {
+ Write-Host "Open pull Request [ $($openPullRequest.html_url) ] will be closed after branch deletion."
+ }
+
+ # If there is date filter, then check if branch last commit older than the date.
if ($LastCommitOlderThan) {
if (!$res.object -or !$res.object.url) {
LogWarning "No commit url returned from response. Skipping... "
@@ -61,8 +99,7 @@ foreach ($res in $responses)
}
try {
$commitDate = Get-GithubReferenceCommitDate -commitUrl $res.object.url -AuthToken $AuthToken
- if (!$commitDate)
- {
+ if (!$commitDate) {
LogDebug "No last commit date found. Skipping."
continue
}
@@ -78,9 +115,12 @@ foreach ($res in $responses)
exit 1
}
}
+
try {
- Remove-GitHubSourceReferences -RepoId $RepoId -Ref $branch -AuthToken $AuthToken
- LogDebug "The branch [ $branchName ] in [ $RepoId ] has been deleted."
+ if ($PSCmdlet.ShouldProcess("[ $branchName ] in [ $RepoId ]", "Deleting branches on cleanup script")) {
+ Remove-GitHubSourceReferences -RepoId $RepoId -Ref $branch -AuthToken $AuthToken
+ Write-Host "The branch [ $branchName ] with sha [$($res.object.sha)] in [ $RepoId ] has been deleted."
+ }
}
catch {
LogError "Remove-GitHubSourceReferences failed with exception:`n$_"
diff --git a/eng/common/scripts/Helpers/Metadata-Helpers.ps1 b/eng/common/scripts/Helpers/Metadata-Helpers.ps1
index a8daf0d837..c5d22ea834 100644
--- a/eng/common/scripts/Helpers/Metadata-Helpers.ps1
+++ b/eng/common/scripts/Helpers/Metadata-Helpers.ps1
@@ -80,3 +80,56 @@ function GetPrimaryCodeOwner ([string]$TargetDirectory)
Write-Warning "No code owner found in $TargetDirectory."
return $null
}
+
+function GetDocsMsService($packageInfo, $serviceName)
+{
+ $service = $serviceName.ToLower().Replace(' ', '').Replace('/', '-')
+ if ($packageInfo.MSDocService) {
+ # Use MSDocService in csv metadata to override the service directory
+ # TODO: Use taxonomy for service name -- https://github.com/Azure/azure-sdk-tools/issues/1442
+ $service = $packageInfo.MSDocService
+ }
+ Write-Host "The service of package: $service"
+ return $service
+}
+
+function GenerateDocsMsMetadata($language, $langTitle = "", $serviceName, $tenantId, $clientId, $clientSecret, $msService)
+{
+ if (!$langTitle) {
+ $langTitle = "Azure $serviceName SDK for $language"
+ }
+ $langDescription = "Reference for Azure $serviceName SDK for $language"
+ # Github url for source code: e.g. https://github.com/Azure/azure-sdk-for-js
+ $serviceBaseName = $serviceName.ToLower().Replace(' ', '').Replace('/', '-')
+ $author = GetPrimaryCodeOwner -TargetDirectory "/sdk/$serviceBaseName/"
+ $msauthor = ""
+ if (!$author) {
+ LogError "Cannot fetch the author from CODEOWNER file."
+ }
+ elseif ($TenantId -and $ClientId -and $ClientSecret) {
+ $msauthor = GetMsAliasFromGithub -TenantId $tenantId -ClientId $clientId -ClientSecret $clientSecret -GithubUser $author
+ }
+ # Default value
+ if (!$msauthor) {
+ LogError "No ms.author found for $author. "
+ $msauthor = $author
+ }
+ $date = Get-Date -Format "MM/dd/yyyy"
+ $header = @"
+---
+title: $langTitle
+description: $langDescription
+author: $author
+ms.author: $msauthor
+ms.date: $date
+ms.topic: reference
+ms.devlang: $language
+ms.service: $msService
+---
+"@
+ return $header
+}
+
+function ServiceLevelReadmeNameStyle($serviceName) {
+ return $serviceName.ToLower().Replace(' ', '-').Replace('/', '-')
+}
\ No newline at end of file
diff --git a/eng/common/scripts/Helpers/Package-Helpers.ps1 b/eng/common/scripts/Helpers/Package-Helpers.ps1
new file mode 100644
index 0000000000..15a1f2ea8d
--- /dev/null
+++ b/eng/common/scripts/Helpers/Package-Helpers.ps1
@@ -0,0 +1,37 @@
+function GetPackageKey($pkg) {
+ $pkgKey = $pkg.Package
+ $groupId = $null
+
+ if ($pkg.PSObject.Members.Name -contains "GroupId") {
+ $groupId = $pkg.GroupId
+ }
+
+ if ($groupId) {
+ $pkgKey = "${groupId}:${pkgKey}"
+ }
+
+ return $pkgKey
+ }
+
+ # Different language needs a different way to index the package. Build a map in convienice to lookup the package.
+ # E.g. : is the package key in java.
+ function GetPackageLookup($packageList) {
+ $packageLookup = @{}
+
+ foreach ($pkg in $packageList) {
+ $pkgKey = GetPackageKey $pkg
+
+ # We want to prefer updating non-hidden packages but if there is only
+ # a hidden entry then we will return that
+ if (!$packageLookup.ContainsKey($pkgKey) -or $packageLookup[$pkgKey].Hide -eq "true") {
+ $packageLookup[$pkgKey] = $pkg
+ }
+ else {
+ # Warn if there are more then one non-hidden package
+ if ($pkg.Hide -ne "true") {
+ Write-Host "Found more than one package entry for $($pkg.Package) selecting the first non-hidden one."
+ }
+ }
+ }
+ return $packageLookup
+ }
diff --git a/eng/common/scripts/Invoke-GitHubAPI.ps1 b/eng/common/scripts/Invoke-GitHubAPI.ps1
index 0bc2e871c8..504ac51ada 100644
--- a/eng/common/scripts/Invoke-GitHubAPI.ps1
+++ b/eng/common/scripts/Invoke-GitHubAPI.ps1
@@ -95,10 +95,9 @@ function Get-GitHubSourceReferences {
function Get-GitHubPullRequest {
param (
- [Parameter(Mandatory = $true)]
$RepoOwner,
- [Parameter(Mandatory = $true)]
$RepoName,
+ $RepoId = "$RepoOwner/$RepoName",
[Parameter(Mandatory = $true)]
$PullRequestNumber,
[ValidateNotNullOrEmpty()]
@@ -106,7 +105,7 @@ function Get-GitHubPullRequest {
$AuthToken
)
- $uri = "$GithubAPIBaseURI/$RepoOwner/$RepoName/pulls/$PullRequestNumber"
+ $uri = "$GithubAPIBaseURI/$RepoId/pulls/$PullRequestNumber"
return Invoke-RestMethod `
-Method GET `
@@ -152,6 +151,27 @@ function New-GitHubPullRequest {
-MaximumRetryCount 3
}
+function Close-GitHubPullRequest {
+ param (
+ [Parameter(Mandatory = $true)]
+ $apiurl,
+ [ValidateNotNullOrEmpty()]
+ [Parameter(Mandatory = $true)]
+ $AuthToken
+ )
+
+ $parameters = @{
+ state = "closed"
+ }
+
+ return Invoke-RestMethod `
+ -Method PATCH `
+ -Uri $apiurl `
+ -Body ($parameters | ConvertTo-Json) `
+ -Headers (Get-GitHubApiHeaders -token $AuthToken) `
+ -MaximumRetryCount 3
+}
+
function New-GitHubIssue {
param (
[Parameter(Mandatory = $true)]
diff --git a/eng/common/scripts/Save-Package-Properties.ps1 b/eng/common/scripts/Save-Package-Properties.ps1
index db2470dbd0..6fb9e61ee0 100644
--- a/eng/common/scripts/Save-Package-Properties.ps1
+++ b/eng/common/scripts/Save-Package-Properties.ps1
@@ -108,6 +108,12 @@ if ($allPackageProperties)
}
$outputPath = Join-Path -Path $outDirectory "$configFilePrefix.json"
Write-Host "Output path of json file: $outputPath"
+ $outDir = Split-Path $outputPath -parent
+ if (-not (Test-Path -path $outDir))
+ {
+ Write-Host "Creating directory $($outDir) for json property file"
+ New-Item -ItemType Directory -Path $outDir
+ }
SetOutput $outputPath $pkg
}
diff --git a/eng/common/scripts/Service-Level-Readme-Automation.ps1 b/eng/common/scripts/Service-Level-Readme-Automation.ps1
new file mode 100644
index 0000000000..513871dfe8
--- /dev/null
+++ b/eng/common/scripts/Service-Level-Readme-Automation.ps1
@@ -0,0 +1,236 @@
+<#
+.SYNOPSIS
+The script is to generate service level readme if it is missing.
+For exist ones, we do 2 things here:
+1. Generate the client but not import to the existing service level readme.
+2. Update the metadata of service level readme
+
+.DESCRIPTION
+Given a doc repo location, and the credential for fetching the ms.author.
+Generate missing service level readme and updating metadata of the existing ones.
+
+.PARAMETER DocRepoLocation
+Location of the documentation repo. This repo may be sparsely checked out
+depending on the requirements for the domain
+
+.PARAMETER TenantId
+The aad tenant id/object id for ms.author.
+
+.PARAMETER ClientId
+The add client id/application id for ms.author.
+
+.PARAMETER ClientSecret
+The client secret of add app for ms.author.
+#>
+
+param(
+ [Parameter(Mandatory = $true)]
+ [string] $DocRepoLocation,
+
+ [Parameter(Mandatory = $false)]
+ [string]$TenantId,
+
+ [Parameter(Mandatory = $false)]
+ [string]$ClientId,
+
+ [Parameter(Mandatory = $false)]
+ [string]$ClientSecret
+)
+. $PSScriptRoot/common.ps1
+. $PSScriptRoot/Helpers/Metadata-Helpers.ps1
+. $PSScriptRoot/Helpers/Package-Helpers.ps1
+
+Set-StrictMode -Version 3
+
+function create-metadata-table($readmeFolder, $readmeName, $moniker, $msService, $clientTableLink, $mgmtTableLink, $serviceName)
+{
+ $readmePath = Join-Path $readmeFolder -ChildPath $readmeName
+ $content = ""
+ if (Test-Path (Join-Path $readmeFolder -ChildPath $clientTableLink)) {
+ $content = "## Client packages - $moniker`r`n"
+ $content += "[!INCLUDE [client-packages]($clientTableLink)]`r`n"
+ }
+ if (Test-Path (Join-Path $readmeFolder -ChildPath $mgmtTableLink)) {
+ $content = "## Management packages - $moniker`r`n"
+ $content += "[!INCLUDE [mgmt-packages]($mgmtTableLink)]`r`n"
+ }
+ if (!$content) {
+ return
+ }
+ $null = New-Item -Path $readmePath -Force
+ $lang = $LanguageDisplayName
+ $langTitle = "Azure $serviceName SDK for $lang"
+ # Generate the front-matter for docs needs
+ $metadataString = GenerateDocsMsMetadata -language $lang -langTitle $langTitle -serviceName $serviceName `
+ -tenantId $TenantId -clientId $ClientId -clientSecret $ClientSecret `
+ -msService $msService
+ Add-Content -Path $readmePath -Value $metadataString
+
+ # Add tables, seperate client and mgmt.
+ $readmeHeader = "# $langTitle - $moniker"
+ Add-Content -Path $readmePath -Value $readmeHeader
+ Add-Content -Path $readmePath -Value $content
+}
+
+function compare-and-merge-metadata ($original, $updated) {
+ $originalTable = ConvertFrom-StringData -StringData $original -Delimiter ":"
+ $updatedTable = ConvertFrom-StringData -StringData $updated -Delimiter ":"
+ foreach ($key in $originalTable.Keys) {
+ if (!($updatedTable.ContainsKey($key))) {
+ Write-Warning "New metadata missed the entry: $key. Adding back."
+ $updated += "$key`: $($originalTable[$key])`r`n"
+ }
+ }
+ return $updated
+}
+
+# Update the metadata table.
+function update-metadata-table($readmeFolder, $readmeName, $serviceName, $msService)
+{
+ $readmePath = Join-Path $readmeFolder -ChildPath $readmeName
+ $readmeContent = Get-Content -Path $readmePath -Raw
+ $null = $readmeContent -match "---`n*(?(.*`n)*)---`n*(?(.*`n)*)"
+ $restContent = $Matches["content"]
+ $lang = $LanguageDisplayName
+ $orignalMetadata = $Matches["metadata"]
+ $metadataString = GenerateDocsMsMetadata -language $lang -serviceName $serviceName `
+ -tenantId $TenantId -clientId $ClientId -clientSecret $ClientSecret `
+ -msService $msService
+ $null = $metadataString -match "---`n*(?(.*`n)*)---"
+ $mergedMetadata = compare-and-merge-metadata -original $orignalMetadata -updated $Matches["metadata"]
+ Set-Content -Path $readmePath -Value "---`n$mergedMetadata---`n$restContent" -NoNewline
+}
+
+function generate-markdown-table($readmeFolder, $readmeName, $packageInfo, $moniker) {
+ $tableHeader = "| Reference | Package | Source |`r`n|---|---|---|`r`n"
+ $tableContent = ""
+ # Here is the table, the versioned value will
+ foreach ($pkg in $packageInfo) {
+ $repositoryLink = $RepositoryUri
+ $packageLevelReadme = ""
+ if (Test-Path "Function:$GetPackageLevelReadmeFn") {
+ $packageLevelReadme = &$GetPackageLevelReadmeFn -packageMetadata $pkg
+ }
+
+ $referenceLink = "[$($pkg.DisplayName)]($packageLevelReadme-readme.md)"
+ if (!(Test-Path (Join-Path $readmeFolder -ChildPath "$packageLevelReadme-readme.md"))) {
+ $referenceLink = $pkg.DisplayName
+ }
+ $githubLink = $GithubUri
+ if ($pkg.PSObject.Members.Name -contains "DirectoryPath") {
+ $githubLink = "$GithubUri/blob/main/$($pkg.DirectoryPath)"
+ }
+ $line = "|$referenceLink|[$($pkg.Package)]($repositoryLink/$($pkg.Package))|[Github]($githubLink)|`r`n"
+ $tableContent += $line
+ }
+ $readmePath = Join-Path $readmeFolder -ChildPath $readmeName
+ if($tableContent) {
+ $null = New-Item -Path $readmePath -ItemType File -Force
+ Add-Content -Path $readmePath -Value $tableHeader -NoNewline
+ Add-Content -Path $readmePath -Value $tableContent -NoNewline
+ }
+}
+
+function generate-service-level-readme($readmeBaseName, $pathPrefix, $packageInfos, $serviceName, $moniker) {
+ # Add ability to override
+ # Fetch the service readme name
+ $msService = GetDocsMsService -packageInfo $packageInfos[0] -serviceName $serviceName
+
+ $readmeFolder = "$DocRepoLocation/$pathPrefix/$moniker/"
+ $serviceReadme = "$readmeBaseName.md"
+ $clientIndexReadme = "$readmeBaseName-client-index.md"
+ $mgmtIndexReadme = "$readmeBaseName-mgmt-index.md"
+ $clientPackageInfo = $packageInfos.Where({ 'client' -eq $_.Type }) | Sort-Object -Property Package
+ if ($clientPackageInfo) {
+ generate-markdown-table -readmeFolder $readmeFolder -readmeName "$clientIndexReadme" -packageInfo $clientPackageInfo -moniker $moniker
+ }
+ # TODO: we currently do not have the right decision on how we display mgmt packages. Will track the mgmt work in issue.
+ # https://github.com/Azure/azure-sdk-tools/issues/3422
+ # $mgmtPackageInfo = $packageInfos.Where({ 'mgmt' -eq $_.Type }) | Sort-Object -Property Package
+ # if ($mgmtPackageInfo) {
+ # generate-markdown-table -readmeFolder $readmeFolder -readmeName "$mgmtIndexReadme" -packageInfo $mgmtPackageInfo -moniker $moniker
+ # }
+ if (!(Test-Path (Join-Path $readmeFolder -ChildPath $serviceReadme))) {
+ create-metadata-table -readmeFolder $readmeFolder -readmeName $serviceReadme -moniker $moniker -msService $msService `
+ -clientTableLink $clientIndexReadme -mgmtTableLink $mgmtIndexReadme `
+ -serviceName $serviceName
+ }
+ else {
+ update-metadata-table -readmeFolder $readmeFolder -readmeName $serviceReadme -serviceName $serviceName -msService $msService
+ }
+}
+
+$fullMetadata = Get-CSVMetadata
+$monikers = @("latest", "preview")
+foreach($moniker in $monikers) {
+ # The onboarded packages return is key-value pair, which key is the package index, and value is the package info from {metadata}.json
+ # E.g.
+ # Key as: @azure/storage-blob
+ # Value as:
+ # {
+ # "Name": "@azure/storage-blob",
+ # "Version": "12.10.0-beta.1",
+ # "DevVersion": null,
+ # "DirectoryPath": "sdk/storage/storage-blob",
+ # "ServiceDirectory": "storage",
+ # "ReadMePath": "sdk/storage/storage-blob/README.md",
+ # "ChangeLogPath": "sdk/storage/storage-blob/CHANGELOG.md",
+ # "Group": null,
+ # "SdkType": "client",
+ # "IsNewSdk": true,
+ # "ArtifactName": "azure-storage-blob",
+ # "ReleaseStatus": "2022-04-19"
+ # }
+ $onboardedPackages = &$GetOnboardedDocsMsPackagesForMonikerFn `
+ -DocRepoLocation $DocRepoLocation -moniker $moniker
+ $csvMetadata = @()
+ foreach($metadataEntry in $fullMetadata) {
+ if ($metadataEntry.Package -and $metadataEntry.Hide -ne 'true') {
+ $pkgKey = GetPackageKey $metadataEntry
+ if($onboardedPackages.ContainsKey($pkgKey)) {
+ if ($onboardedPackages[$pkgKey] -and $onboardedPackages[$pkgKey].DirectoryPath) {
+ if (!($metadataEntry.PSObject.Members.Name -contains "DirectoryPath")) {
+ Add-Member -InputObject $metadataEntry `
+ -MemberType NoteProperty `
+ -Name DirectoryPath `
+ -Value $onboardedPackages[$pkgKey].DirectoryPath
+ }
+ }
+ $csvMetadata += $metadataEntry
+ }
+ }
+ }
+ $packagesForService = @{}
+ $allPackages = GetPackageLookup $csvMetadata
+ foreach ($metadataKey in $allPackages.Keys) {
+ $metadataEntry = $allPackages[$metadataKey]
+ if (!$metadataEntry.ServiceName) {
+ LogWarning "Empty ServiceName for package `"$metadataKey`". Skipping."
+ continue
+ }
+ $packagesForService[$metadataKey] = $metadataEntry
+ }
+ $services = @{}
+ foreach ($package in $packagesForService.Values) {
+ if ($package.ServiceName -eq 'Other') {
+ # Skip packages under the service category "Other". Those will be handled
+ # later
+ continue
+ }
+ if (!$services.ContainsKey($package.ServiceName)) {
+ $services[$package.ServiceName] = $true
+ }
+ }
+ foreach ($service in $services.Keys) {
+ Write-Host "Building service: $service"
+
+ $servicePackages = $packagesForService.Values.Where({ $_.ServiceName -eq $service })
+
+
+ $serviceReadmeBaseName = ServiceLevelReadmeNameStyle -serviceName $service
+ $hrefPrefix = "docs-ref-services"
+
+ generate-service-level-readme -readmeBaseName $serviceReadmeBaseName -pathPrefix $hrefPrefix `
+ -packageInfos $servicePackages -serviceName $service -moniker $moniker
+ }
+}
diff --git a/eng/common/scripts/Test-SampleMetadata.ps1 b/eng/common/scripts/Test-SampleMetadata.ps1
index 523aeb31dd..d5681e85d3 100644
--- a/eng/common/scripts/Test-SampleMetadata.ps1
+++ b/eng/common/scripts/Test-SampleMetadata.ps1
@@ -221,6 +221,7 @@ begin {
"azure-kubernetes-service",
"azure-lab-services",
"azure-language-understanding",
+ "azure-language-service",
"azure-lighthouse",
"azure-linux-vm",
"azure-live-ondemand-streaming",
diff --git a/eng/common/scripts/common.ps1 b/eng/common/scripts/common.ps1
index 6951c5a9a9..c472d18034 100644
--- a/eng/common/scripts/common.ps1
+++ b/eng/common/scripts/common.ps1
@@ -50,6 +50,8 @@ $FindArtifactForApiReviewFn = "Find-${Language}-Artifacts-For-Apireview"
$TestProxyTrustCertFn = "Import-Dev-Cert-${Language}"
$ValidateDocsMsPackagesFn = "Validate-${Language}-DocMsPackages"
$GetOnboardedDocsMsPackagesFn = "Get-${Language}-OnboardedDocsMsPackages"
+$GetOnboardedDocsMsPackagesForMonikerFn = "Get-${Language}-OnboardedDocsMsPackagesForMoniker"
$GetDocsMsTocDataFn = "Get-${Language}-DocsMsTocData"
$GetDocsMsTocChildrenForManagementPackagesFn = "Get-${Language}-DocsMsTocChildrenForManagementPackages"
$UpdateDocsMsTocFn = "Get-${Language}-UpdatedDocsMsToc"
+$GetPackageLevelReadmeFn = "Get-${Language}-PackageLevelReadme"
\ No newline at end of file
diff --git a/eng/common/scripts/job-matrix/job-matrix-functions.ps1 b/eng/common/scripts/job-matrix/job-matrix-functions.ps1
index 7d36752135..8822d7ce72 100644
--- a/eng/common/scripts/job-matrix/job-matrix-functions.ps1
+++ b/eng/common/scripts/job-matrix/job-matrix-functions.ps1
@@ -117,7 +117,7 @@ function GenerateMatrix(
}
$matrix = FilterMatrix $matrix $filters
- $matrix = ProcessReplace $matrix $replace $config.displayNamesLookup
+ $matrix = ProcessReplace $matrix $replace $combinedDisplayNameLookup
$matrix = FilterMatrixDisplayName $matrix $displayNameFilter
return $matrix
}
@@ -352,7 +352,7 @@ function ProcessImport([MatrixParameter[]]$matrix, [String]$selection, [Array]$n
}
}
if ((!$matrix -and !$importPath) -or !$importPath) {
- return $matrix, @()
+ return $matrix, @(), @{}
}
if (!(Test-Path $importPath)) {
@@ -370,7 +370,7 @@ function ProcessImport([MatrixParameter[]]$matrix, [String]$selection, [Array]$n
$combinedDisplayNameLookup[$lookup.Name] = $lookup.Value
}
- return $matrix, $importedMatrix, $importedMatrixConfig.displayNamesLookup
+ return $matrix, $importedMatrix, $combinedDisplayNameLookup
}
function CombineMatrices([Array]$matrix1, [Array]$matrix2, [Hashtable]$displayNamesLookup = @{})
diff --git a/eng/common/scripts/job-matrix/tests/job-matrix-functions.modification.tests.ps1 b/eng/common/scripts/job-matrix/tests/job-matrix-functions.modification.tests.ps1
index 08979caaaf..9dca8eba09 100644
--- a/eng/common/scripts/job-matrix/tests/job-matrix-functions.modification.tests.ps1
+++ b/eng/common/scripts/job-matrix/tests/job-matrix-functions.modification.tests.ps1
@@ -403,7 +403,7 @@ Describe "Platform Matrix Replace" -Tag "replace" {
{ $parsed = ParseReplacement $query } | Should -Throw
{ $parsed = ParseReplacement $query } | Should -Throw
}
-
+
It "Should replace values in a matrix" {
$matrixJson = @'
{
@@ -542,4 +542,31 @@ Describe "Platform Matrix Replace" -Tag "replace" {
$matrix[1].parameters.Foo | Should -Be "foo2"
$matrix[1].parameters.Bar | Should -Be "bar1"
}
+
+ It "Should parse replacement syntax and source imported display name lookups" {
+ $matrixJson = @'
+{
+ "displayNames": {
+ "replaceme": ""
+ },
+ "matrix": {
+ "$IMPORT": "./test-import-matrix.json",
+ "replaceme": "replaceme"
+ }
+}
+'@
+ $importConfig = GetMatrixConfigFromJson $matrixJson
+ $replace = 'Foo=(foo)1/$1ReplacedFoo1', 'B.*=(.*)2/$1ReplacedBar2'
+ $matrix = GenerateMatrix $importConfig "sparse" -replace $replace
+
+ $matrix.Length | Should -Be 3
+ $matrix[0].name | Should -Be "fooReplacedFoo1_bar1"
+ $matrix[0].parameters.Foo | Should -Be "fooReplacedFoo1"
+ $matrix[1].name | Should -Be "foo2_barReplacedBar2"
+ $matrix[1].parameters.Bar | Should -Be "barReplacedBar2"
+ $matrix[2].name | Should -Be "importedBazName"
+ $matrix[2].parameters.Baz | Should -Be "importedBaz"
+ $matrix[2].parameters.replaceme | Should -Be "replaceme"
+ }
+
}
diff --git a/eng/pipelines/templates/jobs/archetype-sdk-client.yml b/eng/pipelines/templates/jobs/archetype-sdk-client.yml
index d24656dc3d..82079bd9ea 100644
--- a/eng/pipelines/templates/jobs/archetype-sdk-client.yml
+++ b/eng/pipelines/templates/jobs/archetype-sdk-client.yml
@@ -93,9 +93,6 @@ jobs:
workingDirectory: $(Agent.TempDirectory)
displayName: Download and Install Doxygen
- # Install dependencies required for build from vcpkg
- # TODO: We should be able to generate docs without having to install these
- # prerequisites:
- template: /eng/pipelines/templates/steps/vcpkg.yml
- template: /eng/pipelines/templates/steps/cmake-build.yml
diff --git a/eng/pipelines/templates/jobs/live.tests.yml b/eng/pipelines/templates/jobs/live.tests.yml
index 5d3ae87fae..e5272766e3 100644
--- a/eng/pipelines/templates/jobs/live.tests.yml
+++ b/eng/pipelines/templates/jobs/live.tests.yml
@@ -19,7 +19,7 @@ parameters:
default: sdk/*/*/*cov_xml.xml
- name: TimeoutInMinutes
type: number
- default: 60
+ default: 120
- name: DependsOn
type: string
default: ''
@@ -41,7 +41,7 @@ jobs:
- job: ValidateLive
dependsOn: ${{ parameters.DependsOn }}
condition: ne(${{ parameters.Matrix }}, '{}')
-
+ timeoutInMinutes: ${{ parameters.TimeoutInMinutes }}
pool:
name: $(Pool)
vmImage: $(OSVmImage)
diff --git a/eng/pipelines/templates/stages/archetype-sdk-client.yml b/eng/pipelines/templates/stages/archetype-sdk-client.yml
index 3c478076b8..5b4ae1ba76 100644
--- a/eng/pipelines/templates/stages/archetype-sdk-client.yml
+++ b/eng/pipelines/templates/stages/archetype-sdk-client.yml
@@ -25,7 +25,7 @@ parameters:
default: 'sdk/*/*/*cov_xml.xml'
- name: LiveTestTimeoutInMinutes
type: number
- default: 90
+ default: 120
- name: LineCoverageTarget
type: number
default: 95
@@ -49,8 +49,14 @@ parameters:
default:
Public:
SubscriptionConfiguration: $(sub-config-azure-cloud-test-resources)
+ # TODO: Migrate location override into azure-sdk-tools eng/common
+ # See https://github.com/Azure/azure-sdk-tools/issues/3398
+ Location: 'westus'
Preview:
SubscriptionConfiguration: $(sub-config-azure-cloud-test-resources-preview)
+ # TODO: Migrate location override into azure-sdk-tools eng/common
+ # See https://github.com/Azure/azure-sdk-tools/issues/3398
+ Location: 'westus'
Canary:
SubscriptionConfiguration: $(sub-config-azure-cloud-test-resources)
Location: 'eastus2euap'
diff --git a/eng/pipelines/templates/stages/archetype-sdk-tests.yml b/eng/pipelines/templates/stages/archetype-sdk-tests.yml
index 7cc6edb924..737de7b297 100644
--- a/eng/pipelines/templates/stages/archetype-sdk-tests.yml
+++ b/eng/pipelines/templates/stages/archetype-sdk-tests.yml
@@ -13,7 +13,7 @@ parameters:
default: sdk/*/*/*cov_xml.xml
- name: TimeoutInMinutes
type: number
- default: 60
+ default: 120
- name: Location
type: string
default: ''
diff --git a/eng/pipelines/templates/stages/platform-matrix-live.json b/eng/pipelines/templates/stages/platform-matrix-live.json
index 07787623a9..151c57a2ae 100644
--- a/eng/pipelines/templates/stages/platform-matrix-live.json
+++ b/eng/pipelines/templates/stages/platform-matrix-live.json
@@ -73,15 +73,15 @@
"Win_x86_with_unit_test_winHttp": {
"VcpkgInstall": "openssl",
"CMAKE_GENERATOR_PLATFORM": "Win32",
- "CmakeArgs": " -DBUILD_TESTING=ON -DRUN_LONG_UNIT_TESTS=ON -DBUILD_PERFORMANCE_TESTS=ON ",
+ "CmakeArgs": " -DBUILD_TESTING=ON -DRUN_LONG_UNIT_TESTS=ON -DBUILD_PERFORMANCE_TESTS=ON -DMSVC_USE_STATIC_CRT=ON ",
"VCPKG_DEFAULT_TRIPLET": "x86-windows-static",
"WindowsCtestConfig": "-C Release",
"BuildArgs": "-v --parallel 8 --config Release"
},
- "Win_x86_no_rtti_whit_unit_test": {
+ "Win_x86_no_rtti_with_unit_test": {
"VcpkgInstall": "libxml2 openssl",
"CMAKE_GENERATOR_PLATFORM": "Win32",
- "CmakeArgs": " -DBUILD_RTTI=OFF -DBUILD_TESTING=ON -DBUILD_SAMPLES=ON",
+ "CmakeArgs": " -DBUILD_RTTI=OFF -DBUILD_TESTING=ON -DBUILD_SAMPLES=ON -DMSVC_USE_STATIC_CRT=ON",
"VCPKG_DEFAULT_TRIPLET": "x86-windows-static",
"WindowsCtestConfig": "-C Release",
"BuildArgs": "-v --parallel 8 --config Release"
@@ -89,32 +89,49 @@
"Win_x86_with_unit_test_libcurl": {
"CMAKE_GENERATOR_PLATFORM": "Win32",
"VCPKG_DEFAULT_TRIPLET": "x86-windows-static",
- "CmakeArgs": " -DBUILD_TRANSPORT_CURL=ON -DBUILD_TESTING=ON -DRUN_LONG_UNIT_TESTS=ON -DBUILD_PERFORMANCE_TESTS=ON ",
+ "CmakeArgs": " -DBUILD_TRANSPORT_CURL=ON -DBUILD_TESTING=ON -DRUN_LONG_UNIT_TESTS=ON -DBUILD_PERFORMANCE_TESTS=ON -DMSVC_USE_STATIC_CRT=ON ",
"BuildArgs": "-v --parallel 8"
},
- "Win_x64_with_unit_test_winHttp": {
+ "Win_x64_with_json_unit_test_winHttp": {
"VcpkgInstall": "openssl",
"CMAKE_GENERATOR_PLATFORM": "x64",
- "CmakeArgs": " -DBUILD_TESTING=ON -DRUN_LONG_UNIT_TESTS=ON -DBUILD_PERFORMANCE_TESTS=ON ",
+ "CmakeArgs": " -DBUILD_TESTING=ON -DRUN_LONG_UNIT_TESTS=ON -DBUILD_PERFORMANCE_TESTS=ON -DDISABLE_AZURE_CORE_OPENTELEMETRY=ON ",
"BuildArgs": "-v --parallel 8 --config Release",
"AZURE_CORE_ENABLE_JSON_TESTS": 1,
"VCPKG_DEFAULT_TRIPLET": "x64-windows-static",
"WindowsCtestConfig": "-C Release"
},
- "Win_x64_with_unit_samples_winHttp": {
+ "Win_x64_with_json_unit_samples_winHttp": {
"VcpkgInstall": "openssl",
"VCPKG_DEFAULT_TRIPLET": "x64-windows-static",
"CMAKE_GENERATOR_PLATFORM": "x64",
- "CmakeArgs": " -DBUILD_TESTING=ON -DRUN_LONG_UNIT_TESTS=ON -DBUILD_PERFORMANCE_TESTS=ON -DBUILD_SAMPLES=ON ",
+ "CmakeArgs": " -DBUILD_TESTING=ON -DRUN_LONG_UNIT_TESTS=ON -DBUILD_PERFORMANCE_TESTS=ON -DBUILD_SAMPLES=ON -DDISABLE_AZURE_CORE_OPENTELEMETRY=ON ",
"BuildArgs": "-v --parallel 8 --config Release",
"AZURE_CORE_ENABLE_JSON_TESTS": 1,
"RunSamples": 1,
"WindowsCtestConfig": "-C Release"
},
+ "Win_x64_with_unit_test_winHttp": {
+ "VcpkgInstall": "openssl",
+ "CMAKE_GENERATOR_PLATFORM": "x64",
+ "CmakeArgs": " -DBUILD_TESTING=ON -DRUN_LONG_UNIT_TESTS=ON -DBUILD_PERFORMANCE_TESTS=ON -DMSVC_USE_STATIC_CRT=ON ",
+ "BuildArgs": "-v --parallel 8 --config Release",
+ "VCPKG_DEFAULT_TRIPLET": "x64-windows-static",
+ "WindowsCtestConfig": "-C Release"
+ },
+ "Win_x64_with_unit_samples_winHttp": {
+ "VcpkgInstall": "openssl",
+ "VCPKG_DEFAULT_TRIPLET": "x64-windows-static",
+ "CMAKE_GENERATOR_PLATFORM": "x64",
+ "CmakeArgs": " -DBUILD_TESTING=ON -DRUN_LONG_UNIT_TESTS=ON -DBUILD_PERFORMANCE_TESTS=ON -DBUILD_SAMPLES=ON -DMSVC_USE_STATIC_CRT=ON ",
+ "BuildArgs": "-v --parallel 8 --config Release",
+ "RunSamples": 1,
+ "WindowsCtestConfig": "-C Release"
+ },
"Win_x64_with_unit_test_libcurl": {
"VCPKG_DEFAULT_TRIPLET": "x64-windows-static",
"CMAKE_GENERATOR_PLATFORM": "x64",
- "CmakeArgs": " -DBUILD_TRANSPORT_CURL=ON -DBUILD_TESTING=ON -DRUN_LONG_UNIT_TESTS=ON -DBUILD_PERFORMANCE_TESTS=ON ",
+ "CmakeArgs": " -DBUILD_TRANSPORT_CURL=ON -DBUILD_TESTING=ON -DRUN_LONG_UNIT_TESTS=ON -DBUILD_PERFORMANCE_TESTS=ON -DMSVC_USE_STATIC_CRT=ON ",
"BuildArgs": "-v --parallel 8 --config Release",
"WindowsCtestConfig": "-C Release"
},
@@ -122,7 +139,7 @@
"VcpkgInstall": "curl[winssl] openssl",
"VCPKG_DEFAULT_TRIPLET": "x64-windows-static",
"CMAKE_GENERATOR_PLATFORM": "x64",
- "CmakeArgs": " -DBUILD_TRANSPORT_CURL=ON -DBUILD_TESTING=ON -DRUN_LONG_UNIT_TESTS=ON -DBUILD_PERFORMANCE_TESTS=ON -DBUILD_SAMPLES=ON ",
+ "CmakeArgs": " -DBUILD_TRANSPORT_CURL=ON -DBUILD_TESTING=ON -DRUN_LONG_UNIT_TESTS=ON -DBUILD_PERFORMANCE_TESTS=ON -DBUILD_SAMPLES=ON -DMSVC_USE_STATIC_CRT=ON ",
"BuildArgs": "-v --parallel 8 --config Release",
"RunSamples": 1,
"WindowsCtestConfig": "-C Release"
diff --git a/eng/pipelines/templates/stages/platform-matrix.json b/eng/pipelines/templates/stages/platform-matrix.json
index 090818cc9b..15571ad469 100644
--- a/eng/pipelines/templates/stages/platform-matrix.json
+++ b/eng/pipelines/templates/stages/platform-matrix.json
@@ -44,15 +44,15 @@
"CmakeArgs": " -DBUILD_TRANSPORT_CURL=ON"
},
"Win32Api_release_curl": {
- "CmakeArgs": " -DBUILD_TESTING=ON -DBUILD_PERFORMANCE_TESTS=ON -DRUN_LONG_UNIT_TESTS=ON -DBUILD_TRANSPORT_CURL=ON",
+ "CmakeArgs": " -DBUILD_TESTING=ON -DBUILD_PERFORMANCE_TESTS=ON -DRUN_LONG_UNIT_TESTS=ON -DBUILD_TRANSPORT_CURL=ON -DMSVC_USE_STATIC_CRT=ON",
"BuildArgs": "--parallel 8 --config Release",
"PublishMapFiles": "true"
- },
+ },
"Win32Api_debug_tests": {
- "CmakeArgs": " -DBUILD_TESTING=ON -DBUILD_PERFORMANCE_TESTS=ON -DRUN_LONG_UNIT_TESTS=ON -DBUILD_TRANSPORT_CURL=ON -DBUILD_TRANSPORT_WINHTTP=ON",
+ "CmakeArgs": " -DBUILD_TESTING=ON -DBUILD_PERFORMANCE_TESTS=ON -DRUN_LONG_UNIT_TESTS=ON -DBUILD_TRANSPORT_CURL=ON -DBUILD_TRANSPORT_WINHTTP=ON -DMSVC_USE_STATIC_CRT=ON",
"BuildArgs": "--parallel 8 --config Debug",
"PublishMapFiles": "true"
- }
+ }
},
"TargetArchitecture": {
"x86": {
@@ -72,7 +72,6 @@
"OSVmImage": "MMS2019",
"Pool": "azsdk-pool-mms-win-2019-general",
"CMAKE_GENERATOR": "Visual Studio 16 2019",
- "CmakeArgs": " -DBUILD_TRANSPORT_WINHTTP=ON ",
"PublishMapFiles": "true"
}
},
@@ -80,11 +79,13 @@
"UWP_debug": {
"CMAKE_SYSTEM_NAME": "WindowsStore",
"CMAKE_SYSTEM_VERSION": "10.0",
+ "CmakeArgs": " -DBUILD_TRANSPORT_WINHTTP=ON -DDISABLE_AZURE_CORE_OPENTELEMETRY=ON ",
"BuildArgs": "--parallel 8 --config Debug"
},
"UWP_release": {
"CMAKE_SYSTEM_NAME": "WindowsStore",
"CMAKE_SYSTEM_VERSION": "10.0",
+ "CmakeArgs": " -DBUILD_TRANSPORT_WINHTTP=ON -DDISABLE_AZURE_CORE_OPENTELEMETRY=ON ",
"BuildArgs": "--parallel 8 --config Release"
}
},
@@ -97,12 +98,12 @@
},
{
"StaticConfigs": {
- "Ubuntu18": {
- "OSVmImage": "MMSUbuntu18.04",
- "Pool": "azsdk-pool-mms-ubuntu-1804-general",
- "VCPKG_DEFAULT_TRIPLET": "x64-linux",
- "BuildArgs": "-j 10"
- }
+ "Ubuntu18": {
+ "OSVmImage": "MMSUbuntu18.04",
+ "Pool": "azsdk-pool-mms-ubuntu-1804-general",
+ "VCPKG_DEFAULT_TRIPLET": "x64-linux",
+ "BuildArgs": "-j 10"
+ }
},
"BuildSettings": {
"gpp-5": {
diff --git a/eng/pipelines/templates/steps/vcpkg-publish.yml b/eng/pipelines/templates/steps/vcpkg-publish.yml
index dbf9f7ccad..e732f5aded 100644
--- a/eng/pipelines/templates/steps/vcpkg-publish.yml
+++ b/eng/pipelines/templates/steps/vcpkg-publish.yml
@@ -46,7 +46,7 @@ steps:
-GitCommitParameters '-c user.name="azure-sdk" -c user.email="azuresdk@microsoft.com"'
-DailyRelease:$${{ parameters.DailyRelease }}
workingDirectory: ${{ parameters.Workspace }}/vcpkg
- condition: and(succeeded(), eq(variables['PublishToVcpkg'], 'true'))
+ condition: and(succeeded(), eq(variables['PublishToVcpkg'], 'true'))
displayName: Update vcpkg port ${{ parameters.DisplayNameExtension }}
# On package release vcpkg beta should always be updated
diff --git a/eng/pipelines/templates/steps/vcpkg.yml b/eng/pipelines/templates/steps/vcpkg.yml
index 687bac23b3..54ad698c4b 100644
--- a/eng/pipelines/templates/steps/vcpkg.yml
+++ b/eng/pipelines/templates/steps/vcpkg.yml
@@ -1,16 +1,5 @@
steps:
- pwsh: |
- $TargetPath = "$(Agent.TempDirectory)/vcpkg"
- Remove-Item -Path $TargetPath -Recurse -Force -ErrorAction Ignore
- New-Item -ItemType Directory -Path $TargetPath -Force
-
- $VcpkgCommit = $(Get-Content eng/vcpkg-commit.txt)
- Write-Host "Target Path for vcpkg: $TargetPath"
- Write-Host "Vcpkg SHA: $VcpkgCommit"
-
- Write-Host "##vso[task.prependpath]$TargetPath"
- Write-Host "##vso[task.setvariable variable=VCPKG_INSTALLATION_ROOT]$TargetPath"
- Write-Host "##vso[task.setvariable variable=VcpkgCommit]$VcpkgCommit"
Write-Host "##vso[task.setvariable variable=VCPKG_BINARY_SOURCES_SECRET;issecret=true;]clear;x-azblob,https://cppvcpkgcache.blob.core.windows.net/public-vcpkg-container,,read"
displayName: Set Vcpkg Variables
@@ -22,12 +11,3 @@ steps:
arguments: -StorageAccountKey '$(cpp-vcpkg-cache-storage-key)'
displayName: Set Vcpkg Write-mode Cache
condition: and(succeeded(), eq(variables['System.TeamProject'], 'internal'))
-
- - task: PowerShell@2
- inputs:
- targetType: filePath
- filePath: eng/scripts/vcpkg.ps1
- arguments: >-
- -Ref $(VcpkgCommit)
- -VcpkgPath $(VCPKG_INSTALLATION_ROOT)
- pwsh: true
diff --git a/eng/scripts/Get-ApiViewCommandLine.ps1 b/eng/scripts/Get-ApiViewCommandLine.ps1
new file mode 100644
index 0000000000..9359416cfa
--- /dev/null
+++ b/eng/scripts/Get-ApiViewCommandLine.ps1
@@ -0,0 +1,53 @@
+# Copyright (c) Microsoft Corporation. All rights reserved.
+# SPDX-License-Identifier: MIT
+
+# Usage: Get-ApiViewCommandLine.ps1 .\azure-sdk-for-cpp azure-identity
+# Or: ..\Get-ApiViewCommandLine.ps1 . azure-core
+# Or: Get-ApiViewCommandLine.ps1 ..\.. azure-security-attestation
+# Or: c:\src\azure-sdk-for-cpp\eng\scripts\Get-ApiViewCommandLine.ps1 c:\src\azure-sdk-for-cpp azure-identity
+
+param([String]$RepoPath, [String]$LibName)
+
+[String]$SdkRoot = Resolve-Path ($RepoPath + "\sdk")
+
+[String[]]$AllIncDirs = Get-ChildItem -Directory -Filter "inc" -Recurse $SdkRoot | Select-Object -ExpandProperty FullName
+
+[String[]]$AllIncDirsWithoutInc = $AllIncDirs | Select-Object @{ Label="Substr"; Expression = { $_.Substring(0, $_.Length - "inc".Length) } } | Select-Object -ExpandProperty Substr
+
+[String[]]$AllLibIncDirs = @()
+for($i = 0; $i -lt $AllIncDirsWithoutInc.Length; $i++) {
+ $isLibDir = $true
+ $libDir = $AllIncDirsWithoutInc[$i]
+ for($j = 0; $j -lt $AllIncDirsWithoutInc.Length; $j++) {
+ if ($i -eq $j) {
+ continue
+ }
+
+ $StartsWith = $AllIncDirsWithoutInc[$j] + "*"
+ if ($libDir -Like $StartsWith) {
+ $isLibDir = $false
+ break
+ }
+ }
+
+ if ($isLibDir){
+ $AllLibIncDirs += $libDir + "inc"
+ }
+}
+
+[String]$LibIncDir = $AllLibIncDirs | Where-Object {$_ -Match ("\\" + $LibName + "\\inc") } | Select-Object -First 1
+
+[String[]]$LibHeaders = Get-ChildItem -File -Recurse $LibIncDir | Select-Object -ExpandProperty FullName
+
+$CmdLine = "clang++"
+foreach ($header in $LibHeaders) {
+ $CmdLine += " " + $header
+}
+
+$CmdLine += " -Xclang -ast-dump"
+
+foreach ($incDir in $AllLibIncDirs) {
+ $CmdLine += " -I " + $incDir
+}
+
+$CmdLine
diff --git a/eng/scripts/vcpkg.ps1 b/eng/scripts/vcpkg.ps1
deleted file mode 100644
index 41b1885edc..0000000000
--- a/eng/scripts/vcpkg.ps1
+++ /dev/null
@@ -1,27 +0,0 @@
-[CmdletBinding()]
-Param (
- [Parameter()]
- [ValidateNotNullOrEmpty()]
- [string] $Ref = (Get-Content "$PSScriptRoot/../vcpkg-commit.txt"),
-
- [Parameter()]
- [ValidateNotNullOrEmpty()]
- [string] $VcpkgPath = "$PSScriptRoot/../../vcpkg"
-)
-
-$initialDirectory = Get-Location
-
-try {
- git clone https://github.com/Microsoft/vcpkg $VcpkgPath
- Set-Location $VcpkgPath
- git fetch --tags
- git checkout $Ref
-
- if ($IsWindows) {
- .\bootstrap-vcpkg.bat
- } else {
- ./bootstrap-vcpkg.sh
- }
-} finally {
- Set-Location $initialDirectory
-}
diff --git a/eng/vcpkg-commit.txt b/eng/vcpkg-commit.txt
deleted file mode 100644
index 428f461f18..0000000000
--- a/eng/vcpkg-commit.txt
+++ /dev/null
@@ -1 +0,0 @@
-f0aa678b7471497f1adedcc99f40e1599ad22f69
diff --git a/samples/helpers/service/CMakeLists.txt b/samples/helpers/service/CMakeLists.txt
index 8f25a20ca3..af8944052b 100644
--- a/samples/helpers/service/CMakeLists.txt
+++ b/samples/helpers/service/CMakeLists.txt
@@ -10,8 +10,11 @@ set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
add_library(
service
- INTERFACE
+ OBJECT
inc/azure/service/client.hpp
-)
+ src/client.cpp
+ )
-target_include_directories(service INTERFACE inc)
+ target_link_libraries(service PUBLIC azure-core)
+
+target_include_directories(service PUBLIC inc)
diff --git a/samples/helpers/service/inc/azure/service/client.hpp b/samples/helpers/service/inc/azure/service/client.hpp
index b489445ce3..e28b0f687b 100644
--- a/samples/helpers/service/inc/azure/service/client.hpp
+++ b/samples/helpers/service/inc/azure/service/client.hpp
@@ -3,9 +3,11 @@
#pragma once
+#include
#include
#include
+#include
#include
namespace Azure { namespace Service {
@@ -26,32 +28,13 @@ namespace Azure { namespace Service {
static_cast(serviceUrl); // to suppress the "unused variable" warning.
}
- void DoSomething(const Core::Context& context) const
- {
- static_cast(context); // to suppress the "unused variable" warning.
-
- // This method does nothing, because the purpose of this class is to demonstrate
- // how Azure::Identity classes can be used with a generic Azure SDK service client.
- // If we have code here that gets the token, it would be up to the user to set it up to be
- // valid enough to get a token, which is not critical for the intended demonstration purposes.
- // And if user runs this, and authentication is unsuccessful, it may draw an unnecessary
- // attention to an irrelevant (to the demo) point.
-
- // But an oversimplified logic of what a typical Azure SDK client does is below:
-#if (0)
- // Every client has its own scope. We use management.azure.com here as an example.
- Core::Credentials::TokenRequestContext azureServiceClientContext;
- azureServiceClientContext.Scopes = {"https://management.azure.com/"};
-
- auto authenticationToken = m_credential->GetToken(azureServiceClientContext, context);
-
- // Now that it has a token, Client can authorize and DoSomething().
- // ...
- // ...
-
- static_cast(authenticationToken); // to suppress the "unused variable" warning.
-#endif
- }
+ // This method does nothing, because the purpose of this class is to demonstrate how
+ // Azure::Identity classes can be used with a generic Azure SDK service client. If we have code
+ // here that gets the token, it would be up to the user to set it up to be valid enough to get a
+ // token, which is not critical for the intended demonstration purposes. And if user runs this,
+ // and authentication is unsuccessful, it may draw an unnecessary attention to an irrelevant (to
+ // the demo) point.
+ void DoSomething(const Core::Context& context) const;
};
}} // namespace Azure::Service
diff --git a/samples/helpers/service/src/client.cpp b/samples/helpers/service/src/client.cpp
new file mode 100644
index 0000000000..6d86975216
--- /dev/null
+++ b/samples/helpers/service/src/client.cpp
@@ -0,0 +1,24 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+#include "azure/service/client.hpp"
+
+void Azure::Service::Client::DoSomething(const Azure::Core::Context& context) const
+{
+ static_cast(context); // to suppress the "unused variable" warning.
+
+ // An oversimplified logic of what a typical Azure SDK client does is below:
+#if (0)
+ // Every client has its own scope. We use management.azure.com here as an example.
+ Core::Credentials::TokenRequestContext azureServiceClientContext;
+ azureServiceClientContext.Scopes = {"https://management.azure.com/"};
+
+ auto authenticationToken = m_credential->GetToken(azureServiceClientContext, context);
+
+ // Now that it has a token, Client can authorize and DoSomething().
+ // ...
+ // ...
+
+ static_cast(authenticationToken); // to suppress the "unused variable" warning.
+#endif
+}
diff --git a/samples/integration/vcpkg-all-smoke/src/main.cpp b/samples/integration/vcpkg-all-smoke/src/main.cpp
index 09f2445512..678fe23126 100644
--- a/samples/integration/vcpkg-all-smoke/src/main.cpp
+++ b/samples/integration/vcpkg-all-smoke/src/main.cpp
@@ -9,6 +9,7 @@
#include "get_env.hpp"
#include
#include
+#include
#include
#include
#include
@@ -30,11 +31,16 @@ using namespace Azure::Security::Attestation;
int main()
{
- const std::string tenantId = "tenant";
- const std::string clientId = "client";
- const std::string clientSecret = "secret";
+ auto tenantId = std::getenv("AZURE_TENANT_ID");
+ auto clientId = std::getenv("AZURE_CLIENT_ID");
+ auto clientSecret = std::getenv("AZURE_CLIENT_SECRET");
const std::string leaseID = "leaseID";
const std::string smokeUrl = "https://blob.com";
+ // Creating an attestation service instance requires contacting the attestation service (to
+ // retrieve validation collateral). Use the West US Shared client (which should always be
+ // available) as an anonymous service instance.
+ const std::string attestationUrl = "https://sharedwus.wus.attest.azure.net";
+
auto credential
= std::make_shared(tenantId, clientId, clientSecret);
@@ -43,9 +49,9 @@ int main()
{
std::cout << "Creating Keyvault Clients" << std::endl;
// keyvault
- KeyClient keyClient(std::getenv("AZURE_KEYVAULT_URL"), credential);
- SecretClient secretClient(std::getenv("AZURE_KEYVAULT_URL"), credential);
- CertificateClient certificateClient(std::getenv("AZURE_KEYVAULT_URL"), credential);
+ KeyClient keyClient(smokeUrl, credential);
+ SecretClient secretClient(smokeUrl, credential);
+ CertificateClient certificateClient(smokeUrl, credential);
std::cout << "Creating Storage Clients" << std::endl;
// Storage
@@ -69,9 +75,11 @@ int main()
// Attestation
std::cout << "Creating Attestation Clients" << std::endl;
- AttestationClient attestationClient(AttestationClient::Create(smokeUrl));
+
AttestationAdministrationClient attestationAdminClient(
- AttestationAdministrationClient::Create(smokeUrl, credential));
+ AttestationAdministrationClient::Create(attestationUrl, credential));
+
+ AttestationClient attestationClient(AttestationClient::Create(attestationUrl));
std::cout << "Successfully Created the Clients" << std::endl;
}
diff --git a/samples/integration/vcpkg-keyvault/.devcontainer/Dockerfile b/samples/integration/vcpkg-keyvault/.devcontainer/Dockerfile
deleted file mode 100644
index e5f5ca09ab..0000000000
--- a/samples/integration/vcpkg-keyvault/.devcontainer/Dockerfile
+++ /dev/null
@@ -1,7 +0,0 @@
-# base image installs keyvault beta1 from vcpkg only
-FROM vhvb1989/keyvault:beta1
-
-RUN cd vcpkg \
- && sudo ./vcpkg install azure-identity-cpp
-
-ENV VCPKG_DEFAULT_TRIPLET=x64-linux
diff --git a/samples/integration/vcpkg-keyvault/.devcontainer/devcontainer.json b/samples/integration/vcpkg-keyvault/.devcontainer/devcontainer.json
deleted file mode 100644
index 0dd126a6d8..0000000000
--- a/samples/integration/vcpkg-keyvault/.devcontainer/devcontainer.json
+++ /dev/null
@@ -1,20 +0,0 @@
-{
- "name": "Ubuntu-21.04",
- "dockerFile": "Dockerfile",
- "settings": {
- "terminal.integrated.shell.linux": "/bin/bash"
- },
- "extensions": [
- "ms-vscode.cpptools-themes",
- "bbenoist.doxygen",
- "streetsidesoftware.code-spell-checker",
- "ms-vscode.cpptools",
- "xaver.clang-format",
- "twxs.cmake",
- "ms-vscode.cmake-tools",
- "eamodio.gitlens",
- "davidschuldenfrei.gtest-adapter"
- ],
- // Do not run as root. See https://aka.ms/vscode-remote/containers/non-root.
- "remoteUser": "azure-sdk-for-cpp"
-}
diff --git a/samples/integration/vcpkg-keyvault/CMakeLists.txt b/samples/integration/vcpkg-keyvault/CMakeLists.txt
deleted file mode 100644
index 1707c6a2c7..0000000000
--- a/samples/integration/vcpkg-keyvault/CMakeLists.txt
+++ /dev/null
@@ -1,30 +0,0 @@
-# Copyright (c) Microsoft Corporation. All rights reserved.
-# SPDX-License-Identifier: MIT
-
-# vcpkg integration.
-if(DEFINED ENV{VCPKG_ROOT} AND NOT DEFINED CMAKE_TOOLCHAIN_FILE)
- set(CMAKE_TOOLCHAIN_FILE "$ENV{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake"
- CACHE STRING "")
-endif()
-if(DEFINED ENV{VCPKG_DEFAULT_TRIPLET} AND NOT DEFINED VCPKG_TARGET_TRIPLET)
- set(VCPKG_TARGET_TRIPLET "$ENV{VCPKG_DEFAULT_TRIPLET}" CACHE STRING "")
-endif()
-
-# Project set up
-cmake_minimum_required(VERSION 3.13)
-project(Application-using-keyvault-from-vcpkg LANGUAGES CXX)
-set(CMAKE_CXX_STANDARD 14)
-set(CMAKE_CXX_STANDARD_REQUIRED True)
-
-add_executable (
- application
- src/main
-)
-
-# Link to Azure SDK
-target_link_libraries(application
- PRIVATE
- Azure::azure-security-keyvault-keys
- Azure::azure-identity
- get-env-helper
-)
diff --git a/samples/integration/vcpkg-keyvault/LICENSE b/samples/integration/vcpkg-keyvault/LICENSE
deleted file mode 100644
index 51b6a76e54..0000000000
--- a/samples/integration/vcpkg-keyvault/LICENSE
+++ /dev/null
@@ -1,21 +0,0 @@
- MIT License
-
- Copyright (c) Microsoft Corporation. All rights reserved.
-
- Permission is hereby granted, free of charge, to any person obtaining a copy
- of this software and associated documentation files (the "Software"), to deal
- in the Software without restriction, including without limitation the rights
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- copies of the Software, and to permit persons to whom the Software is
- furnished to do so, subject to the following conditions:
-
- The above copyright notice and this permission notice shall be included in all
- copies or substantial portions of the Software.
-
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- SOFTWARE.
diff --git a/samples/integration/vcpkg-keyvault/README.md b/samples/integration/vcpkg-keyvault/README.md
deleted file mode 100644
index dd7e4b7054..0000000000
--- a/samples/integration/vcpkg-keyvault/README.md
+++ /dev/null
@@ -1,67 +0,0 @@
-# Integrating the Azure SDK for C++ into your application using vcpkg
-
-This application shows how to integrate the Azure SDK for C++ in your application. It uses vcpkg to acquire and build the Azure SDK for C++ client libraries. Your CMake project needs to link the libraries from vcpkg by setting the toolchain file to vcpkg (shown below).
-
-## Pre-requisites
-
-There are two options to set up the development environment:
-
-### Manual installation
-
-Install the [Azure SDK for C++ dependencies](https://github.com/Azure/azure-sdk-for-cpp/blob/main/CONTRIBUTING.md#third-party-dependencies).
-
-- CMake project (min version 3.13).
-- C++ version 14 or greater.
-
-### Container
-
-The sample provides a .devcontainer folder which can be used by VS Code to build and run a docker container with the required C++ build tools and with vcpkg installed.
-
-This method requires VS Code + [Remote Container](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers) to be installed in the system. Also make sure to have Docker installed and running. This method works for any operating system where Docker and VSCode is supported like Windows, Linux and macOS. The development environment will be Debian 10.
-
-- Open vcpkg folder in VS Code.
-- VS Code will detect the `devcontainer` configuration and ask you if you would like to re-open the folder in a container. Click Yes.
-- If VS Code did not ask, you can press F1 and type `Reopen in container` option.
-
-Once VS Code builds and run the container, open the terminal and continue to build step.
-
-> Note: The container is set up to automatically link vcpkg to CMake projects by setting env variables that the CMake sample project will use to set the toolchain.
-
-## Build
-
-### Linux terminal
-
-```bash
-#
-# Building the application.
-# Instructions from application root directory.
-#
-
-# Create build directory just the first time.
-mkdir build
-cd build
-
-# Generate and build
-# This code assumes that the SDK dependencies were installed with vcpkg
-# When using docker provided container, the TOOLCHAIN option is not required (cmake ..).
-cmake -DCMAKE_TOOLCHAIN_FILE=path/to/vcpkg/scripts/buildsystems/vcpkg.cmake ..
-cmake -build .
-```
-
-### Windows VS
-
-If you are using Visual Studio, the toolchain to link vcpkg is set with `CMakeSettings.json`. Update this file and set the vcpkg toolchain file for vcpkg (VCPKG_ROOT\scripts\buildsystems\vcpkg.cmake). After setting the toolchain, VS can generate and build the sample. Use VS to open the sample folder only.
-
-## Run application
-
-Review source code header for `environment variables` that must be set up before running the app.
-
-```bash
-#
-# Running the Application
-# Instructions from inside the build directory.
-#
-
-# Run binary (.exe on Windows)
-./application
-```
diff --git a/samples/integration/vcpkg-keyvault/src/main.cpp b/samples/integration/vcpkg-keyvault/src/main.cpp
deleted file mode 100644
index 541a95160c..0000000000
--- a/samples/integration/vcpkg-keyvault/src/main.cpp
+++ /dev/null
@@ -1,83 +0,0 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// SPDX-License-Identifier: MIT
-
-/**
- * @brief This sample provides the code implementation to use the Key Vault SDK client for C++
- * to create, get, update, delete and purge a key.
- *
- * @remark The following environment variables must be set before running the sample.
- * - AZURE_KEYVAULT_URL: To the Key Vault account URL.
- * - AZURE_TENANT_ID: Tenant ID for the Azure account.
- * - AZURE_CLIENT_ID: The Client ID to authenticate the request.
- * - AZURE_CLIENT_SECRET: The client secret.
- *
- */
-
-#include "get_env.hpp"
-
-#include
-#include
-#include
-
-#include
-#include
-#include
-#include
-
-using namespace Azure::Security::KeyVault::Keys;
-
-int main()
-{
- auto tenantId = std::getenv("AZURE_TENANT_ID");
- auto clientId = std::getenv("AZURE_CLIENT_ID");
- auto clientSecret = std::getenv("AZURE_CLIENT_SECRET");
- auto credential
- = std::make_shared(tenantId, clientId, clientSecret);
-
- KeyClient keyClient(std::getenv("AZURE_KEYVAULT_URL"), credential);
-
- std::string rsaKeyName("CloudRsaKey" + Azure::Core::Uuid::CreateUuid().ToString());
- try
- {
- auto rsaKey = CreateRsaKeyOptions(rsaKeyName);
- rsaKey.KeySize = 2048;
- rsaKey.ExpiresOn = std::chrono::system_clock::now() + std::chrono::hours(24 * 365);
-
- keyClient.CreateRsaKey(rsaKey);
-
- KeyVaultKey cloudRsaKey = keyClient.GetKey(rsaKeyName).Value;
- std::cout << "Key is returned with name " << cloudRsaKey.Name() << " and type "
- << cloudRsaKey.GetKeyType().ToString() << std::endl;
-
- cloudRsaKey.Properties.ExpiresOn
- = cloudRsaKey.Properties.ExpiresOn.Value() + std::chrono::hours(24 * 365);
- KeyVaultKey updatedKey = keyClient.UpdateKeyProperties(cloudRsaKey.Properties).Value;
- std::cout << "Key's updated expiry time is " << updatedKey.Properties.ExpiresOn->ToString()
- << std::endl;
-
- CreateRsaKeyOptions newRsaKey(rsaKeyName);
- newRsaKey.KeySize = 4096;
- newRsaKey.ExpiresOn = std::chrono::system_clock::now() + std::chrono::hours(24 * 365);
-
- keyClient.CreateRsaKey(newRsaKey);
-
- DeleteKeyOperation operation = keyClient.StartDeleteKey(rsaKeyName);
-
- // You only need to wait for completion if you want to purge or recover the key.
- operation.PollUntilDone(std::chrono::milliseconds(2000));
-
- keyClient.PurgeDeletedKey(rsaKeyName);
- }
- catch (Azure::Core::Credentials::AuthenticationException const& e)
- {
- std::cout << "Authentication Exception happened:" << std::endl << e.what() << std::endl;
- return 1;
- }
- catch (Azure::Core::RequestFailedException const& e)
- {
- std::cout << "KeyVault Client Exception happened:" << std::endl << e.Message << std::endl;
- return 1;
- }
-
- return 0;
-}
diff --git a/samples/integration/vcpkg-storage/.devcontainer/Dockerfile b/samples/integration/vcpkg-storage/.devcontainer/Dockerfile
deleted file mode 100644
index 2bac8b8507..0000000000
--- a/samples/integration/vcpkg-storage/.devcontainer/Dockerfile
+++ /dev/null
@@ -1,14 +0,0 @@
-# base image installs dev env for storage v12 beta10
-FROM vhvb1989/storage12:preview10
-
-# Get vcpkg and install storage blobs
-RUN sudo git clone https://github.com/microsoft/vcpkg.git \
- && cd vcpkg \
- # VCPKG commit version for key vault keys 1.0.0-beta.1 - Storage beta 10 - Identity beta 5 - Core beta 8
- && sudo git checkout 414bec05f2a97cfc0ddb8e22fd4635dfe2a20ab8 \
- && sudo ./bootstrap-vcpkg.sh
-
-ENV VCPKG_ROOT=/vcpkg
-
-RUN cd vcpkg \
- && sudo ./vcpkg install azure-storage-blobs-cpp
diff --git a/samples/integration/vcpkg-storage/.devcontainer/devcontainer.json b/samples/integration/vcpkg-storage/.devcontainer/devcontainer.json
deleted file mode 100644
index a1a73de699..0000000000
--- a/samples/integration/vcpkg-storage/.devcontainer/devcontainer.json
+++ /dev/null
@@ -1,20 +0,0 @@
-{
- "name": "AzureSDK-Storage-v12-beta10",
- "dockerFile": "Dockerfile",
- "settings": {
- "terminal.integrated.shell.linux": "/bin/bash"
- },
- "extensions": [
- "ms-vscode.cpptools-themes",
- "bbenoist.doxygen",
- "streetsidesoftware.code-spell-checker",
- "ms-vscode.cpptools",
- "xaver.clang-format",
- "twxs.cmake",
- "ms-vscode.cmake-tools",
- "eamodio.gitlens",
- "davidschuldenfrei.gtest-adapter"
- ],
- // Do not run as root. See https://aka.ms/vscode-remote/containers/non-root.
- "remoteUser": "azure-sdk-for-cpp"
-}
diff --git a/samples/integration/vcpkg-storage/CMakeLists.txt b/samples/integration/vcpkg-storage/CMakeLists.txt
deleted file mode 100644
index c6ca69c645..0000000000
--- a/samples/integration/vcpkg-storage/CMakeLists.txt
+++ /dev/null
@@ -1,32 +0,0 @@
-# Copyright (c) Microsoft Corporation. All rights reserved.
-# SPDX-License-Identifier: MIT
-
-# vcpkg integration.
-if(DEFINED ENV{VCPKG_ROOT} AND NOT DEFINED CMAKE_TOOLCHAIN_FILE)
- set(CMAKE_TOOLCHAIN_FILE "$ENV{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake"
- CACHE STRING "")
-endif()
-if(DEFINED ENV{VCPKG_DEFAULT_TRIPLET} AND NOT DEFINED VCPKG_TARGET_TRIPLET)
- set(VCPKG_TARGET_TRIPLET "$ENV{VCPKG_DEFAULT_TRIPLET}" CACHE STRING "")
-endif()
-
-# Project set up
-cmake_minimum_required(VERSION 3.13)
-project(Application-using-storage-blobs-from-vcpkg LANGUAGES CXX)
-set(CMAKE_CXX_STANDARD 14)
-set(CMAKE_CXX_STANDARD_REQUIRED True)
-
-find_package(CURL REQUIRED)
-find_package(azure-storage-blobs-cpp CONFIG REQUIRED)
-
-add_executable (
- application
- src/main
-)
-
-# Link to Azure SDK
-target_link_libraries(application
- PRIVATE
- Azure::azure-storage-blobs
- get-env-helper
-)
diff --git a/samples/integration/vcpkg-storage/LICENSE b/samples/integration/vcpkg-storage/LICENSE
deleted file mode 100644
index 51b6a76e54..0000000000
--- a/samples/integration/vcpkg-storage/LICENSE
+++ /dev/null
@@ -1,21 +0,0 @@
- MIT License
-
- Copyright (c) Microsoft Corporation. All rights reserved.
-
- Permission is hereby granted, free of charge, to any person obtaining a copy
- of this software and associated documentation files (the "Software"), to deal
- in the Software without restriction, including without limitation the rights
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- copies of the Software, and to permit persons to whom the Software is
- furnished to do so, subject to the following conditions:
-
- The above copyright notice and this permission notice shall be included in all
- copies or substantial portions of the Software.
-
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- SOFTWARE.
diff --git a/samples/integration/vcpkg-storage/README.md b/samples/integration/vcpkg-storage/README.md
deleted file mode 100644
index a1c4e78988..0000000000
--- a/samples/integration/vcpkg-storage/README.md
+++ /dev/null
@@ -1,67 +0,0 @@
-# Integrating the Azure SDK for C++ into your application using vcpkg
-
-This application shows how to integrate the Azure SDK for C++ in your application. It uses vcpkg to adquire and build the Azure SDK for C++ client libraries. Your CMake project needs to link the libraries from vcpkg by setting the toolchain file to vcpkg (shown below).
-
-## Pre-requisites
-
-There are two options to set up the development environment:
-
-### Manual installation
-
-Install the [Azure SDK for C++ dependencies](https://github.com/Azure/azure-sdk-for-cpp/blob/main/CONTRIBUTING.md#third-party-dependencies).
-
-- CMake project (min version 3.13).
-- C++ version 14 or greater.
-
-### Container
-
-The sample provides a .devcontainer folder which can be used by VS Code to build and run a docker container with the required C++ build tools and with vcpkg installed.
-
-This method requires VS Code + [Remote Container](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers) to be installed in the system. Also make sure to have Docker installed and running. This method works for any operating system where Docker and VS Code is supported like Windows, Linux and macOS. The development environment will be Debian 10.
-
-- Open vcpkg folder in VS Code.
-- VS Code will detect the `devcontainer` configuration and ask you if you would like to re-open the folder in a container. Click Yes.
-- If VS Code did not ask, you can press F1 and type `Reopen in container` option.
-
-Once VS Code builds and run the container, open the terminal and continue to build step.
-
-> Note: The container is set up to automatically link vcpkg to CMake projects by setting env variables that the CMake sample project will use to set the toolchain.
-
-## Build
-
-### Linux terminal
-
-```bash
-#
-# Building the application.
-# Instructions from application root directory.
-#
-
-# Create build directory just the first time.
-mkdir build
-cd build
-
-# Generate and build
-# This code assumes that the SDK dependencies were installed with vcpkg
-# When using docker provided container, the TOOLCHAIN option is not required (cmake ..).
-cmake -DCMAKE_TOOLCHAIN_FILE=path/to/vcpkg/scripts/buildsystems/vcpkg.cmake ..
-cmake -build .
-```
-
-### Windows VS
-
-If you are using Visual Studio, the toolchain to link vcpkg is set with `CMakeSettings.json`. Upate this file and set the vcpkg toolchain file for vcpkg (VCPKG_ROOT\scripts\buildsystems\vcpkg.cmake). After setting the toolchain, VS can generate and build the sample. Use VS to open the sample folder only.
-
-## Run application
-
-Review source code header for `environment variables` that must be set up before running the app.
-
-```bash
-#
-# Running the Application
-# Instructions from inside the build directory.
-#
-
-# Run binary (.exe on Windows)
-./application
-```
diff --git a/samples/integration/vcpkg-storage/src/main.cpp b/samples/integration/vcpkg-storage/src/main.cpp
deleted file mode 100644
index 7d7f873a89..0000000000
--- a/samples/integration/vcpkg-storage/src/main.cpp
+++ /dev/null
@@ -1,69 +0,0 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// SPDX-License-Identifier: MIT
-
-/**
- * @brief This sample provides the code implementation to use the Storage blobs SDK client for C++
- * to create a container and upload a blob to it.
- *
- * @remark The following environment variables must be set before running the sample.
- * - AZURE_STORAGE_CONNECTION_STRING: Set it Azure Storage connection string.
- *
- */
-
-#include "get_env.hpp"
-
-#include
-
-#include
-
-const std::string& GetConnectionString();
-
-int main()
-{
- using namespace Azure::Storage::Blobs;
-
- std::string containerName = "sample-container";
- std::string blobName = "sample-blob";
- std::string blobContent = "Hello Azure!";
-
- auto containerClient
- = BlobContainerClient::CreateFromConnectionString(GetConnectionString(), containerName);
-
- containerClient.CreateIfNotExists();
-
- BlockBlobClient blobClient = containerClient.GetBlockBlobClient(blobName);
-
- blobClient.UploadFrom(reinterpret_cast(blobContent.data()), blobContent.size());
-
- Azure::Storage::Metadata blobMetadata = {{"key1", "value1"}, {"key2", "value2"}};
- blobClient.SetMetadata(blobMetadata);
-
- auto properties = blobClient.GetProperties().Value;
- for (auto metadata : properties.Metadata)
- {
- std::cout << metadata.first << ":" << metadata.second << std::endl;
- }
- blobContent.resize(static_cast(properties.BlobSize));
-
- blobClient.DownloadTo(reinterpret_cast(&blobContent[0]), blobContent.size());
-
- std::cout << blobContent << std::endl;
-
- return 0;
-}
-
-const std::string& GetConnectionString()
-{
- const static std::string ConnectionString = "";
-
- if (!ConnectionString.empty())
- {
- return ConnectionString;
- }
- const static std::string envConnectionString = std::getenv("AZURE_STORAGE_CONNECTION_STRING");
- if (!envConnectionString.empty())
- {
- return envConnectionString;
- }
- throw std::runtime_error("Cannot find connection string");
-}
diff --git a/sdk/attestation/azure-security-attestation/CHANGELOG.md b/sdk/attestation/azure-security-attestation/CHANGELOG.md
index b6dc5d1a46..ee807ef860 100644
--- a/sdk/attestation/azure-security-attestation/CHANGELOG.md
+++ b/sdk/attestation/azure-security-attestation/CHANGELOG.md
@@ -1,6 +1,6 @@
# Release History
-## 1.0.0-beta.3 (Unreleased)
+## 1.0.0-beta.4 (Unreleased)
### Features Added
@@ -10,6 +10,16 @@
### Other Changes
+## 1.0.0-beta.3 (2022-06-07)
+
+### Breaking Changes
+
+- `ValueToSend` field in `TpmAttestationOptions` becomes `Payload`.
+- `AddIsolatedModeCertificatesOptions` becomes `AddIsolatedModeCertificateOptions`
+- `RemoveIsolatedModeCertificatesOptions` becomes `RemoveIsolatedModeCertificateOptions`
+- Renamed `AttestEnclaveOptions` to `AttestSgxEnclaveOptions` and `AttestOpenEnclaveOptions`.
+- `AttestationClient` and `AttestationAdministrationClient` creation is now done using the factory method `AttestationClient::Create()` and `AttestationAdministrationClient::Create()`.
+
## 1.0.0-beta.2 (2022-05-10)
### Breaking Changes
diff --git a/sdk/attestation/azure-security-attestation/README.md b/sdk/attestation/azure-security-attestation/README.md
index dc56554408..a04514ca14 100644
--- a/sdk/attestation/azure-security-attestation/README.md
+++ b/sdk/attestation/azure-security-attestation/README.md
@@ -1,3 +1,7 @@
+---
+# cspell:words opentelemetry
+---
+
# Azure Attestation Package client library for C++
Microsoft Azure Attestation is a unified solution for remotely verifying the trustworthiness of a platform and integrity of the binaries running inside it. The service supports attestation of the platforms backed by Trusted Platform Modules (TPMs) alongside the ability to attest to the state of Trusted Execution Environments (TEEs) such as Intel(tm) Software Guard Extensions (SGX) enclaves and Virtualization-based Security (VBS) enclaves.
@@ -210,18 +214,17 @@ The `AttestationClient::Create` method is used to create instances of the attest
```cpp
std::string endpoint = std::getenv("ATTESTATION_AAD_URL");
- return Azure::Security::Attestation::AttestationClient::CreatePointer(m_endpoint);
+ Azure::Security::Attestation::AttestationClient client = Azure::Security::Attestation::AttestationClient::Create(m_endpoint);
```
-If the attestation APIs require authentication, use the following (note that unlike the previous example,
-which returns a pointer to the client, this returns the client by value):
+If the attestation APIs require authentication, use the following:
```cpp
std::string endpoint = std::getenv("ATTESTATION_AAD_URL");
std::shared_ptr credential
= std::make_shared(
std::getenv("AZURE_TENANT_ID"), std::getenv("AZURE_CLIENT_ID"), std::getenv("AZURE_CLIENT_SECRET"));
-return Azure::Security::Attestation::AttestationClient::Create(m_endpoint, credential);
+auto client = Azure::Security::Attestation::AttestationClient::Create(m_endpoint, credential);
```
The same pattern is used to create an `Azure::Security::Attestation::AttestationAdministrationClient`.
@@ -236,7 +239,7 @@ attestation service, however the APIs are provided for completeness and to facil
attestation results.
```cpp
-auto validationCertificates = attestationClient->GetTokenValidationCertificates();
+auto validationCertificates = attestationClient.GetTokenValidationCertificates();
// Enumerate the signers.
for (const auto& signer : validationCertificates.Value.Signers)
{
@@ -267,7 +270,7 @@ std::string endpoint = std::getenv("ATTESTATION_AAD_URL");
std::shared_ptr credential
= std::make_shared(
std::getenv("AZURE_TENANT_ID"), std::getenv("AZURE_CLIENT_ID"), std::getenv("AZURE_CLIENT_SECRET"));
-AttestationAdministrationClient adminClient(m_endpoint, credential);
+AttestationAdministrationClient adminClient(AttestationAdministrationClient::Create(m_endpoint, credential));
```
#### Retrieve current attestation policy for OpenEnclave
@@ -275,9 +278,6 @@ AttestationAdministrationClient adminClient(m_endpoint, credential);
Use the `GetAttestationPolicy` API to retrieve the current attestation policy for a given TEE.
```cpp
- // Retrieve attestation response validation collateral before calling into the service.
- adminClient.RetrieveResponseValidationCollateral();
-
// Retrieve the SGX Attestation Policy from this attestation service instance.
Azure::Response> const sgxPolicy
= adminClient.GetAttestationPolicy(AttestationType::SgxEnclave);
@@ -291,9 +291,6 @@ When an attestation instance is in AAD mode, the caller can use a convenience me
policy on the instance.
```cpp
- // Retrieve attestation response validation collateral before calling into the service.
- adminClient.RetrieveResponseValidationCollateral();
-
// Set the attestation policy on this attestation instance.
// Note that because this is an AAD mode instance, the caller does not need to sign the policy
// being set.
@@ -368,9 +365,6 @@ the policy management tokens. This interaction ensures that the client is in pos
one of the policy management certificates and is thus authorized to perform the operation.
```cpp
-// Retrieve attestation response validation collateral before calling into the service.
-adminClient.RetrieveResponseValidationCollateral();
-
// Retrieve the SGX Attestation Policy from this attestation service instance.
Azure::Response> const policyCertificates
= adminClient.GetIsolatedModeCertificates();
@@ -396,9 +390,6 @@ ignored (this possibly surprising behavior is there because retries could cause
AttestationSigningKey const requestSigner{pemSigningKey, pemSigningCert};
- // Retrieve attestation response validation collateral before calling into the service.
- adminClient.RetrieveResponseValidationCollateral();
-
// We start this sample by adding a new certificate to the set of policy management
// certificates.
{
diff --git a/sdk/attestation/azure-security-attestation/inc/azure/attestation/attestation_administration_client.hpp b/sdk/attestation/azure-security-attestation/inc/azure/attestation/attestation_administration_client.hpp
index 0b00f8f55a..2cd86ca987 100644
--- a/sdk/attestation/azure-security-attestation/inc/azure/attestation/attestation_administration_client.hpp
+++ b/sdk/attestation/azure-security-attestation/inc/azure/attestation/attestation_administration_client.hpp
@@ -6,6 +6,7 @@
#include "azure/attestation/attestation_client_models.hpp"
#include "azure/attestation/attestation_client_options.hpp"
#include
+#include
#include
#include
@@ -44,7 +45,23 @@ namespace Azure { namespace Security { namespace Attestation {
*
*/
class AttestationAdministrationClient final {
+
public:
+ /**
+ * @brief Construct a new Attestation Administration Client object.
+ *
+ * @param endpoint The URL address where the client will send the requests to.
+ * @param credential The authentication token to use.
+ * @param options The options to customize the client behavior.
+ * @return The newly created client.
+ */
+ static AttestationAdministrationClient Create(
+ std::string const& endpoint,
+ std::shared_ptr credential,
+ AttestationAdministrationClientOptions const& options
+ = AttestationAdministrationClientOptions{},
+ Azure::Core::Context const& context = Azure::Core::Context{});
+
/**
* @brief Construct a new Attestation Administration Client object from another attestation
* administration client.
@@ -52,9 +69,7 @@ namespace Azure { namespace Security { namespace Attestation {
* @param attestationClient An existing attestation client.
*/
AttestationAdministrationClient(AttestationAdministrationClient const& attestationClient)
- : m_endpoint(attestationClient.m_endpoint), m_apiVersion(attestationClient.m_apiVersion),
- m_pipeline(attestationClient.m_pipeline),
- m_tokenValidationOptions(attestationClient.m_tokenValidationOptions){};
+ = default;
/**
* @brief Destructor.
@@ -78,13 +93,10 @@ namespace Azure { namespace Security { namespace Attestation {
* @return Response> The returned policy from the
* service.
*
- * @note \b Note: The RetrieveResponseValidationCollateral API \b MUST be called before the
- * GetAttestationPolicy API is called to retrieve the information needed to validate the
- * result returned by the service.
*/
Response> GetAttestationPolicy(
Models::AttestationType const& attestationType,
- GetPolicyOptions const& options = GetPolicyOptions(),
+ GetPolicyOptions const& options = GetPolicyOptions{},
Azure::Core::Context const& context = Azure::Core::Context{}) const;
/**
@@ -114,14 +126,11 @@ namespace Azure { namespace Security { namespace Attestation {
* @return Response> The result of the set policy
* operation.
*
- * @note \b Note: The RetrieveResponseValidationCollateral API \b MUST be called before the
- * SetAttestationPolicy API is called to retrieve the information needed to validate the
- * result returned by the service.
*/
Response> SetAttestationPolicy(
Models::AttestationType const& attestationType,
std::string const& policyToSet,
- SetPolicyOptions const& options = SetPolicyOptions(),
+ SetPolicyOptions const& options = SetPolicyOptions{},
Azure::Core::Context const& context = Azure::Core::Context{}) const;
/**
@@ -133,13 +142,10 @@ namespace Azure { namespace Security { namespace Attestation {
* @return Response> The result of the reset
* policy operation.
*
- * @note \b Note: The RetrieveResponseValidationCollateral API \b MUST be called before the
- * ResetAttestationPolicy API is called to retrieve the information needed to validate the
- * result returned by the service.
*/
Response> ResetAttestationPolicy(
Models::AttestationType const& attestationType,
- SetPolicyOptions const& options = SetPolicyOptions(),
+ SetPolicyOptions const& options = SetPolicyOptions{},
Azure::Core::Context const& context = Azure::Core::Context{}) const;
/**
@@ -213,7 +219,7 @@ namespace Azure { namespace Security { namespace Attestation {
AddIsolatedModeCertificate(
std::string const& pemEncodedCertificateToAdd,
AttestationSigningKey const& signerForRequest,
- AddIsolatedModeCertificatesOptions const& options = AddIsolatedModeCertificatesOptions{},
+ AddIsolatedModeCertificateOptions const& options = AddIsolatedModeCertificateOptions{},
Azure::Core::Context const& context = Azure::Core::Context{}) const;
/**
@@ -240,49 +246,19 @@ namespace Azure { namespace Security { namespace Attestation {
RemoveIsolatedModeCertificate(
std::string const& pemEncodedCertificateToAdd,
AttestationSigningKey const& signerForRequest,
- AddIsolatedModeCertificatesOptions const& options = AddIsolatedModeCertificatesOptions{},
+ RemoveIsolatedModeCertificateOptions const& options
+ = RemoveIsolatedModeCertificateOptions{},
Azure::Core::Context const& context = Azure::Core::Context{}) const;
- /**
- * @brief Construct a new Attestation Administration Client object.
- *
- * @param endpoint The URL address where the client will send the requests to.
- * @param credential The authentication token to use.
- * @param options The options to customize the client behavior.
- * @return std::unique_ptr The newly created client.
- */
- static AttestationAdministrationClient Create(
- std::string const& endpoint,
- std::shared_ptr credential,
- AttestationAdministrationClientOptions const& options
- = AttestationAdministrationClientOptions(),
- Azure::Core::Context const& context = Azure::Core::Context{});
- /**
- * @brief Construct a pointer to a new Attestation Administration Client object.
- *
- * @note It is the responsibility of the caller to manage the lifetime of the returned
- * AttestationAdministrationClient object, typically by constructing a std::unique_ptr or
- * std::shared_ptr from this pointer.
- *
- * @param endpoint The URL address where the client will send the requests to.
- * @param credential The authentication token to use.
- * @param options The options to customize the client behavior.
- */
- static std::unique_ptr CreatePointer(
- std::string const& endpoint,
- std::shared_ptr credential,
- AttestationAdministrationClientOptions const& options
- = AttestationAdministrationClientOptions(),
- Azure::Core::Context const& context = Azure::Core::Context{});
-
private:
Azure::Core::Url m_endpoint;
std::string m_apiVersion;
std::shared_ptr m_credentials;
std::shared_ptr m_pipeline;
AttestationTokenValidationOptions m_tokenValidationOptions;
+ Azure::Core::Tracing::_internal::TracingContextFactory m_tracingFactory;
- mutable std::vector m_attestationSigners;
+ std::vector m_attestationSigners;
/**
* @brief Construct a new Attestation Administration Client object.
@@ -295,7 +271,7 @@ namespace Azure { namespace Security { namespace Attestation {
std::string const& endpoint,
std::shared_ptr credential,
AttestationAdministrationClientOptions const& options
- = AttestationAdministrationClientOptions());
+ = AttestationAdministrationClientOptions{});
std::string CreateIsolatedModeModificationToken(
std::string const& pemEncodedX509CertificateToAdd,
@@ -316,7 +292,6 @@ namespace Azure { namespace Security { namespace Attestation {
* @param context Client context for the request to the service.
*/
void RetrieveResponseValidationCollateral(
- Azure::Core::Context const& context = Azure::Core::Context{}) const;
+ Azure::Core::Context const& context = Azure::Core::Context{});
};
-
}}} // namespace Azure::Security::Attestation
diff --git a/sdk/attestation/azure-security-attestation/inc/azure/attestation/attestation_client.hpp b/sdk/attestation/azure-security-attestation/inc/azure/attestation/attestation_client.hpp
index bcedd9a4fc..69cbb039b9 100644
--- a/sdk/attestation/azure-security-attestation/inc/azure/attestation/attestation_client.hpp
+++ b/sdk/attestation/azure-security-attestation/inc/azure/attestation/attestation_client.hpp
@@ -6,6 +6,7 @@
#include "azure/attestation/attestation_client_models.hpp"
#include "azure/attestation/attestation_client_options.hpp"
#include
+#include
#include
#include
@@ -114,7 +115,44 @@ namespace Azure { namespace Security { namespace Attestation {
*/
class AttestationClient final {
+
public:
+ /** @brief Construct a new Attestation Client object
+ *
+ * @details Constructs a new attestation client. Follows the
+ * factory pattern in [C++ Core Guidelines
+ * C.50](https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#c50-use-a-factory-function-if-you-need-virtual-behavior-during-initialization)
+ *
+ * @param endpoint The URL address where the client will send the requests to.
+ * @param credential The authentication method to use (required for TPM attestation). If the
+ * credential parameter is not supplied, the connection will be unauthenticated.
+ * @param options The options to customize the client behavior.
+ * @return The newly created client.
+ */
+ static AttestationClient Create(
+ std::string const& endpoint,
+ std::shared_ptr credential,
+ AttestationClientOptions const& options = AttestationClientOptions{},
+ Azure::Core::Context const& constext = Azure::Core::Context{});
+
+ /** @brief Construct a new anonymous Attestation Client object
+ *
+ * @details Constructs a new anonymous (unauthenticated) attestation client. Follows the
+ * factory pattern in [C++ Core Guidelines
+ * C.50](https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#c50-use-a-factory-function-if-you-need-virtual-behavior-during-initialization)
+ *
+ * @param endpoint The URL address where the client will send the requests to.
+ * @param options The options to customize the client behavior.
+ * @return The newly created attestation client.
+ *
+ * @note TPM attestation requires an authenticated attestation client.
+ *
+ */
+ static AttestationClient Create(
+ std::string const& endpoint,
+ AttestationClientOptions options = AttestationClientOptions{},
+ Azure::Core::Context const& constext = Azure::Core::Context{});
+
/**
* @brief Destructor.
*
@@ -125,10 +163,7 @@ namespace Azure { namespace Security { namespace Attestation {
*
* @param attestationClient An existing attestation client.
*/
- AttestationClient(AttestationClient const& attestationClient)
- : m_endpoint(attestationClient.m_endpoint), m_apiVersion(attestationClient.m_apiVersion),
- m_pipeline(attestationClient.m_pipeline),
- m_tokenValidationOptions(attestationClient.m_tokenValidationOptions){};
+ AttestationClient(AttestationClient const& attestationClient) = default;
std::string const Endpoint() const { return m_endpoint.GetAbsoluteUrl(); }
@@ -163,13 +198,10 @@ namespace Azure { namespace Security { namespace Attestation {
* @returns Response> - The result of the
* attestation operation.
*
- * @note \b Note: The RetrieveResponseValidationCollateral API \b MUST be called before the
- * AttestSgxEnclave API is called to retrieve the information needed to validate the
- * result returned by the service.
*/
Response> AttestSgxEnclave(
std::vector const& sgxQuoteToAttest,
- AttestEnclaveOptions options = AttestEnclaveOptions(),
+ AttestSgxEnclaveOptions options = AttestSgxEnclaveOptions{},
Azure::Core::Context const& context = Azure::Core::Context{}) const;
/**
@@ -184,13 +216,10 @@ namespace Azure { namespace Security { namespace Attestation {
* @returns Response> - The result of the attestation
* operation
- * @note \b Note: The RetrieveResponseValidationCollateral API \b MUST be called before the
- * AttestOpenEnclave API is called to retrieve information needed to used to validate the
- * result returned by the service.
*/
Response> AttestOpenEnclave(
std::vector const& openEnclaveReportToAttest,
- AttestEnclaveOptions options = AttestEnclaveOptions(),
+ AttestOpenEnclaveOptions options = AttestOpenEnclaveOptions{},
Azure::Core::Context const& context = Azure::Core::Context{}) const;
/**
@@ -214,69 +243,7 @@ namespace Azure { namespace Security { namespace Attestation {
*/
Response AttestTpm(
AttestTpmOptions const& options,
- Azure::Core::Context const& context = Azure::Core::Context::ApplicationContext) const;
-
- /** @brief Construct a new Attestation Client object
- *
- * @param endpoint The URL address where the client will send the requests to.
- * @param credential The authentication method to use (required for TPM attestation).
- * @param options The options to customize the client behavior.
- * @return AttestationClient The newly created client.
- */
- static AttestationClient Create(
- std::string const& endpoint,
- std::shared_ptr credential,
- AttestationClientOptions options = AttestationClientOptions(),
- Azure::Core::Context const& constext = Azure::Core::Context{});
-
- /** @brief Construct a new anonymous Attestation Client object
- *
- * @param endpoint The URL address where the client will send the requests to.
- * @param options The options to customize the client behavior.
- * @return AttestationClient The newly created client.
- *
- * @note TPM attestation requires an authenticated attestation client.
- */
- static AttestationClient Create(
- std::string const& endpoint,
- AttestationClientOptions options = AttestationClientOptions(),
- Azure::Core::Context const& constext = Azure::Core::Context{});
-
- /** @brief Construct a new Attestation Client object
- *
- * @details Constructs a new attestation client. Follows the
- * factory pattern in [C++ Core Guidelines
- * C.50](https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#c50-use-a-factory-function-if-you-need-virtual-behavior-during-initialization)
- *
- * @param endpoint The URL address where the client will send the requests to.
- * @param credential The authentication method to use (required for TPM attestation). If the
- * credential parameter is not supplied, the connection will be unauthenticated.
- * @param options The options to customize the client behavior.
- * @return std::unique_ptr The newly created client.
- */
- static std::unique_ptr CreatePointer(
- std::string const& endpoint,
- std::shared_ptr credential,
- AttestationClientOptions options = AttestationClientOptions(),
- Azure::Core::Context const& constext = Azure::Core::Context{});
-
- /** @brief Construct a new anonymous Attestation Client object
- *
- * @details Constructs a new anonymous (unauthenticated) attestation client. Follows the
- * factory pattern in [C++ Core Guidelines
- * C.50](https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#c50-use-a-factory-function-if-you-need-virtual-behavior-during-initialization)
- *
- * @param endpoint The URL address where the client will send the requests to.
- * @param options The options to customize the client behavior.
- * @return std::unique_ptr The newly created attestation client.
- *
- * @note TPM attestation requires an authenticated attestation client.
- *
- */
- static std::unique_ptr CreatePointer(
- std::string const& endpoint,
- AttestationClientOptions options = AttestationClientOptions(),
- Azure::Core::Context const& constext = Azure::Core::Context{});
+ Azure::Core::Context const& context = Azure::Core::Context{}) const;
private:
Azure::Core::Url m_endpoint;
@@ -284,8 +251,9 @@ namespace Azure { namespace Security { namespace Attestation {
std::shared_ptr m_credentials;
std::shared_ptr m_pipeline;
AttestationTokenValidationOptions m_tokenValidationOptions;
+ std::vector m_attestationSigners;
+ Azure::Core::Tracing::_internal::TracingContextFactory m_tracingFactory;
- mutable std::vector m_attestationSigners;
/** @brief Construct a new Attestation Client object
*
* @param endpoint The URL address where the client will send the requests to.
@@ -295,7 +263,7 @@ namespace Azure { namespace Security { namespace Attestation {
AttestationClient(
std::string const& endpoint,
std::shared_ptr credential,
- AttestationClientOptions options = AttestationClientOptions());
+ AttestationClientOptions options = AttestationClientOptions{});
/**
* @brief Retrieves the information needed to validate a response from the attestation service.
@@ -304,7 +272,7 @@ namespace Azure { namespace Security { namespace Attestation {
* validated.
*/
void RetrieveResponseValidationCollateral(
- Azure::Core::Context const& context = Azure::Core::Context{}) const;
+ Azure::Core::Context const& context = Azure::Core::Context{});
};
}}} // namespace Azure::Security::Attestation
diff --git a/sdk/attestation/azure-security-attestation/inc/azure/attestation/attestation_client_models.hpp b/sdk/attestation/azure-security-attestation/inc/azure/attestation/attestation_client_models.hpp
index 1c86c43971..2fb15bcc51 100644
--- a/sdk/attestation/azure-security-attestation/inc/azure/attestation/attestation_client_models.hpp
+++ b/sdk/attestation/azure-security-attestation/inc/azure/attestation/attestation_client_models.hpp
@@ -265,7 +265,7 @@ namespace Azure { namespace Security { namespace Attestation { namespace Models
* SHA256 hash of the policy document sent to the attestation service.
*
* In order to verify that the attestation service correctly received the attestation policy sent
- * by the client, the AttestationAdministrationClient::CreateSetAttestationPolicyToken API can be
+ * by the client, the AttestationAdministrationClient::CreateAttestationPolicyToken API can be
* used to create an AttestationToken object which is not specialized on any type
* (`AttestationToken<>`). The RawToken field in that can be used to calculate the hash which was
* sent to the service.
diff --git a/sdk/attestation/azure-security-attestation/inc/azure/attestation/attestation_client_options.hpp b/sdk/attestation/azure-security-attestation/inc/azure/attestation/attestation_client_options.hpp
index 72f288c41f..bcd6e12fb7 100644
--- a/sdk/attestation/azure-security-attestation/inc/azure/attestation/attestation_client_options.hpp
+++ b/sdk/attestation/azure-security-attestation/inc/azure/attestation/attestation_client_options.hpp
@@ -216,9 +216,45 @@ namespace Azure { namespace Security { namespace Attestation {
AttestationDataType DataType;
};
- /** @brief Parameters sent to the attestation service to be consumed in an attestation operation.
+ /** @brief Parameters sent to the attestation service for the AttestationClient::AttestSgxEnclave
+ * API.
*/
- struct AttestEnclaveOptions final
+ struct AttestSgxEnclaveOptions final
+ {
+ /**
+ * @brief Data created dynamically within the enclave
+ */
+ Azure::Nullable RunTimeData{};
+
+ /**
+ * @brief Data created when the enclave was created. Not supported on Coffeelake processors.
+ */
+ Azure::Nullable InitTimeData{};
+
+ /**
+ * @brief Nonce which is sent to the attestation service to allow a caller to prevent replay
+ * attacks.
+ */
+ Azure::Nullable Nonce{};
+
+ /**
+ * @brief A test hook which allows developers to test attestation policies before they commit
+ * them to the service.
+ */
+ Azure::Nullable DraftPolicyForAttestation{};
+
+ /** @brief Specifies the options which should be used to validate the attestation token returned
+ * by the attestation service. Overrides the value specified in the AttestationClient.
+ * @details If not provided by the caller, the token validation options
+ * specified when the @{link AttestationClient} was created will be used.
+ */
+ Azure::Nullable TokenValidationOptionsOverride{};
+ };
+
+ /** @brief Parameters sent to the attestation service for the AttestationClient::AttestOpenEnclave
+ * API.
+ */
+ struct AttestOpenEnclaveOptions final
{
/**
* @brief Data created dynamically within the enclave
@@ -259,7 +295,7 @@ namespace Azure { namespace Security { namespace Attestation {
* @details The TPM attestation protocol is defined
* [here](https://docs.microsoft.com/azure/attestation/virtualization-based-security-protocol')
*/
- std::string ValueToSend;
+ std::string Payload;
};
/** @brief The AttestationSigningKey represents a tuple of asymmetric private cryptographic key
@@ -327,7 +363,7 @@ namespace Azure { namespace Security { namespace Attestation {
/** @brief Parameters sent to the attestation service when adding a new policy
* management certificate.
*/
- struct AddIsolatedModeCertificatesOptions final
+ struct AddIsolatedModeCertificateOptions final
{
/** @brief Specifies the options which should be used to validate the attestation token returned
* by the attestation service. Overrides the value specified in the AttestationClient.
@@ -340,7 +376,7 @@ namespace Azure { namespace Security { namespace Attestation {
/** @brief Parameters sent to the attestation service when removing a policy
* management certificate.
*/
- struct RemoveIsolatedModeCertificatesOptions final
+ struct RemoveIsolatedModeCertificateOptions final
{
/** @brief Specifies the options which should be used to validate the attestation token returned
* by the attestation service. Overrides the value specified in the AttestationClient.
diff --git a/sdk/attestation/azure-security-attestation/samples/attestation/attest_openenclave_shared.cpp b/sdk/attestation/azure-security-attestation/samples/attestation/attest_openenclave_shared.cpp
index 8025cd37d9..6cf6cc47c0 100644
--- a/sdk/attestation/azure-security-attestation/samples/attestation/attest_openenclave_shared.cpp
+++ b/sdk/attestation/azure-security-attestation/samples/attestation/attest_openenclave_shared.cpp
@@ -47,13 +47,12 @@ int main()
std::string const endpoint
= "https://shared" + shortLocation + "." + shortLocation + ".attest.azure.net";
- std::unique_ptr attestationClient(
- AttestationClient::CreatePointer(endpoint));
+ AttestationClient const attestationClient(AttestationClient::Create(endpoint));
std::vector const sgxEnclaveQuote = AttestationCollateral::SgxQuote();
Azure::Response> const sgxResult
- = attestationClient->AttestSgxEnclave(sgxEnclaveQuote);
+ = attestationClient.AttestSgxEnclave(sgxEnclaveQuote);
std::cout << "SGX Quote MRSIGNER is: "
<< Convert::Base64Encode(*sgxResult.Value.Body.SgxMrSigner) << std::endl;
diff --git a/sdk/attestation/azure-security-attestation/samples/attestation/attest_openenclave_with_draft_policy.cpp b/sdk/attestation/azure-security-attestation/samples/attestation/attest_openenclave_with_draft_policy.cpp
index 50915363a8..2547cf1899 100644
--- a/sdk/attestation/azure-security-attestation/samples/attestation/attest_openenclave_with_draft_policy.cpp
+++ b/sdk/attestation/azure-security-attestation/samples/attestation/attest_openenclave_with_draft_policy.cpp
@@ -47,7 +47,7 @@ int main()
std::vector const openEnclaveReport = AttestationCollateral::OpenEnclaveReport();
- AttestEnclaveOptions options;
+ AttestOpenEnclaveOptions options;
options.DraftPolicyForAttestation = R"(version= 1.0;
authorizationrules
{
diff --git a/sdk/attestation/azure-security-attestation/samples/attestation/attest_sgxenclave_with_runtime_binary.cpp b/sdk/attestation/azure-security-attestation/samples/attestation/attest_sgxenclave_with_runtime_binary.cpp
index e391dadadd..2ecc6ddacd 100644
--- a/sdk/attestation/azure-security-attestation/samples/attestation/attest_sgxenclave_with_runtime_binary.cpp
+++ b/sdk/attestation/azure-security-attestation/samples/attestation/attest_sgxenclave_with_runtime_binary.cpp
@@ -45,13 +45,13 @@ int main()
// create client
std::string endpoint(GetEnvHelper::GetEnv("ATTESTATION_AAD_URL"));
std::shared_ptr attestationClient(
- AttestationClient::CreatePointer(endpoint));
+ std::make_shared(AttestationClient::Create(endpoint)));
std::vector const sgxEnclaveQuote = AttestationCollateral::SgxQuote();
// Set the RunTimeData in the request to the service. Ask the service to interpret the
// RunTimeData as a JSON object when it is returned in the resulting token.
- AttestEnclaveOptions attestOptions;
+ AttestSgxEnclaveOptions attestOptions;
attestOptions.RunTimeData
= AttestationData{AttestationCollateral::RunTimeData(), AttestationDataType::Binary};
diff --git a/sdk/attestation/azure-security-attestation/samples/attestation/attest_sgxenclave_with_runtime_json.cpp b/sdk/attestation/azure-security-attestation/samples/attestation/attest_sgxenclave_with_runtime_json.cpp
index 18b57c3196..d70c5f43a3 100644
--- a/sdk/attestation/azure-security-attestation/samples/attestation/attest_sgxenclave_with_runtime_json.cpp
+++ b/sdk/attestation/azure-security-attestation/samples/attestation/attest_sgxenclave_with_runtime_json.cpp
@@ -50,7 +50,7 @@ int main()
// Set the RunTimeData in the request to the service. Ask the service to interpret the
// RunTimeData as a JSON object when it is returned in the resulting token.
- AttestEnclaveOptions attestOptions;
+ AttestSgxEnclaveOptions attestOptions;
attestOptions.RunTimeData
= AttestationData{AttestationCollateral::RunTimeData(), AttestationDataType::Json};
diff --git a/sdk/attestation/azure-security-attestation/samples/basic-operations/create_client.cpp b/sdk/attestation/azure-security-attestation/samples/basic-operations/create_client.cpp
index 8d441ed804..9c6d0a4c5f 100644
--- a/sdk/attestation/azure-security-attestation/samples/basic-operations/create_client.cpp
+++ b/sdk/attestation/azure-security-attestation/samples/basic-operations/create_client.cpp
@@ -35,7 +35,7 @@ int main()
clientOptions.TokenValidationOptions.TimeValidationSlack = 10s;
// create client
- AttestationClient const attestationClient(
+ AttestationClient attestationClient(
AttestationClient::Create(GetEnvHelper::GetEnv("ATTESTATION_AAD_URL"), clientOptions));
attestationClient.GetOpenIdMetadata();
diff --git a/sdk/attestation/azure-security-attestation/samples/policy-certificates/add_policy_certificate.cpp b/sdk/attestation/azure-security-attestation/samples/policy-certificates/add_policy_certificate.cpp
index 2c46e53df1..2103a441a5 100644
--- a/sdk/attestation/azure-security-attestation/samples/policy-certificates/add_policy_certificate.cpp
+++ b/sdk/attestation/azure-security-attestation/samples/policy-certificates/add_policy_certificate.cpp
@@ -50,9 +50,8 @@ int main()
GetEnvHelper::GetEnv("AZURE_TENANT_ID"),
GetEnvHelper::GetEnv("AZURE_CLIENT_ID"),
GetEnvHelper::GetEnv("AZURE_CLIENT_SECRET"));
- std::shared_ptr adminClient(
- AttestationAdministrationClient::CreatePointer(
- GetEnvHelper::GetEnv("ATTESTATION_ISOLATED_URL"), credential));
+ AttestationAdministrationClient adminClient(AttestationAdministrationClient::Create(
+ GetEnvHelper::GetEnv("ATTESTATION_ISOLATED_URL"), credential));
std::string const signingKey(GetEnvHelper::GetEnv("ISOLATED_SIGNING_KEY"));
std::string const signingCert(GetEnvHelper::GetEnv("ISOLATED_SIGNING_CERTIFICATE"));
@@ -76,7 +75,7 @@ int main()
// Add the new certificate to the set of policy management certificates for this attestation
// service instance.
Azure::Response> const addResult
- = adminClient->AddIsolatedModeCertificate(pemCertificateToAdd, requestSigner);
+ = adminClient.AddIsolatedModeCertificate(pemCertificateToAdd, requestSigner);
std::cout << "The result of the certificate add operation is: "
<< addResult.Value.Body.CertificateModification.ToString() << std::endl;
@@ -115,7 +114,7 @@ int main()
// Add the new certificate to the set of policy management certificates for this attestation
// service instance.
Azure::Response> const addResult
- = adminClient->RemoveIsolatedModeCertificate(pemCertificateToRemove, requestSigner);
+ = adminClient.RemoveIsolatedModeCertificate(pemCertificateToRemove, requestSigner);
std::cout << "The result of the certificate remove operation is: "
<< addResult.Value.Body.CertificateModification.ToString() << std::endl;
diff --git a/sdk/attestation/azure-security-attestation/samples/policy-certificates/get_policy_certificates.cpp b/sdk/attestation/azure-security-attestation/samples/policy-certificates/get_policy_certificates.cpp
index e337c259cb..a5cbcd5cf4 100644
--- a/sdk/attestation/azure-security-attestation/samples/policy-certificates/get_policy_certificates.cpp
+++ b/sdk/attestation/azure-security-attestation/samples/policy-certificates/get_policy_certificates.cpp
@@ -45,13 +45,12 @@ int main()
// create an administration client
auto const credential = std::make_shared(
GetEnv("AZURE_TENANT_ID"), GetEnv("AZURE_CLIENT_ID"), GetEnv("AZURE_CLIENT_SECRET"));
- std::unique_ptr adminClient(
- AttestationAdministrationClient::CreatePointer(
- GetEnv("ATTESTATION_ISOLATED_URL"), credential));
+ AttestationAdministrationClient adminClient(
+ AttestationAdministrationClient::Create(GetEnv("ATTESTATION_ISOLATED_URL"), credential));
// Retrieve the SGX Attestation Policy from this attestation service instance.
Azure::Response> const policyCertificates
- = adminClient->GetIsolatedModeCertificates();
+ = adminClient.GetIsolatedModeCertificates();
std::cout << "There are " << policyCertificates.Value.Body.Certificates.size()
<< " certificates configured on this instance." << std::endl;
diff --git a/sdk/attestation/azure-security-attestation/samples/policy/get_policy.cpp b/sdk/attestation/azure-security-attestation/samples/policy/get_policy.cpp
index b41ea3e005..c469e4ada6 100644
--- a/sdk/attestation/azure-security-attestation/samples/policy/get_policy.cpp
+++ b/sdk/attestation/azure-security-attestation/samples/policy/get_policy.cpp
@@ -40,6 +40,7 @@ int main()
GetEnvHelper::GetEnv("AZURE_TENANT_ID"),
GetEnvHelper::GetEnv("AZURE_CLIENT_ID"),
GetEnvHelper::GetEnv("AZURE_CLIENT_SECRET"));
+
AttestationAdministrationClient adminClient(AttestationAdministrationClient::Create(
GetEnvHelper::GetEnv("ATTESTATION_AAD_URL"), credential));
diff --git a/sdk/attestation/azure-security-attestation/samples/policy/set_policy.cpp b/sdk/attestation/azure-security-attestation/samples/policy/set_policy.cpp
index 9e5c2ed98c..063ab26a79 100644
--- a/sdk/attestation/azure-security-attestation/samples/policy/set_policy.cpp
+++ b/sdk/attestation/azure-security-attestation/samples/policy/set_policy.cpp
@@ -58,8 +58,8 @@ int main()
GetEnvHelper::GetEnv("AZURE_TENANT_ID"),
GetEnvHelper::GetEnv("AZURE_CLIENT_ID"),
GetEnvHelper::GetEnv("AZURE_CLIENT_SECRET"));
- std::unique_ptr adminClient(
- AttestationAdministrationClient::CreatePointer(endpoint, credential, clientOptions));
+ AttestationAdministrationClient const adminClient(
+ AttestationAdministrationClient::Create(endpoint, credential, clientOptions));
// Set the attestation policy on this attestation instance.
// Note that because this is an AAD mode instance, the caller does not need to sign the policy
@@ -73,7 +73,7 @@ authorizationrules
[ type=="x-ms-sgx-mrsigner", value=="mrsigner2"] => permit();
};)");
Azure::Response> const setResult
- = adminClient->SetAttestationPolicy(AttestationType::SgxEnclave, policyToSet);
+ = adminClient.SetAttestationPolicy(AttestationType::SgxEnclave, policyToSet);
if (setResult.Value.Body.PolicyResolution == PolicyModification::Updated)
{
@@ -89,7 +89,7 @@ authorizationrules
// by the attestation service, the customer can call CreateAttestationPolicyToken and then
// generate the SHA256 of that token and compare it with the value returned by the service - the
// two hash values should be identical.
- auto const setPolicyToken = adminClient->CreateAttestationPolicyToken(policyToSet);
+ auto const setPolicyToken = adminClient.CreateAttestationPolicyToken(policyToSet);
Sha256Hash shaHasher;
std::vector policyTokenHash = shaHasher.Final(
reinterpret_cast(setPolicyToken.RawToken.data()),
diff --git a/sdk/attestation/azure-security-attestation/src/attestation_administration_client.cpp b/sdk/attestation/azure-security-attestation/src/attestation_administration_client.cpp
index f8528c41f0..1728294d73 100644
--- a/sdk/attestation/azure-security-attestation/src/attestation_administration_client.cpp
+++ b/sdk/attestation/azure-security-attestation/src/attestation_administration_client.cpp
@@ -21,6 +21,7 @@ using namespace Azure::Security::Attestation;
using namespace Azure::Security::Attestation::Models;
using namespace Azure::Security::Attestation::_detail;
using namespace Azure::Security::Attestation::Models::_detail;
+using namespace Azure::Core::Tracing::_internal;
using namespace Azure::Core::Http;
using namespace Azure::Core::Http::Policies;
using namespace Azure::Core::Http::Policies::_internal;
@@ -42,7 +43,8 @@ AttestationAdministrationClient::AttestationAdministrationClient(
std::shared_ptr credential,
AttestationAdministrationClientOptions const& options)
: m_endpoint(endpoint), m_apiVersion(options.Version.ToString()),
- m_tokenValidationOptions(options.TokenValidationOptions)
+ m_tokenValidationOptions(options.TokenValidationOptions),
+ m_tracingFactory(options, "security.attestation", PackageVersion::ToString())
{
std::vector> perRetrypolicies;
if (credential)
@@ -58,11 +60,7 @@ AttestationAdministrationClient::AttestationAdministrationClient(
std::vector> perCallpolicies;
m_pipeline = std::make_shared(
- options,
- "Attestation",
- PackageVersion::ToString(),
- std::move(perRetrypolicies),
- std::move(perCallpolicies));
+ options, std::move(perRetrypolicies), std::move(perCallpolicies));
}
AttestationAdministrationClient AttestationAdministrationClient::Create(
@@ -76,18 +74,6 @@ AttestationAdministrationClient AttestationAdministrationClient::Create(
return returnValue;
}
-std::unique_ptr AttestationAdministrationClient::CreatePointer(
- std::string const& endpoint,
- std::shared_ptr credential,
- AttestationAdministrationClientOptions const& options,
- Azure::Core::Context const& context)
-{
- std::unique_ptr returnValue(
- new AttestationAdministrationClient(endpoint, credential, options));
- returnValue->RetrieveResponseValidationCollateral(context);
- return returnValue;
-}
-
namespace {
std::shared_timed_mutex SharedStateLock;
}
@@ -98,53 +84,64 @@ AttestationAdministrationClient::GetAttestationPolicy(
GetPolicyOptions const& options,
Azure::Core::Context const& context) const
{
- auto request = AttestationCommonRequest::CreateRequest(
- m_endpoint,
- m_apiVersion,
- HttpMethod::Get,
- {"policies/" + attestationType.ToString()},
- nullptr);
-
- // Send the request to the service.
- auto response = AttestationCommonRequest::SendRequest(*m_pipeline, request, context);
+ auto tracingContext(m_tracingFactory.CreateTracingContext("GetAttestationPolicy", context));
+ try
+ {
- // Deserialize the Service response token and return the JSON web token returned by the
- // service.
- std::string responseToken = AttestationServiceTokenResponseSerializer::Deserialize(response);
+ auto request = AttestationCommonRequest::CreateRequest(
+ m_endpoint,
+ m_apiVersion,
+ HttpMethod::Get,
+ {"policies/" + attestationType.ToString()},
+ nullptr);
- // Parse the JWT returned by the attestation service.
- const auto resultToken
- = AttestationTokenInternal(
- responseToken);
+ // Send the request to the service.
+ auto response = AttestationCommonRequest::SendRequest(*m_pipeline, request, context);
- // Validate the token returned by the service. Use the cached attestation signers in the
- // validation.
- resultToken.ValidateToken(
- options.TokenValidationOptionsOverride ? *options.TokenValidationOptionsOverride
- : this->m_tokenValidationOptions,
- m_attestationSigners);
+ // Deserialize the Service response token and return the JSON web token returned by the
+ // service.
+ std::string responseToken = AttestationServiceTokenResponseSerializer::Deserialize(response);
+
+ // Parse the JWT returned by the attestation service.
+ const auto resultToken
+ = AttestationTokenInternal(
+ responseToken);
+
+ // Validate the token returned by the service. Use the cached attestation signers in the
+ // validation.
+ resultToken.ValidateToken(
+ options.TokenValidationOptionsOverride ? *options.TokenValidationOptionsOverride
+ : this->m_tokenValidationOptions,
+ m_attestationSigners);
+
+ // Extract the underlying policy token from the response.
+ std::string policyTokenValue
+ = *static_cast>(resultToken)
+ .Body.PolicyToken;
+
+ // TPM policies are empty by default, at least in our test instances, so handle the empty policy
+ // token case.
+ const auto policyTokenI
+ = AttestationTokenInternal(
+ policyTokenValue);
+ AttestationToken policyToken(policyTokenI);
+ std::string returnPolicy;
+ if (policyToken.Body.AttestationPolicy)
+ {
+ std::vector policyUtf8 = *policyToken.Body.AttestationPolicy;
+ returnPolicy = std::string(policyUtf8.begin(), policyUtf8.end());
+ }
- // Extract the underlying policy token from the response.
- std::string policyTokenValue
- = *static_cast>(resultToken).Body.PolicyToken;
-
- // TPM policies are empty by default, at least in our test instances, so handle the empty policy
- // token case.
- const auto policyTokenI
- = AttestationTokenInternal(
- policyTokenValue);
- AttestationToken policyToken(policyTokenI);
- std::string returnPolicy;
- if (policyToken.Body.AttestationPolicy)
+ // Construct a token whose body is the policy, but whose token is the response from the
+ // service.
+ const auto returnedToken = AttestationTokenInternal(responseToken, &returnPolicy);
+ return Response>(returnedToken, std::move(response));
+ }
+ catch (std::runtime_error const& ex)
{
- std::vector policyUtf8 = *policyToken.Body.AttestationPolicy;
- returnPolicy = std::string(policyUtf8.begin(), policyUtf8.end());
+ tracingContext.Span.AddEvent(ex);
+ throw;
}
-
- // Construct a token whose body is the policy, but whose token is the response from the
- // service.
- const auto returnedToken = AttestationTokenInternal(responseToken, &returnPolicy);
- return Response>(returnedToken, std::move(response));
}
Models::AttestationToken AttestationAdministrationClient::CreateAttestationPolicyToken(
@@ -175,62 +172,72 @@ AttestationAdministrationClient::SetAttestationPolicy(
SetPolicyOptions const& options,
Azure::Core::Context const& context) const
{
- // Calculate a signed (or unsigned) attestation policy token to send to the service.
- Models::AttestationToken const tokenToSend(
- CreateAttestationPolicyToken(newAttestationPolicy, options.SigningKey));
+ auto tracingContext(m_tracingFactory.CreateTracingContext("SetAttestationPolicy", context));
+ try
+ {
+ // Calculate a signed (or unsigned) attestation policy token to send to the service.
+ Models::AttestationToken const tokenToSend(
+ CreateAttestationPolicyToken(newAttestationPolicy, options.SigningKey));
- Azure::Core::IO::MemoryBodyStream stream(
- reinterpret_cast(tokenToSend.RawToken.data()), tokenToSend.RawToken.size());
+ Azure::Core::IO::MemoryBodyStream stream(
+ reinterpret_cast(tokenToSend.RawToken.data()), tokenToSend.RawToken.size());
- auto request = AttestationCommonRequest::CreateRequest(
- m_endpoint,
- m_apiVersion,
- HttpMethod::Put,
- {"policies/" + attestationType.ToString()},
- &stream);
+ auto request = AttestationCommonRequest::CreateRequest(
+ m_endpoint,
+ m_apiVersion,
+ HttpMethod::Put,
+ {"policies/" + attestationType.ToString()},
+ &stream);
- // Send the request to the service.
- auto response = AttestationCommonRequest::SendRequest(*m_pipeline, request, context);
+ // Send the request to the service.
+ auto response = AttestationCommonRequest::SendRequest(*m_pipeline, request, context);
- // Deserialize the Service response token and return the JSON web token returned by the
- // service.
- std::string responseToken = AttestationServiceTokenResponseSerializer::Deserialize(response);
+ // Deserialize the Service response token and return the JSON web token returned by the
+ // service.
+ std::string responseToken = AttestationServiceTokenResponseSerializer::Deserialize(response);
- // Parse the JWT returned by the attestation service.
- auto resultToken
- = AttestationTokenInternal(
- responseToken);
+ // Parse the JWT returned by the attestation service.
+ auto resultToken
+ = AttestationTokenInternal(
+ responseToken);
- // Validate the token returned by the service. Use the cached attestation signers in the
- // validation.
- resultToken.ValidateToken(
- options.TokenValidationOptionsOverride ? *options.TokenValidationOptionsOverride
- : this->m_tokenValidationOptions,
- m_attestationSigners);
+ // Validate the token returned by the service. Use the cached attestation signers in the
+ // validation.
+ resultToken.ValidateToken(
+ options.TokenValidationOptionsOverride ? *options.TokenValidationOptionsOverride
+ : this->m_tokenValidationOptions,
+ m_attestationSigners);
- // Extract the underlying policy token from the response.
- auto internalResult
- = static_cast>(resultToken).Body;
+ // Extract the underlying policy token from the response.
+ auto internalResult
+ = static_cast>(resultToken).Body;
- Models::PolicyResult returnedResult;
- if (internalResult.PolicyResolution)
- {
- returnedResult.PolicyResolution = Models::PolicyModification(*internalResult.PolicyResolution);
- }
- if (internalResult.PolicySigner)
- {
- returnedResult.PolicySigner = AttestationSignerInternal(*internalResult.PolicySigner);
+ Models::PolicyResult returnedResult;
+ if (internalResult.PolicyResolution)
+ {
+ returnedResult.PolicyResolution
+ = Models::PolicyModification(*internalResult.PolicyResolution);
+ }
+ if (internalResult.PolicySigner)
+ {
+ returnedResult.PolicySigner = AttestationSignerInternal(*internalResult.PolicySigner);
+ }
+ if (internalResult.PolicyTokenHash)
+ {
+ returnedResult.PolicyTokenHash = Base64Url::Base64UrlDecode(*internalResult.PolicyTokenHash);
+ }
+
+ // Construct a token whose body is the policy result, but whose token is the response from
+ // the service.
+ auto returnedToken
+ = AttestationTokenInternal(responseToken, &returnedResult);
+ return Response>(returnedToken, std::move(response));
}
- if (internalResult.PolicyTokenHash)
+ catch (std::runtime_error const& ex)
{
- returnedResult.PolicyTokenHash = Base64Url::Base64UrlDecode(*internalResult.PolicyTokenHash);
+ tracingContext.Span.AddEvent(ex);
+ throw;
}
-
- // Construct a token whose body is the policy result, but whose token is the response from the
- // service.
- auto returnedToken
- = AttestationTokenInternal(responseToken, &returnedResult);
- return Response>(returnedToken, std::move(response));
}
Azure::Response>
@@ -239,67 +246,78 @@ AttestationAdministrationClient::ResetAttestationPolicy(
SetPolicyOptions const& options,
Azure::Core::Context const& context) const
{
- // Calculate a signed (or unsigned) attestation policy token to send to the service.
- Models::AttestationToken tokenToSend(
- CreateAttestationPolicyToken(Azure::Nullable(), options.SigningKey));
+ auto tracingContext(m_tracingFactory.CreateTracingContext("ResetAttestationPolicy", context));
+ try
+ {
+ // Calculate a signed (or unsigned) attestation policy token to send to the service.
+ Models::AttestationToken tokenToSend(
+ CreateAttestationPolicyToken(Azure::Nullable(), options.SigningKey));
- Azure::Core::IO::MemoryBodyStream stream(
- reinterpret_cast(tokenToSend.RawToken.data()), tokenToSend.RawToken.size());
+ Azure::Core::IO::MemoryBodyStream stream(
+ reinterpret_cast(tokenToSend.RawToken.data()), tokenToSend.RawToken.size());
- auto request = AttestationCommonRequest::CreateRequest(
- m_endpoint,
- m_apiVersion,
- HttpMethod::Post,
- {"policies/" + attestationType.ToString() + ":reset"},
- &stream);
+ auto request = AttestationCommonRequest::CreateRequest(
+ m_endpoint,
+ m_apiVersion,
+ HttpMethod::Post,
+ {"policies/" + attestationType.ToString() + ":reset"},
+ &stream);
- // Send the request to the service.
- auto response = AttestationCommonRequest::SendRequest(*m_pipeline, request, context);
+ // Send the request to the service.
+ auto response = AttestationCommonRequest::SendRequest(*m_pipeline, request, context);
- // Deserialize the Service response token and return the JSON web token returned by the
- // service.
- std::string responseToken = AttestationServiceTokenResponseSerializer::Deserialize(response);
+ // Deserialize the Service response token and return the JSON web token returned by the
+ // service.
+ std::string responseToken = AttestationServiceTokenResponseSerializer::Deserialize(response);
- // Parse the JWT returned by the attestation service.
- auto resultToken
- = AttestationTokenInternal(
- responseToken);
+ // Parse the JWT returned by the attestation service.
+ auto resultToken
+ = AttestationTokenInternal(
+ responseToken);
- // Validate the token returned by the service. Use the cached attestation signers in the
- // validation.
- resultToken.ValidateToken(
- options.TokenValidationOptionsOverride ? *options.TokenValidationOptionsOverride
- : this->m_tokenValidationOptions,
- m_attestationSigners);
+ // Validate the token returned by the service. Use the cached attestation signers in the
+ // validation.
+ resultToken.ValidateToken(
+ options.TokenValidationOptionsOverride ? *options.TokenValidationOptionsOverride
+ : this->m_tokenValidationOptions,
+ m_attestationSigners);
- // Extract the underlying policy token from the response.
- auto internalResult
- = static_cast>(resultToken).Body;
+ // Extract the underlying policy token from the response.
+ auto internalResult
+ = static_cast>(resultToken).Body;
- Models::PolicyResult returnedResult;
- if (internalResult.PolicyResolution)
+ Models::PolicyResult returnedResult;
+ if (internalResult.PolicyResolution)
+ {
+ returnedResult.PolicyResolution
+ = Models::PolicyModification(*internalResult.PolicyResolution);
+ }
+ // Note that the attestation service currently never returns these values on Reset, even
+ // though they are meaningful. Commenting them out to improve code coverage numbers. At
+ // some point the attestation service may start returning these values, at which point
+ // they can be un-commented out.
+ // if (internalResult.PolicySigner)
+ // {
+ // returnedResult.PolicySigner =
+ // AttestationSignerInternal(*internalResult.PolicySigner);
+ // }
+ // if (internalResult.PolicyTokenHash)
+ // {
+ // returnedResult.PolicyTokenHash =
+ // Base64Url::Base64UrlDecode(*internalResult.PolicyTokenHash);
+ // }
+
+ // Construct a token whose body is the policy result, but whose token is the response from
+ // the service.
+ auto returnedToken
+ = AttestationTokenInternal(responseToken, &returnedResult);
+ return Response>(returnedToken, std::move(response));
+ }
+ catch (std::runtime_error const& ex)
{
- returnedResult.PolicyResolution = Models::PolicyModification(*internalResult.PolicyResolution);
+ tracingContext.Span.AddEvent(ex);
+ throw;
}
- // Note that the attestation service currently never returns these values on Reset, even though
- // they are meaningful. Commenting them out to improve code coverage numbers. At some point the
- // attestation service may start returning these values, at which point they can be un-commented
- // out.
- // if (internalResult.PolicySigner)
- // {
- // returnedResult.PolicySigner = AttestationSignerInternal(*internalResult.PolicySigner);
- // }
- // if (internalResult.PolicyTokenHash)
- // {
- // returnedResult.PolicyTokenHash =
- // Base64Url::Base64UrlDecode(*internalResult.PolicyTokenHash);
- // }
-
- // Construct a token whose body is the policy result, but whose token is the response from the
- // service.
- auto returnedToken
- = AttestationTokenInternal(responseToken, &returnedResult);
- return Response>(returnedToken, std::move(response));
}
Azure::Response>
@@ -307,44 +325,54 @@ AttestationAdministrationClient::GetIsolatedModeCertificates(
GetIsolatedModeCertificatesOptions const& options,
Azure::Core::Context const& context) const
{
- auto request = AttestationCommonRequest::CreateRequest(
- m_endpoint, m_apiVersion, HttpMethod::Get, {"certificates"}, nullptr);
-
- // Send the request to the service.
- auto response = AttestationCommonRequest::SendRequest(*m_pipeline, request, context);
+ auto tracingContext(
+ m_tracingFactory.CreateTracingContext("GetIsolatedModeCertificates", context));
+ try
+ {
+ auto request = AttestationCommonRequest::CreateRequest(
+ m_endpoint, m_apiVersion, HttpMethod::Get, {"certificates"}, nullptr);
- // Deserialize the Service response token and return the JSON web token returned by the
- // service.
- std::string responseToken = AttestationServiceTokenResponseSerializer::Deserialize(response);
+ // Send the request to the service.
+ auto response = AttestationCommonRequest::SendRequest(*m_pipeline, request, context);
- // Parse the JWT returned by the attestation service.
- auto resultToken = AttestationTokenInternal<
- Models::_detail::GetIsolatedModeCertificatesResult,
- IsolatedModeCertificateGetResultSerializer>(responseToken);
+ // Deserialize the Service response token and return the JSON web token returned by the
+ // service.
+ std::string responseToken = AttestationServiceTokenResponseSerializer::Deserialize(response);
+
+ // Parse the JWT returned by the attestation service.
+ auto resultToken = AttestationTokenInternal<
+ Models::_detail::GetIsolatedModeCertificatesResult,
+ IsolatedModeCertificateGetResultSerializer>(responseToken);
+
+ // Validate the token returned by the service. Use the cached attestation signers in the
+ // validation.
+ resultToken.ValidateToken(
+ options.TokenValidationOptionsOverride ? *options.TokenValidationOptionsOverride
+ : this->m_tokenValidationOptions,
+ m_attestationSigners);
+
+ Models::_detail::JsonWebKeySet jwks(
+ *static_cast>(
+ resultToken)
+ .Body.PolicyCertificates);
+ Models::IsolatedModeCertificateListResult returnedResult;
+ for (const auto& certificate : jwks.Keys)
+ {
+ returnedResult.Certificates.push_back(AttestationSignerInternal(certificate));
+ }
- // Validate the token returned by the service. Use the cached attestation signers in the
- // validation.
- resultToken.ValidateToken(
- options.TokenValidationOptionsOverride ? *options.TokenValidationOptionsOverride
- : this->m_tokenValidationOptions,
- m_attestationSigners);
-
- Models::_detail::JsonWebKeySet jwks(
- *static_cast>(
- resultToken)
- .Body.PolicyCertificates);
- Models::IsolatedModeCertificateListResult returnedResult;
- for (const auto& certificate : jwks.Keys)
+ // Construct a token whose body is the get policy certificates result, but whose token
+ // is the response from the service.
+ auto returnedToken = AttestationTokenInternal(
+ responseToken, &returnedResult);
+ return Response>(
+ returnedToken, std::move(response));
+ }
+ catch (std::runtime_error const& ex)
{
- returnedResult.Certificates.push_back(AttestationSignerInternal(certificate));
+ tracingContext.Span.AddEvent(ex);
+ throw;
}
-
- // Construct a token whose body is the get policy certificates result, but whose token is the
- // response from the service.
- auto returnedToken = AttestationTokenInternal(
- responseToken, &returnedResult);
- return Response>(
- returnedToken, std::move(response));
}
std::string AttestationAdministrationClient::CreateIsolatedModeModificationToken(
@@ -409,8 +437,8 @@ AttestationAdministrationClient::ProcessIsolatedModeModificationResult(
returnValue.CertificateThumbprint = (*internalResult.CertificateThumbprint);
}
- // Construct a token whose body is the policy result, but whose token is the response from the
- // service.
+ // Construct a token whose body is the policy result, but whose token is the response
+ // from the service.
auto const returnedToken
= AttestationTokenInternal(
responseToken, &returnValue);
@@ -421,60 +449,79 @@ Azure::Response(policyCertToken.data()), policyCertToken.size());
-
- auto request = AttestationCommonRequest::CreateRequest(
- m_endpoint, m_apiVersion, HttpMethod::Post, {"certificates:add"}, &stream);
-
- // Send the request to the service.
- auto response = AttestationCommonRequest::SendRequest(*m_pipeline, request, context);
- AttestationToken returnValue(
- ProcessIsolatedModeModificationResult(
- response,
- options.TokenValidationOptionsOverride ? *options.TokenValidationOptionsOverride
- : this->m_tokenValidationOptions));
- return Response>(
- returnValue, std::move(response));
+ auto tracingContext(m_tracingFactory.CreateTracingContext("AddIsolatedModeCertificate", context));
+ try
+ {
+ auto const policyCertToken(
+ CreateIsolatedModeModificationToken(pemEncodedX509CertificateToAdd, existingSigningKey));
+ Azure::Core::IO::MemoryBodyStream stream(
+ reinterpret_cast(policyCertToken.data()), policyCertToken.size());
+
+ auto request = AttestationCommonRequest::CreateRequest(
+ m_endpoint, m_apiVersion, HttpMethod::Post, {"certificates:add"}, &stream);
+
+ // Send the request to the service.
+ auto response = AttestationCommonRequest::SendRequest(*m_pipeline, request, context);
+ AttestationToken returnValue(
+ ProcessIsolatedModeModificationResult(
+ response,
+ options.TokenValidationOptionsOverride ? *options.TokenValidationOptionsOverride
+ : this->m_tokenValidationOptions));
+ return Response>(
+ returnValue, std::move(response));
+ }
+ catch (std::runtime_error const& ex)
+ {
+ tracingContext.Span.AddEvent(ex);
+ throw;
+ }
}
Azure::Response>
AttestationAdministrationClient::RemoveIsolatedModeCertificate(
std::string const& pemEncodedX509CertificateToRemove,
AttestationSigningKey const& existingSigningKey,
- AddIsolatedModeCertificatesOptions const& options,
+ RemoveIsolatedModeCertificateOptions const& options,
Azure::Core::Context const& context) const
{
- // Calculate a signed (or unsigned) attestation policy token to send to the service.
- // Embed the encoded policy in the StoredAttestationPolicy.
- auto const policyCertToken(
- CreateIsolatedModeModificationToken(pemEncodedX509CertificateToRemove, existingSigningKey));
-
- Azure::Core::IO::MemoryBodyStream stream(
- reinterpret_cast(policyCertToken.data()), policyCertToken.size());
-
- auto request = AttestationCommonRequest::CreateRequest(
- m_endpoint, m_apiVersion, HttpMethod::Post, {"certificates:remove"}, &stream);
-
- // Send the request to the service.
- auto response = AttestationCommonRequest::SendRequest(*m_pipeline, request, context);
- AttestationToken returnValue(
- ProcessIsolatedModeModificationResult(
- response,
- options.TokenValidationOptionsOverride ? *options.TokenValidationOptionsOverride
- : this->m_tokenValidationOptions));
- return Response>(
- returnValue, std::move(response));
+ auto tracingContext(
+ m_tracingFactory.CreateTracingContext("RemoveIsolatedModeCertificate", context));
+ try
+ {
+ // Calculate a signed (or unsigned) attestation policy token to send to the service.
+ // Embed the encoded policy in the StoredAttestationPolicy.
+ auto const policyCertToken(
+ CreateIsolatedModeModificationToken(pemEncodedX509CertificateToRemove, existingSigningKey));
+
+ Azure::Core::IO::MemoryBodyStream stream(
+ reinterpret_cast(policyCertToken.data()), policyCertToken.size());
+
+ auto request = AttestationCommonRequest::CreateRequest(
+ m_endpoint, m_apiVersion, HttpMethod::Post, {"certificates:remove"}, &stream);
+
+ // Send the request to the service.
+ auto response = AttestationCommonRequest::SendRequest(*m_pipeline, request, context);
+ AttestationToken returnValue(
+ ProcessIsolatedModeModificationResult(
+ response,
+ options.TokenValidationOptionsOverride ? *options.TokenValidationOptionsOverride
+ : this->m_tokenValidationOptions));
+ return Response>(
+ returnValue, std::move(response));
+ }
+ catch (std::runtime_error const& ex)
+ {
+ tracingContext.Span.AddEvent(ex);
+ throw;
+ }
}
/**
- * @brief Retrieves the information needed to validate the response returned from the attestation
- * service.
+ * @brief Retrieves the information needed to validate the response returned from the
+ * attestation service.
*
* @details Validating the response returned by the attestation service requires a set of
* possible signers for the attestation token.
@@ -482,28 +529,37 @@ AttestationAdministrationClient::RemoveIsolatedModeCertificate(
* @param context Client context for the request to the service.
*/
void AttestationAdministrationClient::RetrieveResponseValidationCollateral(
- Azure::Core::Context const& context) const
+ Azure::Core::Context const& context)
{
- std::unique_lock stateLock(SharedStateLock);
-
- if (m_attestationSigners.empty())
+ auto tracingContext(m_tracingFactory.CreateTracingContext("Create", context));
+ try
{
- stateLock.unlock();
- auto request
- = AttestationCommonRequest::CreateRequest(m_endpoint, HttpMethod::Get, {"certs"}, nullptr);
- auto response = AttestationCommonRequest::SendRequest(*m_pipeline, request, context);
- auto jsonWebKeySet(JsonWebKeySetSerializer::Deserialize(response));
- TokenValidationCertificateResult returnValue;
- std::vector newValue;
- for (const auto& jwk : jsonWebKeySet.Keys)
- {
- AttestationSignerInternal internalSigner(jwk);
- newValue.push_back(internalSigner);
- }
- stateLock.lock();
+ std::unique_lock stateLock(SharedStateLock);
+
if (m_attestationSigners.empty())
{
- m_attestationSigners = newValue;
+ stateLock.unlock();
+ auto request = AttestationCommonRequest::CreateRequest(
+ m_endpoint, HttpMethod::Get, {"certs"}, nullptr);
+ auto response = AttestationCommonRequest::SendRequest(*m_pipeline, request, context);
+ auto jsonWebKeySet(JsonWebKeySetSerializer::Deserialize(response));
+ TokenValidationCertificateResult returnValue;
+ std::vector newValue;
+ for (const auto& jwk : jsonWebKeySet.Keys)
+ {
+ AttestationSignerInternal internalSigner(jwk);
+ newValue.push_back(internalSigner);
+ }
+ stateLock.lock();
+ if (m_attestationSigners.empty())
+ {
+ m_attestationSigners = newValue;
+ }
}
}
+ catch (std::runtime_error const& ex)
+ {
+ tracingContext.Span.AddEvent(ex);
+ throw;
+ }
}
diff --git a/sdk/attestation/azure-security-attestation/src/attestation_client.cpp b/sdk/attestation/azure-security-attestation/src/attestation_client.cpp
index 7fc3602b31..ee970ed8c3 100644
--- a/sdk/attestation/azure-security-attestation/src/attestation_client.cpp
+++ b/sdk/attestation/azure-security-attestation/src/attestation_client.cpp
@@ -21,6 +21,7 @@ using namespace Azure::Security::Attestation;
using namespace Azure::Security::Attestation::Models;
using namespace Azure::Security::Attestation::_detail;
using namespace Azure::Security::Attestation::Models::_detail;
+using namespace Azure::Core::Tracing::_internal;
using namespace Azure::Core::Http;
using namespace Azure::Core::Http::Policies;
using namespace Azure::Core::Http::Policies::_internal;
@@ -31,7 +32,8 @@ AttestationClient::AttestationClient(
std::shared_ptr credential,
AttestationClientOptions options)
: m_endpoint(endpoint), m_credentials(credential),
- m_tokenValidationOptions(options.TokenValidationOptions)
+ m_tokenValidationOptions(options.TokenValidationOptions),
+ m_tracingFactory(options, "security.attestation", PackageVersion::ToString())
{
std::vector> perRetrypolicies;
if (credential)
@@ -47,128 +49,179 @@ AttestationClient::AttestationClient(
std::vector> perCallpolicies;
m_pipeline = std::make_shared(
- options,
- "Attestation",
- PackageVersion::ToString(),
- std::move(perRetrypolicies),
- std::move(perCallpolicies));
+ options, std::move(perRetrypolicies), std::move(perCallpolicies));
}
Azure::Response AttestationClient::GetOpenIdMetadata(
Azure::Core::Context const& context) const
{
- auto request = AttestationCommonRequest::CreateRequest(
- m_endpoint, HttpMethod::Get, {".well-known/openid-configuration"}, nullptr);
+ auto tracingContext(m_tracingFactory.CreateTracingContext("GetOpenIdMetadata", context));
+ try
+ {
+ auto request = AttestationCommonRequest::CreateRequest(
+ m_endpoint, HttpMethod::Get, {".well-known/openid-configuration"}, nullptr);
+
+ auto response
+ = AttestationCommonRequest::SendRequest(*m_pipeline, request, tracingContext.Context);
+ auto openIdMetadata(OpenIdMetadataSerializer::Deserialize(response));
- auto response = AttestationCommonRequest::SendRequest(*m_pipeline, request, context);
- auto openIdMetadata(OpenIdMetadataSerializer::Deserialize(response));
- return Response(std::move(openIdMetadata), std::move(response));
+ return Response(std::move(openIdMetadata), std::move(response));
+ }
+ catch (std::runtime_error const& ex)
+ {
+ tracingContext.Span.AddEvent(ex);
+ throw;
+ }
}
Azure::Response AttestationClient::GetTokenValidationCertificates(
Azure::Core::Context const& context) const
{
- auto request
- = AttestationCommonRequest::CreateRequest(m_endpoint, HttpMethod::Get, {"certs"}, nullptr);
+ auto tracingContext(
+ m_tracingFactory.CreateTracingContext("GetTokenValidationCertificates", context));
+ try
+ {
- auto response = AttestationCommonRequest::SendRequest(*m_pipeline, request, context);
- auto jsonWebKeySet(JsonWebKeySetSerializer::Deserialize(response));
- TokenValidationCertificateResult returnValue;
- for (const auto& jwk : jsonWebKeySet.Keys)
+ auto request
+ = AttestationCommonRequest::CreateRequest(m_endpoint, HttpMethod::Get, {"certs"}, nullptr);
+
+ auto response
+ = AttestationCommonRequest::SendRequest(*m_pipeline, request, tracingContext.Context);
+ auto jsonWebKeySet(JsonWebKeySetSerializer::Deserialize(response));
+ TokenValidationCertificateResult returnValue;
+ for (const auto& jwk : jsonWebKeySet.Keys)
+ {
+ AttestationSignerInternal internalSigner(jwk);
+ returnValue.Signers.push_back(internalSigner);
+ }
+ return Response(returnValue, std::move(response));
+ }
+ catch (std::runtime_error const& ex)
{
- AttestationSignerInternal internalSigner(jwk);
- returnValue.Signers.push_back(internalSigner);
+ tracingContext.Span.AddEvent(ex);
+ throw;
}
- return Response(returnValue, std::move(response));
}
Azure::Response> AttestationClient::AttestSgxEnclave(
std::vector const& sgxQuote,
- AttestEnclaveOptions options,
+ AttestSgxEnclaveOptions options,
Azure::Core::Context const& context) const
{
- AttestSgxEnclaveRequest attestRequest{
- sgxQuote,
- options.InitTimeData,
- options.RunTimeData,
- options.DraftPolicyForAttestation,
- options.Nonce};
-
- const std::string serializedRequest(AttestSgxEnclaveRequestSerializer::Serialize(attestRequest));
-
- const auto encodedVector
- = std::vector(serializedRequest.begin(), serializedRequest.end());
- Azure::Core::IO::MemoryBodyStream stream(encodedVector);
- auto request = AttestationCommonRequest::CreateRequest(
- m_endpoint, m_apiVersion, HttpMethod::Post, {"attest/SgxEnclave"}, &stream);
-
- // Send the request to the service.
- auto response = AttestationCommonRequest::SendRequest(*m_pipeline, request, context);
-
- // Deserialize the Service response token and return the JSON web token returned by the service.
- std::string responseToken = AttestationServiceTokenResponseSerializer::Deserialize(response);
-
- // Parse the JWT returned by the attestation service.
- auto const token
- = AttestationTokenInternal(responseToken);
-
- // Validate the token returned by the service. Use the cached attestation signers in the
- // validation.
- token.ValidateToken(
- options.TokenValidationOptionsOverride ? *options.TokenValidationOptionsOverride
- : this->m_tokenValidationOptions,
- m_attestationSigners);
-
- // And return the attestation result to the caller.
- auto returnedToken = AttestationToken(token);
- return Response>(returnedToken, std::move(response));
+ auto tracingContext(m_tracingFactory.CreateTracingContext("AttestSgxEnclave", context));
+ try
+ {
+
+ AttestSgxEnclaveRequest attestRequest{
+ sgxQuote,
+ options.InitTimeData,
+ options.RunTimeData,
+ options.DraftPolicyForAttestation,
+ options.Nonce};
+
+ const std::string serializedRequest(
+ AttestSgxEnclaveRequestSerializer::Serialize(attestRequest));
+
+ const auto encodedVector
+ = std::vector(serializedRequest.begin(), serializedRequest.end());
+ Azure::Core::IO::MemoryBodyStream stream(encodedVector);
+ auto request = AttestationCommonRequest::CreateRequest(
+ m_endpoint, m_apiVersion, HttpMethod::Post, {"attest/SgxEnclave"}, &stream);
+
+ // Send the request to the service.
+ auto response
+ = AttestationCommonRequest::SendRequest(*m_pipeline, request, tracingContext.Context);
+
+ // Deserialize the Service response token and return the JSON web token returned by the service.
+ std::string responseToken = AttestationServiceTokenResponseSerializer::Deserialize(response);
+
+ // Parse the JWT returned by the attestation service.
+ auto const token
+ = AttestationTokenInternal(responseToken);
+
+ // Validate the token returned by the service. Use the cached attestation signers in the
+ // validation.
+ token.ValidateToken(
+ options.TokenValidationOptionsOverride ? *options.TokenValidationOptionsOverride
+ : this->m_tokenValidationOptions,
+ m_attestationSigners);
+
+ // And return the attestation result to the caller.
+ auto returnedToken = AttestationToken(token);
+ return Response>(returnedToken, std::move(response));
+ }
+ catch (std::runtime_error const& ex)
+ {
+ tracingContext.Span.AddEvent(ex);
+ throw;
+ }
}
Azure::Response> AttestationClient::AttestOpenEnclave(
std::vector const& openEnclaveReport,
- AttestEnclaveOptions options,
+ AttestOpenEnclaveOptions options,
Azure::Core::Context const& context) const
{
- AttestOpenEnclaveRequest attestRequest{
- openEnclaveReport,
- options.InitTimeData,
- options.RunTimeData,
- options.DraftPolicyForAttestation,
- options.Nonce};
- std::string serializedRequest(AttestOpenEnclaveRequestSerializer::Serialize(attestRequest));
-
- auto encodedVector = std::vector(serializedRequest.begin(), serializedRequest.end());
- Azure::Core::IO::MemoryBodyStream stream(encodedVector);
- auto request = AttestationCommonRequest::CreateRequest(
- m_endpoint, m_apiVersion, HttpMethod::Post, {"attest/OpenEnclave"}, &stream);
-
- auto response = AttestationCommonRequest::SendRequest(*m_pipeline, request, context);
- std::string responseToken = AttestationServiceTokenResponseSerializer::Deserialize(response);
- auto token
- = AttestationTokenInternal(responseToken);
- token.ValidateToken(
- options.TokenValidationOptionsOverride ? *options.TokenValidationOptionsOverride
- : this->m_tokenValidationOptions,
- m_attestationSigners);
-
- return Response>(token, std::move(response));
+ auto tracingContext(m_tracingFactory.CreateTracingContext("AttestOpenEnclave", context));
+ try
+ {
+ AttestOpenEnclaveRequest attestRequest{
+ openEnclaveReport,
+ options.InitTimeData,
+ options.RunTimeData,
+ options.DraftPolicyForAttestation,
+ options.Nonce};
+ std::string serializedRequest(AttestOpenEnclaveRequestSerializer::Serialize(attestRequest));
+
+ auto encodedVector = std::vector(serializedRequest.begin(), serializedRequest.end());
+ Azure::Core::IO::MemoryBodyStream stream(encodedVector);
+ auto request = AttestationCommonRequest::CreateRequest(
+ m_endpoint, m_apiVersion, HttpMethod::Post, {"attest/OpenEnclave"}, &stream);
+
+ auto response
+ = AttestationCommonRequest::SendRequest(*m_pipeline, request, tracingContext.Context);
+ std::string responseToken = AttestationServiceTokenResponseSerializer::Deserialize(response);
+ auto token
+ = AttestationTokenInternal(responseToken);
+ token.ValidateToken(
+ options.TokenValidationOptionsOverride ? *options.TokenValidationOptionsOverride
+ : this->m_tokenValidationOptions,
+ m_attestationSigners);
+
+ return Response>(token, std::move(response));
+ }
+ catch (std::runtime_error const& ex)
+ {
+ tracingContext.Span.AddEvent(ex);
+ throw;
+ }
}
Azure::Response AttestationClient::AttestTpm(
AttestTpmOptions const& attestTpmOptions,
Azure::Core::Context const& context) const
{
- std::string jsonToSend = TpmDataSerializer::Serialize(attestTpmOptions.ValueToSend);
- auto encodedVector = std::vector(jsonToSend.begin(), jsonToSend.end());
- Azure::Core::IO::MemoryBodyStream stream(encodedVector);
-
- auto request = AttestationCommonRequest::CreateRequest(
- m_endpoint, m_apiVersion, HttpMethod::Post, {"attest/Tpm"}, &stream);
-
- // Send the request to the service.
- auto response = AttestationCommonRequest::SendRequest(*m_pipeline, request, context);
- std::string returnedBody(TpmDataSerializer::Deserialize(response));
- return Response(TpmAttestationResult{returnedBody}, std::move(response));
+ auto tracingContext(m_tracingFactory.CreateTracingContext("AttestTpm", context));
+ try
+ {
+ std::string jsonToSend = TpmDataSerializer::Serialize(attestTpmOptions.Payload);
+ auto encodedVector = std::vector(jsonToSend.begin(), jsonToSend.end());
+ Azure::Core::IO::MemoryBodyStream stream(encodedVector);
+
+ auto request = AttestationCommonRequest::CreateRequest(
+ m_endpoint, m_apiVersion, HttpMethod::Post, {"attest/Tpm"}, &stream);
+
+ // Send the request to the service.
+ auto response
+ = AttestationCommonRequest::SendRequest(*m_pipeline, request, tracingContext.Context);
+ std::string returnedBody(TpmDataSerializer::Deserialize(response));
+ return Response(TpmAttestationResult{returnedBody}, std::move(response));
+ }
+ catch (std::runtime_error const& ex)
+ {
+ tracingContext.Span.AddEvent(ex);
+ throw;
+ }
}
namespace {
@@ -184,31 +237,41 @@ std::shared_timed_mutex SharedStateLock;
*
* @param context Client context for the request to the service.
*/
-void AttestationClient::RetrieveResponseValidationCollateral(
- Azure::Core::Context const& context) const
+void AttestationClient::RetrieveResponseValidationCollateral(Azure::Core::Context const& context)
{
- std::unique_lock stateLock(SharedStateLock);
-
- if (m_attestationSigners.empty())
+ auto tracingContext(m_tracingFactory.CreateTracingContext("Create", context));
+ try
{
- stateLock.unlock();
- auto request
- = AttestationCommonRequest::CreateRequest(m_endpoint, HttpMethod::Get, {"certs"}, nullptr);
- auto response = AttestationCommonRequest::SendRequest(*m_pipeline, request, context);
- auto jsonWebKeySet(JsonWebKeySetSerializer::Deserialize(response));
- TokenValidationCertificateResult returnValue;
- std::vector newValue;
- for (const auto& jwk : jsonWebKeySet.Keys)
- {
- AttestationSignerInternal internalSigner(jwk);
- newValue.push_back(internalSigner);
- }
- stateLock.lock();
+ std::unique_lock stateLock(SharedStateLock);
+
if (m_attestationSigners.empty())
{
- m_attestationSigners = newValue;
+ stateLock.unlock();
+ auto request = AttestationCommonRequest::CreateRequest(
+ m_endpoint, HttpMethod::Get, {"certs"}, nullptr);
+ auto response
+ = AttestationCommonRequest::SendRequest(*m_pipeline, request, tracingContext.Context);
+ auto jsonWebKeySet(JsonWebKeySetSerializer::Deserialize(response));
+ TokenValidationCertificateResult returnValue;
+ std::vector newValue;
+ for (const auto& jwk : jsonWebKeySet.Keys)
+ {
+ AttestationSignerInternal internalSigner(jwk);
+ newValue.push_back(internalSigner);
+ }
+ stateLock.lock();
+ if (m_attestationSigners.empty())
+ {
+ m_attestationSigners = newValue;
+ }
+ tracingContext.Span.SetStatus(SpanStatus::Ok);
}
}
+ catch (std::runtime_error const& ex)
+ {
+ tracingContext.Span.AddEvent(ex);
+ throw;
+ }
}
/** @brief Construct a new Attestation Client object
@@ -217,47 +280,14 @@ void AttestationClient::RetrieveResponseValidationCollateral(
* @param credential The authentication method to use (required for TPM attestation).
* @param options The options to customize the client behavior.
*/
-AttestationClient AttestationClient::Create(
+Azure::Security::Attestation::AttestationClient AttestationClient::Create(
std::string const& endpoint,
std::shared_ptr credential,
- AttestationClientOptions options,
+ AttestationClientOptions const& options,
Azure::Core::Context const& context)
{
AttestationClient returnValue(endpoint, credential, options);
returnValue.RetrieveResponseValidationCollateral(context);
- return returnValue;
-}
-
-/** @brief Construct a new anonymous Attestation Client object
- *
- * @param endpoint The URL address where the client will send the requests to.
- * @param options The options to customize the client behavior.
- *
- * @note TPM attestation requires an authenticated attestation client.
- */
-AttestationClient AttestationClient::Create(
- std::string const& endpoint,
- AttestationClientOptions options,
- Azure::Core::Context const& context)
-{
- return Create(endpoint, nullptr, options, context);
-}
-
-/** @brief Construct a new Attestation Client object
- *
- * @param endpoint The URL address where the client will send the requests to.
- * @param credential The authentication method to use (required for TPM attestation).
- * @param options The options to customize the client behavior.
- */
-std::unique_ptr AttestationClient::CreatePointer(
- std::string const& endpoint,
- std::shared_ptr credential,
- AttestationClientOptions options,
- Azure::Core::Context const& context)
-{
- std::unique_ptr returnValue(
- new AttestationClient(endpoint, credential, options));
- returnValue->RetrieveResponseValidationCollateral(context);
// Release the client pointer from the unique pointer to let the parent manage it.
return returnValue;
}
@@ -269,10 +299,10 @@ std::unique_ptr AttestationClient::CreatePointer(
*
* @note TPM attestation requires an authenticated attestation client.
*/
-std::unique_ptr AttestationClient::CreatePointer(
+Azure::Security::Attestation::AttestationClient AttestationClient::Create(
std::string const& endpoint,
AttestationClientOptions options,
Azure::Core::Context const& context)
{
- return CreatePointer(endpoint, nullptr, options, context);
+ return Create(endpoint, nullptr, options, context);
}
diff --git a/sdk/attestation/azure-security-attestation/src/private/attestation_client_private.cpp b/sdk/attestation/azure-security-attestation/src/private/attestation_client_private.cpp
index 073c0fe1c7..c3237bde0a 100644
--- a/sdk/attestation/azure-security-attestation/src/private/attestation_client_private.cpp
+++ b/sdk/attestation/azure-security-attestation/src/private/attestation_client_private.cpp
@@ -32,7 +32,7 @@ namespace Azure {
m_signer.KeyId = jwk.Kid;
if (jwk.X5c)
{
- m_signer.CertificateChain = std::vector();
+ m_signer.CertificateChain = std::vector{};
for (const auto& X5c : *jwk.X5c)
{
m_signer.CertificateChain->push_back(Cryptography::PemFromBase64(X5c, "CERTIFICATE"));
diff --git a/sdk/attestation/azure-security-attestation/src/private/attestation_client_private.hpp b/sdk/attestation/azure-security-attestation/src/private/attestation_client_private.hpp
index 44cef11345..bfc68430b3 100644
--- a/sdk/attestation/azure-security-attestation/src/private/attestation_client_private.hpp
+++ b/sdk/attestation/azure-security-attestation/src/private/attestation_client_private.hpp
@@ -30,7 +30,7 @@ namespace Azure { namespace Security { namespace Attestation { namespace _detail
template class EmptyDeserializer {
public:
- static T Deserialize(Azure::Core::Json::_internal::json const&) { return T(); }
+ static T Deserialize(Azure::Core::Json::_internal::json const&) { return T{}; }
};
template > class AttestationTokenInternal {
@@ -170,7 +170,7 @@ namespace Azure { namespace Security { namespace Attestation { namespace _detail
pemEncodedChain.push_back(_detail::Cryptography::PemFromBase64(X5c, "CERTIFICATE"));
}
returnValue.push_back(
- Models::AttestationSigner{Azure::Nullable(), pemEncodedChain});
+ Models::AttestationSigner{Azure::Nullable