diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index a9f26317a4af..6ac611d7c590 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -180,6 +180,12 @@ # ServiceLabel: %Bot Service # ServiceOwners: @sgellock +#PRLabel %Code Signing +/sdk/trustedsigning/ @jaxelr + +# ServiceLabel: %Code Signing +# ServiceOwners: @jaxelr + # PRLabel: %Cognitive - Language /sdk/cognitivelanguage/ @quentinRobinson @bidisha-c diff --git a/sdk/trustedsigning/Azure.Developer.Signing/Azure.Developer.Signing.sln b/sdk/trustedsigning/Azure.Developer.Signing/Azure.Developer.Signing.sln new file mode 100644 index 000000000000..da294abeea56 --- /dev/null +++ b/sdk/trustedsigning/Azure.Developer.Signing/Azure.Developer.Signing.sln @@ -0,0 +1,36 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.3.32825.248 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Azure.Core.TestFramework", "..\..\core\Azure.Core.TestFramework\src\Azure.Core.TestFramework.csproj", "{ECC730C1-4AEA-420C-916A-66B19B79E4DC}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Azure.Developer.Signing", "src\Azure.Developer.Signing.csproj", "{FC39285B-629E-4C91-8728-28C5CAE9CDA0}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Azure.Developer.Signing.Tests", "tests\Azure.Developer.Signing.Tests.csproj", "{700074ED-BCA1-4F21-9F72-ACA7EB36C6E5}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {ECC730C1-4AEA-420C-916A-66B19B79E4DC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {ECC730C1-4AEA-420C-916A-66B19B79E4DC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {ECC730C1-4AEA-420C-916A-66B19B79E4DC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {ECC730C1-4AEA-420C-916A-66B19B79E4DC}.Release|Any CPU.Build.0 = Release|Any CPU + {FC39285B-629E-4C91-8728-28C5CAE9CDA0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FC39285B-629E-4C91-8728-28C5CAE9CDA0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FC39285B-629E-4C91-8728-28C5CAE9CDA0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FC39285B-629E-4C91-8728-28C5CAE9CDA0}.Release|Any CPU.Build.0 = Release|Any CPU + {700074ED-BCA1-4F21-9F72-ACA7EB36C6E5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {700074ED-BCA1-4F21-9F72-ACA7EB36C6E5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {700074ED-BCA1-4F21-9F72-ACA7EB36C6E5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {700074ED-BCA1-4F21-9F72-ACA7EB36C6E5}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {A97F4B90-2591-4689-B1F8-5F21FE6D6CAE} + EndGlobalSection +EndGlobal diff --git a/sdk/trustedsigning/Azure.Developer.Signing/CHANGELOG.md b/sdk/trustedsigning/Azure.Developer.Signing/CHANGELOG.md new file mode 100644 index 000000000000..39f55e08ac30 --- /dev/null +++ b/sdk/trustedsigning/Azure.Developer.Signing/CHANGELOG.md @@ -0,0 +1,13 @@ +# Release History + +## 1.0.0-beta.1 (Unreleased) + +Initial release of the Azure developer signing library + +### Features Added + +### Breaking Changes + +### Bugs Fixed + +### Other Changes diff --git a/sdk/trustedsigning/Azure.Developer.Signing/Directory.Build.props b/sdk/trustedsigning/Azure.Developer.Signing/Directory.Build.props new file mode 100644 index 000000000000..63bd836ad44b --- /dev/null +++ b/sdk/trustedsigning/Azure.Developer.Signing/Directory.Build.props @@ -0,0 +1,6 @@ + + + + diff --git a/sdk/trustedsigning/Azure.Developer.Signing/README.md b/sdk/trustedsigning/Azure.Developer.Signing/README.md new file mode 100644 index 000000000000..7afd77cf032f --- /dev/null +++ b/sdk/trustedsigning/Azure.Developer.Signing/README.md @@ -0,0 +1,154 @@ +# Azure Developer Signing client library for .NET + +Azure.Developer.Signing is a fully managed end-to-end signing solution for 3rd party developers. The Azure.Developer.Signing client library allows you to easily sign your bits without the hassle of managing certificate lifetimes. + +Use the client library for Azure Developer Signing to: + +* [Perform Signing of bits](https://learn.microsoft.com/azure/trusted-signing/how-to-signing-integrations/) +* [Access Signing information](https://learn.microsoft.com/azure/trusted-signing/how-to-sign-ci-policy/) + +[Source code][source_root] | [Package (NuGet)][package] | [API reference documentation][reference_docs] | [Product documentation][azconfig_docs] | [Samples][source_samples] + + [Source code](https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/trustedsigning/Azure.Developer.Signing/src) | [Package (NuGet)](https://www.nuget.org/packages) | [API reference documentation](https://azure.github.io/azure-sdk-for-net) | [Product documentation](https://docs.microsoft.com/azure) + +## Getting started + +### Install the package + +Install the client library for .NET with [NuGet](https://www.nuget.org/ ): + +```dotnetcli +dotnet add package Azure.Developer.Signing --prerelease +``` + +### Prerequisites + +You must have an [Azure subscription](https://azure.microsoft.com/free/dotnet/). It is recommended that you compile using the latest [.NET SDK](https://dotnet.microsoft.com/download) 6.0 or higher with a [language version](https://docs.microsoft.com/dotnet/csharp/language-reference/configure-language-version#override-a-default) of `latest`. + +To have the capability to perform signing actions a Signing Account, Certificate Profile and Identity Validation must be created. These resources can be created using the Azure portal or the Azure CLI. + +### Authenticate the client + +To access the client, you can use the [Token Credential authentication](https://learn.microsoft.com/dotnet/api/azure.core.tokencredential) method provided by Standard Azure Active Directory. The identity interacting with the resource must have the role of `Code Signing Certificate Profile Signer` on the resource. These roles need to be assigned from the Azure portal or by using the Azure CLI. + +To use Entra ID authentication, add the Azure Identity package: + +`dotnet add package Azure.Identity` + +You will also need to register a new AAD application, or run locally or in an environment with a managed identity. If using an application, set the values of the client ID, tenant ID, and client secret of the AAD application as environment variables: AZURE_CLIENT_ID, AZURE_TENANT_ID, AZURE_CLIENT_SECRET. + +## Key concepts + +This library interacts with the Azure Developer Signing service using two principal concepts, these are: + +- `Trusted Signing Accounts` – A Signing Account is the logical container holding certificate profiles and identity validations and is considered a Azure Developer Signing resource. +- `Certificate Profile` – A Certificate Profile is the template with the information that is used in the issued certificates. It is a sub-resource to a Code Signing Account resource. +- `Identity Validation` - An Identity Validation resource is the identity of the legal business or individual. This information will be in the Subject Name of the certificates and therefore is a pre-requisite resource to be able to create a Certificate Profile. + +Since the interaction of the client is at the certificate profile level, the client is designed to interact with this entity. A region must be provided to ensure the request is routed to the specific appropiate environment. + +```C# Snippet:Azure_Developer_Signing_CreateCertificateProfileClient +var credential = new DefaultAzureCredential(); +CertificateProfile certificateProfileClient = new SigningClient(region, credential).GetCertificateProfileClient(); +``` + +### Thread safety + +We guarantee that all client instance methods are thread-safe and independent of each other ([guideline](https://azure.github.io/azure-sdk/dotnet_introduction.html#dotnet-service-methods-thread-safety)). This ensures that the recommendation of reusing client instances is always safe, even across threads. + +### Additional concepts + +[Client options](https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/core/Azure.Core/README.md#configuring-service-clients-using-clientoptions) | +[Accessing the response](https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/core/Azure.Core/README.md#accessing-http-response-details-using-responset) | +[Long-running operations](https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/core/Azure.Core/README.md#consuming-long-running-operations-using-operationt) | +[Handling failures](https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/core/Azure.Core/README.md#reporting-errors-requestfailedexception) | +[Diagnostics](https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/core/Azure.Core/samples/Diagnostics.md) | +[Mocking](https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/core/Azure.Core/README.md#mocking) | +[Client lifetime](https://devblogs.microsoft.com/azure-sdk/lifetime-management-and-thread-safety-guarantees-of-azure-sdk-net-clients/) + + +## Examples + +You can familiarize yourself with different APIs using [Samples](https://github.com/Azure/azure-sdk-for-net/tree/main/sdk/trustedsigning/Azure.Developer.Signing/samples). + +### Signing bytes + +Sign the digest corresponding to a file using an algorithm. + +```C# Snippet:Azure_Developer_Signing_SigningBytes +CertificateProfile certificateProfileClient = new SigningClient(region, credential).GetCertificateProfileClient(); + +using RequestContent content = RequestContent.Create(new +{ + signatureAlgorithm, + digest, +}); + +Operation operation = certificateProfileClient.Sign(WaitUntil.Completed, accountName, profileName, content); +BinaryData responseData = operation.Value; + +JsonElement result = JsonDocument.Parse(responseData.ToStream()).RootElement; +``` + +### List available customer extended key usages (EKUs) + +Request all the available customer extended key usages from a certificate profile. + +```C# Snippet:Azure_Developer_Signing_GetExtendedKeyUsages +CertificateProfile certificateProfileClient = new SigningClient(region, credential).GetCertificateProfileClient(); + +List ekus = new(); + +foreach (BinaryData item in certificateProfileClient.GetExtendedKeyUsages(accountName, profileName, null)) +{ + JsonElement result = JsonDocument.Parse(item.ToStream()).RootElement; + string eku = result.GetProperty("eku").ToString(); + + ekus.Add(eku); +} +``` + +### Download the root certificate + +Request the sign root certificate from a certificate profile. + +```C# Snippet:Azure_Developer_Signing_GetSignRootCertificate +CertificateProfile certificateProfileClient = new SigningClient(region, credential).GetCertificateProfileClient(); + +Response response = certificateProfileClient.GetSignRootCertificate(accountName, profileName); + +byte[] rootCertificate = response.Value.ToArray(); +``` + +## Troubleshooting + +Errors may occur during the Signing Action due to problems with Azure resources or your Azure configuration. You can view the `errorDetails` property on the SignResult if the signing action fails, it will show more information about the problem and how to resolve it. + +Ensure that your client has the correct permissions to perform the action you are trying to perform. For example, if you are trying to sign a file, ensure that your client has the `Code Signing Certificate Profile Signer` role on the resource. + +## Contributing + +See the [DeveloperSigning CONTRIBUTING.md][developersigning_contrib] for details on building, testing, and contributing to this library. + +This project welcomes contributions and suggestions. Most contributions require you to agree to a Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us the rights to use your contribution. For details, visit [cla.microsoft.com][cla]. + +When you submit a pull request, a CLA-bot will automatically determine whether you need to provide a CLA and decorate the PR appropriately (e.g., label, comment). Simply follow the instructions provided by the bot. You will only need to do this once across all repos using our CLA. + +This project has adopted the [Microsoft Open Source Code of Conduct][code_of_conduct]. For more information see the [Code of Conduct FAQ][code_of_conduct_faq] or contact [opencode@microsoft.com][email_opencode] with any additional questions or comments. + + +[developersigning_contrib]: https://github.com/Azure/azure-sdk-for-net/blob/main/CONTRIBUTING.md +[style-guide-msft]: https://docs.microsoft.com/style-guide/capitalization +[style-guide-cloud]: https://aka.ms/azsdk/cloud-style-guide +[cla]: https://cla.microsoft.com +[code_of_conduct]: https://opensource.microsoft.com/codeofconduct/ +[code_of_conduct_faq]: https://opensource.microsoft.com/codeofconduct/faq/ +[email_opencode]: mailto:opencode@microsoft.com + +![Impressions](https://azure-sdk-impressions.azurewebsites.net/api/impressions/azure-sdk-for-net/sdk/trustedsigning/Azure.Developer.Signing/README.png) + +## Next steps + +For more information on Azure SDK, please refer to [this website](https://azure.github.io/azure-sdk/) + +![Impressions](https://azure-sdk-impressions.azurewebsites.net/api/impressions/azure-sdk-for-net%2Fsdk%2Ftrustedsigning%2FAzure.Developer.Signing%2FREADME.png) diff --git a/sdk/trustedsigning/Azure.Developer.Signing/api/Azure.Developer.Signing.netstandard2.0.cs b/sdk/trustedsigning/Azure.Developer.Signing/api/Azure.Developer.Signing.netstandard2.0.cs new file mode 100644 index 000000000000..6f9d346053a6 --- /dev/null +++ b/sdk/trustedsigning/Azure.Developer.Signing/api/Azure.Developer.Signing.netstandard2.0.cs @@ -0,0 +1,136 @@ +namespace Azure.Developer.Signing +{ + public partial class CertificateProfile + { + protected CertificateProfile() { } + public virtual Azure.Core.Pipeline.HttpPipeline Pipeline { get { throw null; } } + public virtual Azure.Pageable GetExtendedKeyUsages(string accountName, string certificateProfile, Azure.RequestContext context) { throw null; } + public virtual Azure.Pageable GetExtendedKeyUsages(string accountName, string certificateProfile, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public virtual Azure.AsyncPageable GetExtendedKeyUsagesAsync(string accountName, string certificateProfile, Azure.RequestContext context) { throw null; } + public virtual Azure.AsyncPageable GetExtendedKeyUsagesAsync(string accountName, string certificateProfile, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public virtual Azure.Response GetSigningStatus(string accountName, string certificateProfile, string operationId, Azure.RequestContext context) { throw null; } + public virtual Azure.Response GetSigningStatus(string accountName, string certificateProfile, string operationId, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public virtual System.Threading.Tasks.Task GetSigningStatusAsync(string accountName, string certificateProfile, string operationId, Azure.RequestContext context) { throw null; } + public virtual System.Threading.Tasks.Task> GetSigningStatusAsync(string accountName, string certificateProfile, string operationId, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public virtual Azure.Response GetSignRootCertificate(string accountName, string certificateProfile, Azure.RequestContext context) { throw null; } + public virtual Azure.Response GetSignRootCertificate(string accountName, string certificateProfile, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public virtual System.Threading.Tasks.Task GetSignRootCertificateAsync(string accountName, string certificateProfile, Azure.RequestContext context) { throw null; } + public virtual System.Threading.Tasks.Task> GetSignRootCertificateAsync(string accountName, string certificateProfile, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public virtual Azure.Operation Sign(Azure.WaitUntil waitUntil, string accountName, string certificateProfile, Azure.Core.RequestContent content, string clientVersion = null, string xCorrelationId = null, Azure.RequestContext context = null) { throw null; } + public virtual Azure.Operation Sign(Azure.WaitUntil waitUntil, string accountName, string certificateProfile, Azure.Developer.Signing.SigningPayloadOptions signingPayloadOptions, string clientVersion = null, string xCorrelationId = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public virtual System.Threading.Tasks.Task> SignAsync(Azure.WaitUntil waitUntil, string accountName, string certificateProfile, Azure.Core.RequestContent content, string clientVersion = null, string xCorrelationId = null, Azure.RequestContext context = null) { throw null; } + public virtual System.Threading.Tasks.Task> SignAsync(Azure.WaitUntil waitUntil, string accountName, string certificateProfile, Azure.Developer.Signing.SigningPayloadOptions signingPayloadOptions, string clientVersion = null, string xCorrelationId = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + } + public static partial class DeveloperSigningModelFactory + { + public static Azure.Developer.Signing.ExtendedKeyUsage ExtendedKeyUsage(string eku = null) { throw null; } + public static Azure.Developer.Signing.OperationStatusSignResultError OperationStatusSignResultError(string id = null, Azure.Developer.Signing.OperationState status = default(Azure.Developer.Signing.OperationState), Azure.ResponseError error = null, Azure.Developer.Signing.SignResult result = null) { throw null; } + public static Azure.Developer.Signing.SigningPayloadOptions SigningPayloadOptions(Azure.Developer.Signing.SignatureAlgorithm signatureAlgorithm = Azure.Developer.Signing.SignatureAlgorithm.RS256, System.BinaryData digest = null, System.Collections.Generic.IEnumerable fileHashList = null, System.Collections.Generic.IEnumerable authenticodeHashList = null) { throw null; } + public static Azure.Developer.Signing.SignResult SignResult(System.BinaryData signature = null, System.BinaryData signingCertificate = null) { throw null; } + } + public partial class ExtendedKeyUsage : System.ClientModel.Primitives.IJsonModel, System.ClientModel.Primitives.IPersistableModel + { + internal ExtendedKeyUsage() { } + public string Eku { get { throw null; } } + Azure.Developer.Signing.ExtendedKeyUsage System.ClientModel.Primitives.IJsonModel.Create(ref System.Text.Json.Utf8JsonReader reader, System.ClientModel.Primitives.ModelReaderWriterOptions options) { throw null; } + void System.ClientModel.Primitives.IJsonModel.Write(System.Text.Json.Utf8JsonWriter writer, System.ClientModel.Primitives.ModelReaderWriterOptions options) { } + Azure.Developer.Signing.ExtendedKeyUsage System.ClientModel.Primitives.IPersistableModel.Create(System.BinaryData data, System.ClientModel.Primitives.ModelReaderWriterOptions options) { throw null; } + string System.ClientModel.Primitives.IPersistableModel.GetFormatFromOptions(System.ClientModel.Primitives.ModelReaderWriterOptions options) { throw null; } + System.BinaryData System.ClientModel.Primitives.IPersistableModel.Write(System.ClientModel.Primitives.ModelReaderWriterOptions options) { throw null; } + } + [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)] + public readonly partial struct OperationState : System.IEquatable + { + private readonly object _dummy; + private readonly int _dummyPrimitive; + public OperationState(string value) { throw null; } + public static Azure.Developer.Signing.OperationState Canceled { get { throw null; } } + public static Azure.Developer.Signing.OperationState Failed { get { throw null; } } + public static Azure.Developer.Signing.OperationState NotStarted { get { throw null; } } + public static Azure.Developer.Signing.OperationState Running { get { throw null; } } + public static Azure.Developer.Signing.OperationState Succeeded { get { throw null; } } + public bool Equals(Azure.Developer.Signing.OperationState other) { throw null; } + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + public override bool Equals(object obj) { throw null; } + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + public override int GetHashCode() { throw null; } + public static bool operator ==(Azure.Developer.Signing.OperationState left, Azure.Developer.Signing.OperationState right) { throw null; } + public static implicit operator Azure.Developer.Signing.OperationState (string value) { throw null; } + public static bool operator !=(Azure.Developer.Signing.OperationState left, Azure.Developer.Signing.OperationState right) { throw null; } + public override string ToString() { throw null; } + } + public partial class OperationStatusSignResultError : System.ClientModel.Primitives.IJsonModel, System.ClientModel.Primitives.IPersistableModel + { + internal OperationStatusSignResultError() { } + public Azure.ResponseError Error { get { throw null; } } + public string Id { get { throw null; } } + public Azure.Developer.Signing.SignResult Result { get { throw null; } } + public Azure.Developer.Signing.OperationState Status { get { throw null; } } + Azure.Developer.Signing.OperationStatusSignResultError System.ClientModel.Primitives.IJsonModel.Create(ref System.Text.Json.Utf8JsonReader reader, System.ClientModel.Primitives.ModelReaderWriterOptions options) { throw null; } + void System.ClientModel.Primitives.IJsonModel.Write(System.Text.Json.Utf8JsonWriter writer, System.ClientModel.Primitives.ModelReaderWriterOptions options) { } + Azure.Developer.Signing.OperationStatusSignResultError System.ClientModel.Primitives.IPersistableModel.Create(System.BinaryData data, System.ClientModel.Primitives.ModelReaderWriterOptions options) { throw null; } + string System.ClientModel.Primitives.IPersistableModel.GetFormatFromOptions(System.ClientModel.Primitives.ModelReaderWriterOptions options) { throw null; } + System.BinaryData System.ClientModel.Primitives.IPersistableModel.Write(System.ClientModel.Primitives.ModelReaderWriterOptions options) { throw null; } + } + public enum SignatureAlgorithm + { + RS256 = 0, + RS384 = 1, + RS512 = 2, + PS256 = 3, + PS384 = 4, + PS512 = 5, + ES256 = 6, + ES384 = 7, + ES512 = 8, + ES256K = 9, + } + public partial class SigningClient + { + protected SigningClient() { } + public SigningClient(string region, Azure.Core.TokenCredential credential) { } + public SigningClient(string region, Azure.Core.TokenCredential credential, Azure.Developer.Signing.SigningClientOptions options) { } + public virtual Azure.Core.Pipeline.HttpPipeline Pipeline { get { throw null; } } + public virtual Azure.Developer.Signing.CertificateProfile GetCertificateProfileClient(string apiVersion = "2023-06-15-preview") { throw null; } + } + public partial class SigningClientOptions : Azure.Core.ClientOptions + { + public SigningClientOptions(Azure.Developer.Signing.SigningClientOptions.ServiceVersion version = Azure.Developer.Signing.SigningClientOptions.ServiceVersion.V2023_06_15_Preview) { } + public enum ServiceVersion + { + V2023_06_15_Preview = 1, + } + } + public partial class SigningPayloadOptions : System.ClientModel.Primitives.IJsonModel, System.ClientModel.Primitives.IPersistableModel + { + public SigningPayloadOptions(Azure.Developer.Signing.SignatureAlgorithm signatureAlgorithm, System.BinaryData digest) { } + public System.Collections.Generic.IList AuthenticodeHashList { get { throw null; } } + public System.BinaryData Digest { get { throw null; } } + public System.Collections.Generic.IList FileHashList { get { throw null; } } + public Azure.Developer.Signing.SignatureAlgorithm SignatureAlgorithm { get { throw null; } } + Azure.Developer.Signing.SigningPayloadOptions System.ClientModel.Primitives.IJsonModel.Create(ref System.Text.Json.Utf8JsonReader reader, System.ClientModel.Primitives.ModelReaderWriterOptions options) { throw null; } + void System.ClientModel.Primitives.IJsonModel.Write(System.Text.Json.Utf8JsonWriter writer, System.ClientModel.Primitives.ModelReaderWriterOptions options) { } + Azure.Developer.Signing.SigningPayloadOptions System.ClientModel.Primitives.IPersistableModel.Create(System.BinaryData data, System.ClientModel.Primitives.ModelReaderWriterOptions options) { throw null; } + string System.ClientModel.Primitives.IPersistableModel.GetFormatFromOptions(System.ClientModel.Primitives.ModelReaderWriterOptions options) { throw null; } + System.BinaryData System.ClientModel.Primitives.IPersistableModel.Write(System.ClientModel.Primitives.ModelReaderWriterOptions options) { throw null; } + } + public partial class SignResult : System.ClientModel.Primitives.IJsonModel, System.ClientModel.Primitives.IPersistableModel + { + internal SignResult() { } + public System.BinaryData Signature { get { throw null; } } + public System.BinaryData SigningCertificate { get { throw null; } } + Azure.Developer.Signing.SignResult System.ClientModel.Primitives.IJsonModel.Create(ref System.Text.Json.Utf8JsonReader reader, System.ClientModel.Primitives.ModelReaderWriterOptions options) { throw null; } + void System.ClientModel.Primitives.IJsonModel.Write(System.Text.Json.Utf8JsonWriter writer, System.ClientModel.Primitives.ModelReaderWriterOptions options) { } + Azure.Developer.Signing.SignResult System.ClientModel.Primitives.IPersistableModel.Create(System.BinaryData data, System.ClientModel.Primitives.ModelReaderWriterOptions options) { throw null; } + string System.ClientModel.Primitives.IPersistableModel.GetFormatFromOptions(System.ClientModel.Primitives.ModelReaderWriterOptions options) { throw null; } + System.BinaryData System.ClientModel.Primitives.IPersistableModel.Write(System.ClientModel.Primitives.ModelReaderWriterOptions options) { throw null; } + } +} +namespace Microsoft.Extensions.Azure +{ + public static partial class DeveloperSigningClientBuilderExtensions + { + public static Azure.Core.Extensions.IAzureClientBuilder AddSigningClient(this TBuilder builder, string region) where TBuilder : Azure.Core.Extensions.IAzureClientFactoryBuilderWithCredential { throw null; } + public static Azure.Core.Extensions.IAzureClientBuilder AddSigningClient(this TBuilder builder, TConfiguration configuration) where TBuilder : Azure.Core.Extensions.IAzureClientFactoryBuilderWithConfiguration { throw null; } + } +} diff --git a/sdk/trustedsigning/Azure.Developer.Signing/assets.json b/sdk/trustedsigning/Azure.Developer.Signing/assets.json new file mode 100644 index 000000000000..1d8d65e1a586 --- /dev/null +++ b/sdk/trustedsigning/Azure.Developer.Signing/assets.json @@ -0,0 +1,6 @@ +{ + "AssetsRepo": "Azure/azure-sdk-assets", + "AssetsRepoPrefixPath": "net", + "TagPrefix": "net/trustedsigning/Azure.Developer.Signing", + "Tag": "net/trustedsigning/Azure.Developer.Signing_092afa324f" +} diff --git a/sdk/trustedsigning/Azure.Developer.Signing/samples/README.md b/sdk/trustedsigning/Azure.Developer.Signing/samples/README.md new file mode 100644 index 000000000000..a4dce8eb7058 --- /dev/null +++ b/sdk/trustedsigning/Azure.Developer.Signing/samples/README.md @@ -0,0 +1,16 @@ +--- +page_type: sample +languages: +- csharp +products: +# Including relevant stubs from https://review.docs.microsoft.com/help/contribute/metadata-taxonomies#product +- azure +name: Azure.Developer.Signing samples for .NET +description: Samples for the Azure.Developer.Signing client library. +--- + +# Azure.Developer.Signing Samples + +* [Submit a signing request](https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/trustedsigning/Azure.Developer.Signing/samples/Sample_Sign.md) +* [Get a profile eku](https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/trustedsigning/Azure.Developer.Signing/samples/Sample_GetProfileEku.md) +* [Get a profile root certificate](https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/trustedsigning/Azure.Developer.Signing/samples/Sample_GetProfileRootCertificate.md) diff --git a/sdk/trustedsigning/Azure.Developer.Signing/samples/Sample_GetProfileEku.md b/sdk/trustedsigning/Azure.Developer.Signing/samples/Sample_GetProfileEku.md new file mode 100644 index 000000000000..534eba5d9fe2 --- /dev/null +++ b/sdk/trustedsigning/Azure.Developer.Signing/samples/Sample_GetProfileEku.md @@ -0,0 +1,21 @@ +# # Azure.Developer.Signing samples - Get customer extended key usages + +To use these samples, you'll first need to set up resources. See [getting started](https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/trustedsigning/Azure.Developer.Signing/README.md#getting-started) for details. + +## Get customer extended key usages + +The extended key usages are a piece of data used to describe the purpose of a certificate. This sample demonstrates how to get the available customer extended key usages from a certificate profile. + +```C# Snippet:Azure_Developer_Signing_GetExtendedKeyUsages +CertificateProfile certificateProfileClient = new SigningClient(region, credential).GetCertificateProfileClient(); + +List ekus = new(); + +foreach (BinaryData item in certificateProfileClient.GetExtendedKeyUsages(accountName, profileName, null)) +{ + JsonElement result = JsonDocument.Parse(item.ToStream()).RootElement; + string eku = result.GetProperty("eku").ToString(); + + ekus.Add(eku); +} +``` diff --git a/sdk/trustedsigning/Azure.Developer.Signing/samples/Sample_GetProfileRootCertificate.md b/sdk/trustedsigning/Azure.Developer.Signing/samples/Sample_GetProfileRootCertificate.md new file mode 100644 index 000000000000..5c823f90fde1 --- /dev/null +++ b/sdk/trustedsigning/Azure.Developer.Signing/samples/Sample_GetProfileRootCertificate.md @@ -0,0 +1,15 @@ +# # Azure.Developer.Signing samples - Get certificate profile sign root certificate + +To use these samples, you'll first need to set up resources. See [getting started](https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/trustedsigning/Azure.Developer.Signing/README.md#getting-started) for details. + +# Get certificate profile sign root certificate + +Interaction with the sign root certificate operation requires a `CertificateProfile` client. Certificates can be converted into valid X509 certificates using the `X509Certificate2` class from `System.Security.Cryptography.X509Certificates` namespace. + +```C# Snippet:Azure_Developer_Signing_GetSignRootCertificate +CertificateProfile certificateProfileClient = new SigningClient(region, credential).GetCertificateProfileClient(); + +Response response = certificateProfileClient.GetSignRootCertificate(accountName, profileName); + +byte[] rootCertificate = response.Value.ToArray(); +``` diff --git a/sdk/trustedsigning/Azure.Developer.Signing/samples/Sample_Sign.md b/sdk/trustedsigning/Azure.Developer.Signing/samples/Sample_Sign.md new file mode 100644 index 000000000000..93cfc5723f04 --- /dev/null +++ b/sdk/trustedsigning/Azure.Developer.Signing/samples/Sample_Sign.md @@ -0,0 +1,22 @@ +# Azure.Developer.Signing samples - Signing + +To use these samples, you'll first need to set up resources. See [getting started](https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/trustedsigning/Azure.Developer.Signing/README.md#getting-started) for details. + +# Submit a signing action + +The signing action is used to sign a certificate. This sample demonstrates how to submit a request to sign a byte array using a signature algorithm. + +```C# Snippet:Azure_Developer_Signing_SigningBytes +CertificateProfile certificateProfileClient = new SigningClient(region, credential).GetCertificateProfileClient(); + +using RequestContent content = RequestContent.Create(new +{ + signatureAlgorithm, + digest, +}); + +Operation operation = certificateProfileClient.Sign(WaitUntil.Completed, accountName, profileName, content); +BinaryData responseData = operation.Value; + +JsonElement result = JsonDocument.Parse(responseData.ToStream()).RootElement; +``` diff --git a/sdk/trustedsigning/Azure.Developer.Signing/src/Azure.Developer.Signing.csproj b/sdk/trustedsigning/Azure.Developer.Signing/src/Azure.Developer.Signing.csproj new file mode 100644 index 000000000000..7faaf1035a4b --- /dev/null +++ b/sdk/trustedsigning/Azure.Developer.Signing/src/Azure.Developer.Signing.csproj @@ -0,0 +1,20 @@ + + + Azure Developer Signing client library for usage with the trusted signing service to sign artifacts. + Azure Developer Signing Data Plane Library + 1.0.0-beta.1 + Azure.Developer.Signing + $(RequiredTargetFrameworks) + true + + + + + + + + + + + + diff --git a/sdk/trustedsigning/Azure.Developer.Signing/src/Generated/CertificateProfile.cs b/sdk/trustedsigning/Azure.Developer.Signing/src/Generated/CertificateProfile.cs new file mode 100644 index 000000000000..613c01e8db47 --- /dev/null +++ b/sdk/trustedsigning/Azure.Developer.Signing/src/Generated/CertificateProfile.cs @@ -0,0 +1,684 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text.Json; +using System.Threading; +using System.Threading.Tasks; +using Autorest.CSharp.Core; +using Azure.Core; +using Azure.Core.Pipeline; + +namespace Azure.Developer.Signing +{ + // Data plane generated sub-client. + /// The CertificateProfile sub-client. + public partial class CertificateProfile + { + private static readonly string[] AuthorizationScopes = new string[] { "https://codesigning.azure.net/.default" }; + private readonly TokenCredential _tokenCredential; + private readonly HttpPipeline _pipeline; + private readonly string _region; + private readonly string _apiVersion; + + /// The ClientDiagnostics is used to provide tracing support for the client library. + internal ClientDiagnostics ClientDiagnostics { get; } + + /// The HTTP pipeline for sending and receiving REST requests and responses. + public virtual HttpPipeline Pipeline => _pipeline; + + /// Initializes a new instance of CertificateProfile for mocking. + protected CertificateProfile() + { + } + + /// Initializes a new instance of CertificateProfile. + /// The handler for diagnostic messaging in the client. + /// The HTTP pipeline for sending and receiving REST requests and responses. + /// The token credential to copy. + /// The Azure region wherein requests for signing will be sent. + /// The API version to use for this operation. + internal CertificateProfile(ClientDiagnostics clientDiagnostics, HttpPipeline pipeline, TokenCredential tokenCredential, string region, string apiVersion) + { + ClientDiagnostics = clientDiagnostics; + _pipeline = pipeline; + _tokenCredential = tokenCredential; + _region = region; + _apiVersion = apiVersion; + } + + /// Gets the status of a signing operation. + /// Signing account name. + /// Signing Certificate profile name. + /// The unique ID of the operation. + /// The cancellation token to use. + /// , or is null. + /// , or is an empty string, and was expected to be non-empty. + /// This status operation requires that a Sign request has been submitted and the operationId is known. + /// + public virtual async Task> GetSigningStatusAsync(string accountName, string certificateProfile, string operationId, CancellationToken cancellationToken = default) + { + Argument.AssertNotNullOrEmpty(accountName, nameof(accountName)); + Argument.AssertNotNullOrEmpty(certificateProfile, nameof(certificateProfile)); + Argument.AssertNotNullOrEmpty(operationId, nameof(operationId)); + + RequestContext context = FromCancellationToken(cancellationToken); + Response response = await GetSigningStatusAsync(accountName, certificateProfile, operationId, context).ConfigureAwait(false); + return Response.FromValue(OperationStatusSignResultError.FromResponse(response), response); + } + + /// Gets the status of a signing operation. + /// Signing account name. + /// Signing Certificate profile name. + /// The unique ID of the operation. + /// The cancellation token to use. + /// , or is null. + /// , or is an empty string, and was expected to be non-empty. + /// This status operation requires that a Sign request has been submitted and the operationId is known. + /// + public virtual Response GetSigningStatus(string accountName, string certificateProfile, string operationId, CancellationToken cancellationToken = default) + { + Argument.AssertNotNullOrEmpty(accountName, nameof(accountName)); + Argument.AssertNotNullOrEmpty(certificateProfile, nameof(certificateProfile)); + Argument.AssertNotNullOrEmpty(operationId, nameof(operationId)); + + RequestContext context = FromCancellationToken(cancellationToken); + Response response = GetSigningStatus(accountName, certificateProfile, operationId, context); + return Response.FromValue(OperationStatusSignResultError.FromResponse(response), response); + } + + /// + /// [Protocol Method] Gets the status of a signing operation. + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// Signing account name. + /// Signing Certificate profile name. + /// The unique ID of the operation. + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// , or is null. + /// , or is an empty string, and was expected to be non-empty. + /// Service returned a non-success status code. + /// The response returned from the service. + /// + public virtual async Task GetSigningStatusAsync(string accountName, string certificateProfile, string operationId, RequestContext context) + { + Argument.AssertNotNullOrEmpty(accountName, nameof(accountName)); + Argument.AssertNotNullOrEmpty(certificateProfile, nameof(certificateProfile)); + Argument.AssertNotNullOrEmpty(operationId, nameof(operationId)); + + using var scope = ClientDiagnostics.CreateScope("CertificateProfile.GetSigningStatus"); + scope.Start(); + try + { + using HttpMessage message = CreateGetSigningStatusRequest(accountName, certificateProfile, operationId, context); + return await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + /// + /// [Protocol Method] Gets the status of a signing operation. + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// Signing account name. + /// Signing Certificate profile name. + /// The unique ID of the operation. + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// , or is null. + /// , or is an empty string, and was expected to be non-empty. + /// Service returned a non-success status code. + /// The response returned from the service. + /// + public virtual Response GetSigningStatus(string accountName, string certificateProfile, string operationId, RequestContext context) + { + Argument.AssertNotNullOrEmpty(accountName, nameof(accountName)); + Argument.AssertNotNullOrEmpty(certificateProfile, nameof(certificateProfile)); + Argument.AssertNotNullOrEmpty(operationId, nameof(operationId)); + + using var scope = ClientDiagnostics.CreateScope("CertificateProfile.GetSigningStatus"); + scope.Start(); + try + { + using HttpMessage message = CreateGetSigningStatusRequest(accountName, certificateProfile, operationId, context); + return _pipeline.ProcessMessage(message, context); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + /// Gets the signing root certificate on the certificate chain for that account and profile name. + /// Signing account name. + /// Signing Certificate profile name. + /// The cancellation token to use. + /// or is null. + /// or is an empty string, and was expected to be non-empty. + /// The root certificate is generated as part of the initial account creation and it is used to sign the bits for the profile provided. + /// + public virtual async Task> GetSignRootCertificateAsync(string accountName, string certificateProfile, CancellationToken cancellationToken = default) + { + Argument.AssertNotNullOrEmpty(accountName, nameof(accountName)); + Argument.AssertNotNullOrEmpty(certificateProfile, nameof(certificateProfile)); + + RequestContext context = FromCancellationToken(cancellationToken); + Response response = await GetSignRootCertificateAsync(accountName, certificateProfile, context).ConfigureAwait(false); + return Response.FromValue(response.Content, response); + } + + /// Gets the signing root certificate on the certificate chain for that account and profile name. + /// Signing account name. + /// Signing Certificate profile name. + /// The cancellation token to use. + /// or is null. + /// or is an empty string, and was expected to be non-empty. + /// The root certificate is generated as part of the initial account creation and it is used to sign the bits for the profile provided. + /// + public virtual Response GetSignRootCertificate(string accountName, string certificateProfile, CancellationToken cancellationToken = default) + { + Argument.AssertNotNullOrEmpty(accountName, nameof(accountName)); + Argument.AssertNotNullOrEmpty(certificateProfile, nameof(certificateProfile)); + + RequestContext context = FromCancellationToken(cancellationToken); + Response response = GetSignRootCertificate(accountName, certificateProfile, context); + return Response.FromValue(response.Content, response); + } + + /// + /// [Protocol Method] Gets the signing root certificate on the certificate chain for that account and profile name. + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// Signing account name. + /// Signing Certificate profile name. + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// or is null. + /// or is an empty string, and was expected to be non-empty. + /// Service returned a non-success status code. + /// The response returned from the service. + /// + public virtual async Task GetSignRootCertificateAsync(string accountName, string certificateProfile, RequestContext context) + { + Argument.AssertNotNullOrEmpty(accountName, nameof(accountName)); + Argument.AssertNotNullOrEmpty(certificateProfile, nameof(certificateProfile)); + + using var scope = ClientDiagnostics.CreateScope("CertificateProfile.GetSignRootCertificate"); + scope.Start(); + try + { + using HttpMessage message = CreateGetSignRootCertificateRequest(accountName, certificateProfile, context); + return await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + /// + /// [Protocol Method] Gets the signing root certificate on the certificate chain for that account and profile name. + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// Signing account name. + /// Signing Certificate profile name. + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// or is null. + /// or is an empty string, and was expected to be non-empty. + /// Service returned a non-success status code. + /// The response returned from the service. + /// + public virtual Response GetSignRootCertificate(string accountName, string certificateProfile, RequestContext context) + { + Argument.AssertNotNullOrEmpty(accountName, nameof(accountName)); + Argument.AssertNotNullOrEmpty(certificateProfile, nameof(certificateProfile)); + + using var scope = ClientDiagnostics.CreateScope("CertificateProfile.GetSignRootCertificate"); + scope.Start(); + try + { + using HttpMessage message = CreateGetSignRootCertificateRequest(accountName, certificateProfile, context); + return _pipeline.ProcessMessage(message, context); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + /// Gets a list of extended key usage object identifiers that are allowed for this account and profile combination. + /// Azure Developer Signing account name. + /// Azure Developer Signing certificate profile name under an account. + /// The cancellation token to use. + /// or is null. + /// or is an empty string, and was expected to be non-empty. + /// The list of extended key usages are used to determine the purpose of the certificate usage as part of the signing operation. + /// + public virtual AsyncPageable GetExtendedKeyUsagesAsync(string accountName, string certificateProfile, CancellationToken cancellationToken = default) + { + Argument.AssertNotNullOrEmpty(accountName, nameof(accountName)); + Argument.AssertNotNullOrEmpty(certificateProfile, nameof(certificateProfile)); + + RequestContext context = cancellationToken.CanBeCanceled ? new RequestContext { CancellationToken = cancellationToken } : null; + HttpMessage FirstPageRequest(int? pageSizeHint) => CreateGetExtendedKeyUsagesRequest(accountName, certificateProfile, context); + HttpMessage NextPageRequest(int? pageSizeHint, string nextLink) => CreateGetExtendedKeyUsagesNextPageRequest(nextLink, accountName, certificateProfile, context); + return GeneratorPageableHelpers.CreateAsyncPageable(FirstPageRequest, NextPageRequest, e => ExtendedKeyUsage.DeserializeExtendedKeyUsage(e), ClientDiagnostics, _pipeline, "CertificateProfile.GetExtendedKeyUsages", "value", "nextLink", context); + } + + /// Gets a list of extended key usage object identifiers that are allowed for this account and profile combination. + /// Azure Developer Signing account name. + /// Azure Developer Signing certificate profile name under an account. + /// The cancellation token to use. + /// or is null. + /// or is an empty string, and was expected to be non-empty. + /// The list of extended key usages are used to determine the purpose of the certificate usage as part of the signing operation. + /// + public virtual Pageable GetExtendedKeyUsages(string accountName, string certificateProfile, CancellationToken cancellationToken = default) + { + Argument.AssertNotNullOrEmpty(accountName, nameof(accountName)); + Argument.AssertNotNullOrEmpty(certificateProfile, nameof(certificateProfile)); + + RequestContext context = cancellationToken.CanBeCanceled ? new RequestContext { CancellationToken = cancellationToken } : null; + HttpMessage FirstPageRequest(int? pageSizeHint) => CreateGetExtendedKeyUsagesRequest(accountName, certificateProfile, context); + HttpMessage NextPageRequest(int? pageSizeHint, string nextLink) => CreateGetExtendedKeyUsagesNextPageRequest(nextLink, accountName, certificateProfile, context); + return GeneratorPageableHelpers.CreatePageable(FirstPageRequest, NextPageRequest, e => ExtendedKeyUsage.DeserializeExtendedKeyUsage(e), ClientDiagnostics, _pipeline, "CertificateProfile.GetExtendedKeyUsages", "value", "nextLink", context); + } + + /// + /// [Protocol Method] Gets a list of extended key usage object identifiers that are allowed for this account and profile combination. + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// Azure Developer Signing account name. + /// Azure Developer Signing certificate profile name under an account. + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// or is null. + /// or is an empty string, and was expected to be non-empty. + /// Service returned a non-success status code. + /// The from the service containing a list of objects. Details of the body schema for each item in the collection are in the Remarks section below. + /// + public virtual AsyncPageable GetExtendedKeyUsagesAsync(string accountName, string certificateProfile, RequestContext context) + { + Argument.AssertNotNullOrEmpty(accountName, nameof(accountName)); + Argument.AssertNotNullOrEmpty(certificateProfile, nameof(certificateProfile)); + + HttpMessage FirstPageRequest(int? pageSizeHint) => CreateGetExtendedKeyUsagesRequest(accountName, certificateProfile, context); + HttpMessage NextPageRequest(int? pageSizeHint, string nextLink) => CreateGetExtendedKeyUsagesNextPageRequest(nextLink, accountName, certificateProfile, context); + return GeneratorPageableHelpers.CreateAsyncPageable(FirstPageRequest, NextPageRequest, e => BinaryData.FromString(e.GetRawText()), ClientDiagnostics, _pipeline, "CertificateProfile.GetExtendedKeyUsages", "value", "nextLink", context); + } + + /// + /// [Protocol Method] Gets a list of extended key usage object identifiers that are allowed for this account and profile combination. + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// Azure Developer Signing account name. + /// Azure Developer Signing certificate profile name under an account. + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// or is null. + /// or is an empty string, and was expected to be non-empty. + /// Service returned a non-success status code. + /// The from the service containing a list of objects. Details of the body schema for each item in the collection are in the Remarks section below. + /// + public virtual Pageable GetExtendedKeyUsages(string accountName, string certificateProfile, RequestContext context) + { + Argument.AssertNotNullOrEmpty(accountName, nameof(accountName)); + Argument.AssertNotNullOrEmpty(certificateProfile, nameof(certificateProfile)); + + HttpMessage FirstPageRequest(int? pageSizeHint) => CreateGetExtendedKeyUsagesRequest(accountName, certificateProfile, context); + HttpMessage NextPageRequest(int? pageSizeHint, string nextLink) => CreateGetExtendedKeyUsagesNextPageRequest(nextLink, accountName, certificateProfile, context); + return GeneratorPageableHelpers.CreatePageable(FirstPageRequest, NextPageRequest, e => BinaryData.FromString(e.GetRawText()), ClientDiagnostics, _pipeline, "CertificateProfile.GetExtendedKeyUsages", "value", "nextLink", context); + } + + /// Submit a sign operation. + /// if the method should wait to return until the long-running operation has completed on the service; if it should return after starting the operation. For more information on long-running operations, please see Azure.Core Long-Running Operation samples. + /// Azure Developer Signing account name. + /// Azure Developer Signing certificate profile name under an account. + /// The supported signature algorithm identifiers. + /// Content digest to sign. + /// List of full file digital signatures. + /// List of authenticode digital signatures. + /// An optional client version. + /// An identifier used to batch multiple requests. + /// The cancellation token to use. + /// , or is null. + /// or is an empty string, and was expected to be non-empty. + /// Submit a sign operation under the created account and profile name provided. + /// + public virtual async Task> SignAsync(WaitUntil waitUntil, string accountName, string certificateProfile, SignatureAlgorithm signatureAlgorithm, BinaryData digest, IEnumerable fileHashList = null, IEnumerable authenticodeHashList = null, string clientVersion = null, string xCorrelationId = null, CancellationToken cancellationToken = default) + { + Argument.AssertNotNullOrEmpty(accountName, nameof(accountName)); + Argument.AssertNotNullOrEmpty(certificateProfile, nameof(certificateProfile)); + Argument.AssertNotNull(digest, nameof(digest)); + + SigningPayloadOptions signingPayloadOptions = new SigningPayloadOptions(signatureAlgorithm, digest, fileHashList?.ToList() as IList ?? new ChangeTrackingList(), authenticodeHashList?.ToList() as IList ?? new ChangeTrackingList(), null); + RequestContext context = FromCancellationToken(cancellationToken); + Operation response = await SignAsync(waitUntil, accountName, certificateProfile, signingPayloadOptions.ToRequestContent(), clientVersion, xCorrelationId, context).ConfigureAwait(false); + return ProtocolOperationHelpers.Convert(response, FetchSignResultFromOperationStatusSignResultError, ClientDiagnostics, "CertificateProfile.Sign"); + } + + /// Submit a sign operation. + /// if the method should wait to return until the long-running operation has completed on the service; if it should return after starting the operation. For more information on long-running operations, please see Azure.Core Long-Running Operation samples. + /// Azure Developer Signing account name. + /// Azure Developer Signing certificate profile name under an account. + /// The supported signature algorithm identifiers. + /// Content digest to sign. + /// List of full file digital signatures. + /// List of authenticode digital signatures. + /// An optional client version. + /// An identifier used to batch multiple requests. + /// The cancellation token to use. + /// , or is null. + /// or is an empty string, and was expected to be non-empty. + /// Submit a sign operation under the created account and profile name provided. + /// + public virtual Operation Sign(WaitUntil waitUntil, string accountName, string certificateProfile, SignatureAlgorithm signatureAlgorithm, BinaryData digest, IEnumerable fileHashList = null, IEnumerable authenticodeHashList = null, string clientVersion = null, string xCorrelationId = null, CancellationToken cancellationToken = default) + { + Argument.AssertNotNullOrEmpty(accountName, nameof(accountName)); + Argument.AssertNotNullOrEmpty(certificateProfile, nameof(certificateProfile)); + Argument.AssertNotNull(digest, nameof(digest)); + + SigningPayloadOptions signingPayloadOptions = new SigningPayloadOptions(signatureAlgorithm, digest, fileHashList?.ToList() as IList ?? new ChangeTrackingList(), authenticodeHashList?.ToList() as IList ?? new ChangeTrackingList(), null); + RequestContext context = FromCancellationToken(cancellationToken); + Operation response = Sign(waitUntil, accountName, certificateProfile, signingPayloadOptions.ToRequestContent(), clientVersion, xCorrelationId, context); + return ProtocolOperationHelpers.Convert(response, FetchSignResultFromOperationStatusSignResultError, ClientDiagnostics, "CertificateProfile.Sign"); + } + + /// + /// [Protocol Method] Submit a sign operation. + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// if the method should wait to return until the long-running operation has completed on the service; if it should return after starting the operation. For more information on long-running operations, please see Azure.Core Long-Running Operation samples. + /// Azure Developer Signing account name. + /// Azure Developer Signing certificate profile name under an account. + /// The content to send as the body of the request. + /// An optional client version. + /// An identifier used to batch multiple requests. + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// , or is null. + /// or is an empty string, and was expected to be non-empty. + /// Service returned a non-success status code. + /// The representing an asynchronous operation on the service. + /// + public virtual async Task> SignAsync(WaitUntil waitUntil, string accountName, string certificateProfile, RequestContent content, string clientVersion = null, string xCorrelationId = null, RequestContext context = null) + { + Argument.AssertNotNullOrEmpty(accountName, nameof(accountName)); + Argument.AssertNotNullOrEmpty(certificateProfile, nameof(certificateProfile)); + Argument.AssertNotNull(content, nameof(content)); + + using var scope = ClientDiagnostics.CreateScope("CertificateProfile.Sign"); + scope.Start(); + try + { + using HttpMessage message = CreateSignRequest(accountName, certificateProfile, content, clientVersion, xCorrelationId, context); + return await ProtocolOperationHelpers.ProcessMessageAsync(_pipeline, message, ClientDiagnostics, "CertificateProfile.Sign", OperationFinalStateVia.OperationLocation, context, waitUntil).ConfigureAwait(false); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + /// + /// [Protocol Method] Submit a sign operation. + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// if the method should wait to return until the long-running operation has completed on the service; if it should return after starting the operation. For more information on long-running operations, please see Azure.Core Long-Running Operation samples. + /// Azure Developer Signing account name. + /// Azure Developer Signing certificate profile name under an account. + /// The content to send as the body of the request. + /// An optional client version. + /// An identifier used to batch multiple requests. + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// , or is null. + /// or is an empty string, and was expected to be non-empty. + /// Service returned a non-success status code. + /// The representing an asynchronous operation on the service. + /// + public virtual Operation Sign(WaitUntil waitUntil, string accountName, string certificateProfile, RequestContent content, string clientVersion = null, string xCorrelationId = null, RequestContext context = null) + { + Argument.AssertNotNullOrEmpty(accountName, nameof(accountName)); + Argument.AssertNotNullOrEmpty(certificateProfile, nameof(certificateProfile)); + Argument.AssertNotNull(content, nameof(content)); + + using var scope = ClientDiagnostics.CreateScope("CertificateProfile.Sign"); + scope.Start(); + try + { + using HttpMessage message = CreateSignRequest(accountName, certificateProfile, content, clientVersion, xCorrelationId, context); + return ProtocolOperationHelpers.ProcessMessage(_pipeline, message, ClientDiagnostics, "CertificateProfile.Sign", OperationFinalStateVia.OperationLocation, context, waitUntil); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + internal HttpMessage CreateGetSigningStatusRequest(string accountName, string certificateProfile, string operationId, RequestContext context) + { + var message = _pipeline.CreateMessage(context, ResponseClassifier200); + var request = message.Request; + request.Method = RequestMethod.Get; + var uri = new RawRequestUriBuilder(); + uri.AppendRaw("https://", false); + uri.AppendRaw(_region, true); + uri.AppendRaw(".codesigning.azure.net/", false); + uri.AppendPath("/codesigningaccounts/", false); + uri.AppendPath(accountName, true); + uri.AppendPath("/certificateprofiles/", false); + uri.AppendPath(certificateProfile, true); + uri.AppendPath("/sign/", false); + uri.AppendPath(operationId, true); + uri.AppendQuery("api-version", _apiVersion, true); + request.Uri = uri; + request.Headers.Add("Accept", "application/json"); + return message; + } + + internal HttpMessage CreateGetSignRootCertificateRequest(string accountName, string certificateProfile, RequestContext context) + { + var message = _pipeline.CreateMessage(context, ResponseClassifier200); + var request = message.Request; + request.Method = RequestMethod.Get; + var uri = new RawRequestUriBuilder(); + uri.AppendRaw("https://", false); + uri.AppendRaw(_region, true); + uri.AppendRaw(".codesigning.azure.net/", false); + uri.AppendPath("/codesigningaccounts/", false); + uri.AppendPath(accountName, true); + uri.AppendPath("/certificateprofiles/", false); + uri.AppendPath(certificateProfile, true); + uri.AppendPath("/sign/rootcert", false); + uri.AppendQuery("api-version", _apiVersion, true); + request.Uri = uri; + request.Headers.Add("Accept", "application/x-x509-ca-cert"); + return message; + } + + internal HttpMessage CreateGetExtendedKeyUsagesRequest(string accountName, string certificateProfile, RequestContext context) + { + var message = _pipeline.CreateMessage(context, ResponseClassifier200); + var request = message.Request; + request.Method = RequestMethod.Get; + var uri = new RawRequestUriBuilder(); + uri.AppendRaw("https://", false); + uri.AppendRaw(_region, true); + uri.AppendRaw(".codesigning.azure.net/", false); + uri.AppendPath("/codesigningaccounts/", false); + uri.AppendPath(accountName, true); + uri.AppendPath("/certificateprofiles/", false); + uri.AppendPath(certificateProfile, true); + uri.AppendPath("/sign/eku", false); + uri.AppendQuery("api-version", _apiVersion, true); + request.Uri = uri; + request.Headers.Add("Accept", "application/json"); + return message; + } + + internal HttpMessage CreateSignRequest(string accountName, string certificateProfile, RequestContent content, string clientVersion, string xCorrelationId, RequestContext context) + { + var message = _pipeline.CreateMessage(context, ResponseClassifier202); + var request = message.Request; + request.Method = RequestMethod.Post; + var uri = new RawRequestUriBuilder(); + uri.AppendRaw("https://", false); + uri.AppendRaw(_region, true); + uri.AppendRaw(".codesigning.azure.net/", false); + uri.AppendPath("/codesigningaccounts/", false); + uri.AppendPath(accountName, true); + uri.AppendPath("/certificateprofiles/", false); + uri.AppendPath(certificateProfile, true); + uri.AppendPath(":sign", false); + uri.AppendQuery("api-version", _apiVersion, true); + request.Uri = uri; + request.Headers.Add("Accept", "application/json"); + if (clientVersion != null) + { + request.Headers.Add("client-version", clientVersion); + } + if (xCorrelationId != null) + { + request.Headers.Add("x-correlation-id", xCorrelationId); + } + request.Headers.Add("Content-Type", "application/json"); + request.Content = content; + return message; + } + + internal HttpMessage CreateGetExtendedKeyUsagesNextPageRequest(string nextLink, string accountName, string certificateProfile, RequestContext context) + { + var message = _pipeline.CreateMessage(context, ResponseClassifier200); + var request = message.Request; + request.Method = RequestMethod.Get; + var uri = new RawRequestUriBuilder(); + uri.AppendRaw("https://", false); + uri.AppendRaw(_region, true); + uri.AppendRaw(".codesigning.azure.net/", false); + uri.AppendRawNextLink(nextLink, false); + request.Uri = uri; + request.Headers.Add("Accept", "application/json"); + return message; + } + + private static RequestContext DefaultRequestContext = new RequestContext(); + internal static RequestContext FromCancellationToken(CancellationToken cancellationToken = default) + { + if (!cancellationToken.CanBeCanceled) + { + return DefaultRequestContext; + } + + return new RequestContext() { CancellationToken = cancellationToken }; + } + + private static ResponseClassifier _responseClassifier200; + private static ResponseClassifier ResponseClassifier200 => _responseClassifier200 ??= new StatusCodeClassifier(stackalloc ushort[] { 200 }); + private static ResponseClassifier _responseClassifier202; + private static ResponseClassifier ResponseClassifier202 => _responseClassifier202 ??= new StatusCodeClassifier(stackalloc ushort[] { 202 }); + + private SignResult FetchSignResultFromOperationStatusSignResultError(Response response) + { + var resultJsonElement = JsonDocument.Parse(response.Content).RootElement.GetProperty("result"); + return SignResult.DeserializeSignResult(resultJsonElement); + } + } +} diff --git a/sdk/trustedsigning/Azure.Developer.Signing/src/Generated/DeveloperSigningClientBuilderExtensions.cs b/sdk/trustedsigning/Azure.Developer.Signing/src/Generated/DeveloperSigningClientBuilderExtensions.cs new file mode 100644 index 000000000000..65cde707bc2a --- /dev/null +++ b/sdk/trustedsigning/Azure.Developer.Signing/src/Generated/DeveloperSigningClientBuilderExtensions.cs @@ -0,0 +1,34 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using Azure.Core.Extensions; +using Azure.Developer.Signing; + +namespace Microsoft.Extensions.Azure +{ + /// Extension methods to add to client builder. + public static partial class DeveloperSigningClientBuilderExtensions + { + /// Registers a instance. + /// The builder to register with. + /// The Azure region wherein requests for signing will be sent. + public static IAzureClientBuilder AddSigningClient(this TBuilder builder, string region) + where TBuilder : IAzureClientFactoryBuilderWithCredential + { + return builder.RegisterClientFactory((options, cred) => new SigningClient(region, cred, options)); + } + + /// Registers a instance. + /// The builder to register with. + /// The configuration values. + public static IAzureClientBuilder AddSigningClient(this TBuilder builder, TConfiguration configuration) + where TBuilder : IAzureClientFactoryBuilderWithConfiguration + { + return builder.RegisterClientFactory(configuration); + } + } +} diff --git a/sdk/trustedsigning/Azure.Developer.Signing/src/Generated/DeveloperSigningModelFactory.cs b/sdk/trustedsigning/Azure.Developer.Signing/src/Generated/DeveloperSigningModelFactory.cs new file mode 100644 index 000000000000..206904f76f5c --- /dev/null +++ b/sdk/trustedsigning/Azure.Developer.Signing/src/Generated/DeveloperSigningModelFactory.cs @@ -0,0 +1,48 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Azure.Developer.Signing +{ + /// Model factory for models. + public static partial class DeveloperSigningModelFactory + { + /// Initializes a new instance of . + /// The unique ID of the operation. + /// The status of the operation. + /// Error object that describes the error when status is "Failed". + /// The result of the operation. + /// A new instance for mocking. + public static OperationStatusSignResultError OperationStatusSignResultError(string id = null, OperationState status = default, ResponseError error = null, SignResult result = null) + { + return new OperationStatusSignResultError(id, status, error, result, serializedAdditionalRawData: null); + } + + /// Initializes a new instance of . + /// Digital signature of the requested content digest. + /// + /// Signing certificate corresponding to the private key used to sign the requested + /// digest. + /// + /// A new instance for mocking. + public static SignResult SignResult(BinaryData signature = null, BinaryData signingCertificate = null) + { + return new SignResult(signature, signingCertificate, serializedAdditionalRawData: null); + } + + /// Initializes a new instance of . + /// An oid string that represents an eku. + /// A new instance for mocking. + public static ExtendedKeyUsage ExtendedKeyUsage(string eku = null) + { + return new ExtendedKeyUsage(eku, serializedAdditionalRawData: null); + } + } +} diff --git a/sdk/trustedsigning/Azure.Developer.Signing/src/Generated/Docs/CertificateProfile.xml b/sdk/trustedsigning/Azure.Developer.Signing/src/Generated/Docs/CertificateProfile.xml new file mode 100644 index 000000000000..984c681412cb --- /dev/null +++ b/sdk/trustedsigning/Azure.Developer.Signing/src/Generated/Docs/CertificateProfile.xml @@ -0,0 +1,411 @@ + + + + + +This sample shows how to call GetSigningStatusAsync. +", credential).GetCertificateProfileClient(apiVersion: "2023-06-15-preview"); + +Response response = await client.GetSigningStatusAsync("", "", ""); +]]> +This sample shows how to call GetSigningStatusAsync with all parameters. +", credential).GetCertificateProfileClient(apiVersion: "2023-06-15-preview"); + +Response response = await client.GetSigningStatusAsync("", "", ""); +]]> + + + +This sample shows how to call GetSigningStatus. +", credential).GetCertificateProfileClient(apiVersion: "2023-06-15-preview"); + +Response response = client.GetSigningStatus("", "", ""); +]]> +This sample shows how to call GetSigningStatus with all parameters. +", credential).GetCertificateProfileClient(apiVersion: "2023-06-15-preview"); + +Response response = client.GetSigningStatus("", "", ""); +]]> + + + +This sample shows how to call GetSigningStatusAsync and parse the result. +", credential).GetCertificateProfileClient(apiVersion: "2023-06-15-preview"); + +Response response = await client.GetSigningStatusAsync("", "", "", null); + +JsonElement result = JsonDocument.Parse(response.ContentStream).RootElement; +Console.WriteLine(result.GetProperty("id").ToString()); +Console.WriteLine(result.GetProperty("status").ToString()); +]]> +This sample shows how to call GetSigningStatusAsync with all parameters and parse the result. +", credential).GetCertificateProfileClient(apiVersion: "2023-06-15-preview"); + +Response response = await client.GetSigningStatusAsync("", "", "", null); + +JsonElement result = JsonDocument.Parse(response.ContentStream).RootElement; +Console.WriteLine(result.GetProperty("id").ToString()); +Console.WriteLine(result.GetProperty("status").ToString()); +Console.WriteLine(result.GetProperty("error").GetProperty("code").ToString()); +Console.WriteLine(result.GetProperty("error").GetProperty("message").ToString()); +Console.WriteLine(result.GetProperty("error").GetProperty("target").ToString()); +Console.WriteLine(result.GetProperty("error").GetProperty("innererror").GetProperty("code").ToString()); +Console.WriteLine(result.GetProperty("result").GetProperty("signature").ToString()); +Console.WriteLine(result.GetProperty("result").GetProperty("signingCertificate").ToString()); +]]> + + + +This sample shows how to call GetSigningStatus and parse the result. +", credential).GetCertificateProfileClient(apiVersion: "2023-06-15-preview"); + +Response response = client.GetSigningStatus("", "", "", null); + +JsonElement result = JsonDocument.Parse(response.ContentStream).RootElement; +Console.WriteLine(result.GetProperty("id").ToString()); +Console.WriteLine(result.GetProperty("status").ToString()); +]]> +This sample shows how to call GetSigningStatus with all parameters and parse the result. +", credential).GetCertificateProfileClient(apiVersion: "2023-06-15-preview"); + +Response response = client.GetSigningStatus("", "", "", null); + +JsonElement result = JsonDocument.Parse(response.ContentStream).RootElement; +Console.WriteLine(result.GetProperty("id").ToString()); +Console.WriteLine(result.GetProperty("status").ToString()); +Console.WriteLine(result.GetProperty("error").GetProperty("code").ToString()); +Console.WriteLine(result.GetProperty("error").GetProperty("message").ToString()); +Console.WriteLine(result.GetProperty("error").GetProperty("target").ToString()); +Console.WriteLine(result.GetProperty("error").GetProperty("innererror").GetProperty("code").ToString()); +Console.WriteLine(result.GetProperty("result").GetProperty("signature").ToString()); +Console.WriteLine(result.GetProperty("result").GetProperty("signingCertificate").ToString()); +]]> + + + +This sample shows how to call GetSignRootCertificateAsync. +", credential).GetCertificateProfileClient(apiVersion: "2023-06-15-preview"); + +Response response = await client.GetSignRootCertificateAsync("", ""); +]]> +This sample shows how to call GetSignRootCertificateAsync with all parameters. +", credential).GetCertificateProfileClient(apiVersion: "2023-06-15-preview"); + +Response response = await client.GetSignRootCertificateAsync("", ""); +]]> + + + +This sample shows how to call GetSignRootCertificate. +", credential).GetCertificateProfileClient(apiVersion: "2023-06-15-preview"); + +Response response = client.GetSignRootCertificate("", ""); +]]> +This sample shows how to call GetSignRootCertificate with all parameters. +", credential).GetCertificateProfileClient(apiVersion: "2023-06-15-preview"); + +Response response = client.GetSignRootCertificate("", ""); +]]> + + + +This sample shows how to call GetSignRootCertificateAsync and parse the result. +", credential).GetCertificateProfileClient(apiVersion: "2023-06-15-preview"); + +Response response = await client.GetSignRootCertificateAsync("", "", null); + +JsonElement result = JsonDocument.Parse(response.ContentStream).RootElement; +Console.WriteLine(result.ToString()); +]]> +This sample shows how to call GetSignRootCertificateAsync with all parameters and parse the result. +", credential).GetCertificateProfileClient(apiVersion: "2023-06-15-preview"); + +Response response = await client.GetSignRootCertificateAsync("", "", null); + +JsonElement result = JsonDocument.Parse(response.ContentStream).RootElement; +Console.WriteLine(result.ToString()); +]]> + + + +This sample shows how to call GetSignRootCertificate and parse the result. +", credential).GetCertificateProfileClient(apiVersion: "2023-06-15-preview"); + +Response response = client.GetSignRootCertificate("", "", null); + +JsonElement result = JsonDocument.Parse(response.ContentStream).RootElement; +Console.WriteLine(result.ToString()); +]]> +This sample shows how to call GetSignRootCertificate with all parameters and parse the result. +", credential).GetCertificateProfileClient(apiVersion: "2023-06-15-preview"); + +Response response = client.GetSignRootCertificate("", "", null); + +JsonElement result = JsonDocument.Parse(response.ContentStream).RootElement; +Console.WriteLine(result.ToString()); +]]> + + + +This sample shows how to call GetExtendedKeyUsagesAsync. +", credential).GetCertificateProfileClient(apiVersion: "2023-06-15-preview"); + +await foreach (ExtendedKeyUsage item in client.GetExtendedKeyUsagesAsync("", "")) +{ +} +]]> +This sample shows how to call GetExtendedKeyUsagesAsync with all parameters. +", credential).GetCertificateProfileClient(apiVersion: "2023-06-15-preview"); + +await foreach (ExtendedKeyUsage item in client.GetExtendedKeyUsagesAsync("", "")) +{ +} +]]> + + + +This sample shows how to call GetExtendedKeyUsages. +", credential).GetCertificateProfileClient(apiVersion: "2023-06-15-preview"); + +foreach (ExtendedKeyUsage item in client.GetExtendedKeyUsages("", "")) +{ +} +]]> +This sample shows how to call GetExtendedKeyUsages with all parameters. +", credential).GetCertificateProfileClient(apiVersion: "2023-06-15-preview"); + +foreach (ExtendedKeyUsage item in client.GetExtendedKeyUsages("", "")) +{ +} +]]> + + + +This sample shows how to call GetExtendedKeyUsagesAsync and parse the result. +", credential).GetCertificateProfileClient(apiVersion: "2023-06-15-preview"); + +await foreach (BinaryData item in client.GetExtendedKeyUsagesAsync("", "", null)) +{ + JsonElement result = JsonDocument.Parse(item.ToStream()).RootElement; + Console.WriteLine(result.GetProperty("eku").ToString()); +} +]]> +This sample shows how to call GetExtendedKeyUsagesAsync with all parameters and parse the result. +", credential).GetCertificateProfileClient(apiVersion: "2023-06-15-preview"); + +await foreach (BinaryData item in client.GetExtendedKeyUsagesAsync("", "", null)) +{ + JsonElement result = JsonDocument.Parse(item.ToStream()).RootElement; + Console.WriteLine(result.GetProperty("eku").ToString()); +} +]]> + + + +This sample shows how to call GetExtendedKeyUsages and parse the result. +", credential).GetCertificateProfileClient(apiVersion: "2023-06-15-preview"); + +foreach (BinaryData item in client.GetExtendedKeyUsages("", "", null)) +{ + JsonElement result = JsonDocument.Parse(item.ToStream()).RootElement; + Console.WriteLine(result.GetProperty("eku").ToString()); +} +]]> +This sample shows how to call GetExtendedKeyUsages with all parameters and parse the result. +", credential).GetCertificateProfileClient(apiVersion: "2023-06-15-preview"); + +foreach (BinaryData item in client.GetExtendedKeyUsages("", "", null)) +{ + JsonElement result = JsonDocument.Parse(item.ToStream()).RootElement; + Console.WriteLine(result.GetProperty("eku").ToString()); +} +]]> + + + +This sample shows how to call SignAsync. +", credential).GetCertificateProfileClient(apiVersion: "2023-06-15-preview"); + +Operation operation = await client.SignAsync(WaitUntil.Completed, "", "", SignatureAlgorithm.RS256, BinaryData.FromObjectAsJson(new object())); +SignResult responseData = operation.Value; +]]> +This sample shows how to call SignAsync with all parameters. +", credential).GetCertificateProfileClient(apiVersion: "2023-06-15-preview"); + +Operation operation = await client.SignAsync(WaitUntil.Completed, "", "", SignatureAlgorithm.RS256, BinaryData.FromObjectAsJson(new object()), fileHashList: new BinaryData[] +{ + BinaryData.FromObjectAsJson(new object()) +}, authenticodeHashList: new BinaryData[] +{ + BinaryData.FromObjectAsJson(new object()) +}, clientVersion: "", xCorrelationId: ""); +SignResult responseData = operation.Value; +]]> + + + +This sample shows how to call Sign. +", credential).GetCertificateProfileClient(apiVersion: "2023-06-15-preview"); + +Operation operation = client.Sign(WaitUntil.Completed, "", "", SignatureAlgorithm.RS256, BinaryData.FromObjectAsJson(new object())); +SignResult responseData = operation.Value; +]]> +This sample shows how to call Sign with all parameters. +", credential).GetCertificateProfileClient(apiVersion: "2023-06-15-preview"); + +Operation operation = client.Sign(WaitUntil.Completed, "", "", SignatureAlgorithm.RS256, BinaryData.FromObjectAsJson(new object()), fileHashList: new BinaryData[] +{ + BinaryData.FromObjectAsJson(new object()) +}, authenticodeHashList: new BinaryData[] +{ + BinaryData.FromObjectAsJson(new object()) +}, clientVersion: "", xCorrelationId: ""); +SignResult responseData = operation.Value; +]]> + + + +This sample shows how to call SignAsync and parse the result. +", credential).GetCertificateProfileClient(apiVersion: "2023-06-15-preview"); + +using RequestContent content = RequestContent.Create(new +{ + signatureAlgorithm = "RS256", + digest = new object(), +}); +Operation operation = await client.SignAsync(WaitUntil.Completed, "", "", content); +BinaryData responseData = operation.Value; + +JsonElement result = JsonDocument.Parse(responseData.ToStream()).RootElement; +Console.WriteLine(result.ToString()); +]]> +This sample shows how to call SignAsync with all parameters and request content and parse the result. +", credential).GetCertificateProfileClient(apiVersion: "2023-06-15-preview"); + +using RequestContent content = RequestContent.Create(new +{ + signatureAlgorithm = "RS256", + digest = new object(), + fileHashList = new object[] + { + new object() + }, + authenticodeHashList = new object[] + { + new object() + }, +}); +Operation operation = await client.SignAsync(WaitUntil.Completed, "", "", content, clientVersion: "", xCorrelationId: ""); +BinaryData responseData = operation.Value; + +JsonElement result = JsonDocument.Parse(responseData.ToStream()).RootElement; +Console.WriteLine(result.GetProperty("signature").ToString()); +Console.WriteLine(result.GetProperty("signingCertificate").ToString()); +]]> + + + +This sample shows how to call Sign and parse the result. +", credential).GetCertificateProfileClient(apiVersion: "2023-06-15-preview"); + +using RequestContent content = RequestContent.Create(new +{ + signatureAlgorithm = "RS256", + digest = new object(), +}); +Operation operation = client.Sign(WaitUntil.Completed, "", "", content); +BinaryData responseData = operation.Value; + +JsonElement result = JsonDocument.Parse(responseData.ToStream()).RootElement; +Console.WriteLine(result.ToString()); +]]> +This sample shows how to call Sign with all parameters and request content and parse the result. +", credential).GetCertificateProfileClient(apiVersion: "2023-06-15-preview"); + +using RequestContent content = RequestContent.Create(new +{ + signatureAlgorithm = "RS256", + digest = new object(), + fileHashList = new object[] + { + new object() + }, + authenticodeHashList = new object[] + { + new object() + }, +}); +Operation operation = client.Sign(WaitUntil.Completed, "", "", content, clientVersion: "", xCorrelationId: ""); +BinaryData responseData = operation.Value; + +JsonElement result = JsonDocument.Parse(responseData.ToStream()).RootElement; +Console.WriteLine(result.GetProperty("signature").ToString()); +Console.WriteLine(result.GetProperty("signingCertificate").ToString()); +]]> + + + \ No newline at end of file diff --git a/sdk/trustedsigning/Azure.Developer.Signing/src/Generated/ExtendedKeyUsage.Serialization.cs b/sdk/trustedsigning/Azure.Developer.Signing/src/Generated/ExtendedKeyUsage.Serialization.cs new file mode 100644 index 000000000000..4aefe1f4275b --- /dev/null +++ b/sdk/trustedsigning/Azure.Developer.Signing/src/Generated/ExtendedKeyUsage.Serialization.cs @@ -0,0 +1,138 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; +using Azure.Core; + +namespace Azure.Developer.Signing +{ + public partial class ExtendedKeyUsage : IUtf8JsonSerializable, IJsonModel + { + void IUtf8JsonSerializable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, ModelSerializationExtensions.WireOptions); + + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(ExtendedKeyUsage)} does not support writing '{format}' format."); + } + + writer.WriteStartObject(); + if (options.Format != "W") + { + writer.WritePropertyName("eku"u8); + writer.WriteStringValue(Eku); + } + if (options.Format != "W" && _serializedAdditionalRawData != null) + { + foreach (var item in _serializedAdditionalRawData) + { + writer.WritePropertyName(item.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(item.Value); +#else + using (JsonDocument document = JsonDocument.Parse(item.Value)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + } + writer.WriteEndObject(); + } + + ExtendedKeyUsage IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(ExtendedKeyUsage)} does not support reading '{format}' format."); + } + + using JsonDocument document = JsonDocument.ParseValue(ref reader); + return DeserializeExtendedKeyUsage(document.RootElement, options); + } + + internal static ExtendedKeyUsage DeserializeExtendedKeyUsage(JsonElement element, ModelReaderWriterOptions options = null) + { + options ??= ModelSerializationExtensions.WireOptions; + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + string eku = default; + IDictionary serializedAdditionalRawData = default; + Dictionary rawDataDictionary = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("eku"u8)) + { + eku = property.Value.GetString(); + continue; + } + if (options.Format != "W") + { + rawDataDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + serializedAdditionalRawData = rawDataDictionary; + return new ExtendedKeyUsage(eku, serializedAdditionalRawData); + } + + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + return ModelReaderWriter.Write(this, options); + default: + throw new FormatException($"The model {nameof(ExtendedKeyUsage)} does not support writing '{options.Format}' format."); + } + } + + ExtendedKeyUsage IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + { + using JsonDocument document = JsonDocument.Parse(data); + return DeserializeExtendedKeyUsage(document.RootElement, options); + } + default: + throw new FormatException($"The model {nameof(ExtendedKeyUsage)} does not support reading '{options.Format}' format."); + } + } + + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + + /// Deserializes the model from a raw response. + /// The response to deserialize the model from. + internal static ExtendedKeyUsage FromResponse(Response response) + { + using var document = JsonDocument.Parse(response.Content); + return DeserializeExtendedKeyUsage(document.RootElement); + } + + /// Convert into a . + internal virtual RequestContent ToRequestContent() + { + var content = new Utf8JsonRequestContent(); + content.JsonWriter.WriteObjectValue(this, ModelSerializationExtensions.WireOptions); + return content; + } + } +} diff --git a/sdk/trustedsigning/Azure.Developer.Signing/src/Generated/ExtendedKeyUsage.cs b/sdk/trustedsigning/Azure.Developer.Signing/src/Generated/ExtendedKeyUsage.cs new file mode 100644 index 000000000000..cbc89d55afcd --- /dev/null +++ b/sdk/trustedsigning/Azure.Developer.Signing/src/Generated/ExtendedKeyUsage.cs @@ -0,0 +1,65 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System; +using System.Collections.Generic; + +namespace Azure.Developer.Signing +{ + /// Extended key usage object identifier that are allowable. + public partial class ExtendedKeyUsage + { + /// + /// Keeps track of any properties unknown to the library. + /// + /// To assign an object to the value of this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + private IDictionary _serializedAdditionalRawData; + + /// Initializes a new instance of . + internal ExtendedKeyUsage() + { + } + + /// Initializes a new instance of . + /// An oid string that represents an eku. + /// Keeps track of any properties unknown to the library. + internal ExtendedKeyUsage(string eku, IDictionary serializedAdditionalRawData) + { + Eku = eku; + _serializedAdditionalRawData = serializedAdditionalRawData; + } + + /// An oid string that represents an eku. + public string Eku { get; } + } +} diff --git a/sdk/trustedsigning/Azure.Developer.Signing/src/Generated/Internal/Argument.cs b/sdk/trustedsigning/Azure.Developer.Signing/src/Generated/Internal/Argument.cs new file mode 100644 index 000000000000..b366d8db1f7d --- /dev/null +++ b/sdk/trustedsigning/Azure.Developer.Signing/src/Generated/Internal/Argument.cs @@ -0,0 +1,129 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System; +using System.Collections; +using System.Collections.Generic; + +namespace Azure.Developer.Signing +{ + internal static class Argument + { + public static void AssertNotNull(T value, string name) + { + if (value is null) + { + throw new ArgumentNullException(name); + } + } + + public static void AssertNotNull(T? value, string name) + where T : struct + { + if (!value.HasValue) + { + throw new ArgumentNullException(name); + } + } + + public static void AssertNotNullOrEmpty(IEnumerable value, string name) + { + if (value is null) + { + throw new ArgumentNullException(name); + } + if (value is ICollection collectionOfT && collectionOfT.Count == 0) + { + throw new ArgumentException("Value cannot be an empty collection.", name); + } + if (value is ICollection collection && collection.Count == 0) + { + throw new ArgumentException("Value cannot be an empty collection.", name); + } + using IEnumerator e = value.GetEnumerator(); + if (!e.MoveNext()) + { + throw new ArgumentException("Value cannot be an empty collection.", name); + } + } + + public static void AssertNotNullOrEmpty(string value, string name) + { + if (value is null) + { + throw new ArgumentNullException(name); + } + if (value.Length == 0) + { + throw new ArgumentException("Value cannot be an empty string.", name); + } + } + + public static void AssertNotNullOrWhiteSpace(string value, string name) + { + if (value is null) + { + throw new ArgumentNullException(name); + } + if (string.IsNullOrWhiteSpace(value)) + { + throw new ArgumentException("Value cannot be empty or contain only white-space characters.", name); + } + } + + public static void AssertNotDefault(ref T value, string name) + where T : struct, IEquatable + { + if (value.Equals(default)) + { + throw new ArgumentException("Value cannot be empty.", name); + } + } + + public static void AssertInRange(T value, T minimum, T maximum, string name) + where T : notnull, IComparable + { + if (minimum.CompareTo(value) > 0) + { + throw new ArgumentOutOfRangeException(name, "Value is less than the minimum allowed."); + } + if (maximum.CompareTo(value) < 0) + { + throw new ArgumentOutOfRangeException(name, "Value is greater than the maximum allowed."); + } + } + + public static void AssertEnumDefined(Type enumType, object value, string name) + { + if (!Enum.IsDefined(enumType, value)) + { + throw new ArgumentException($"Value not defined for {enumType.FullName}.", name); + } + } + + public static T CheckNotNull(T value, string name) + where T : class + { + AssertNotNull(value, name); + return value; + } + + public static string CheckNotNullOrEmpty(string value, string name) + { + AssertNotNullOrEmpty(value, name); + return value; + } + + public static void AssertNull(T value, string name, string message = null) + { + if (value != null) + { + throw new ArgumentException(message ?? "Value must be null.", name); + } + } + } +} diff --git a/sdk/trustedsigning/Azure.Developer.Signing/src/Generated/Internal/ChangeTrackingDictionary.cs b/sdk/trustedsigning/Azure.Developer.Signing/src/Generated/Internal/ChangeTrackingDictionary.cs new file mode 100644 index 000000000000..e78035dcc019 --- /dev/null +++ b/sdk/trustedsigning/Azure.Developer.Signing/src/Generated/Internal/ChangeTrackingDictionary.cs @@ -0,0 +1,167 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System; +using System.Collections; +using System.Collections.Generic; + +namespace Azure.Developer.Signing +{ + internal class ChangeTrackingDictionary : IDictionary, IReadOnlyDictionary where TKey : notnull + { + private IDictionary _innerDictionary; + + public ChangeTrackingDictionary() + { + } + + public ChangeTrackingDictionary(IDictionary dictionary) + { + if (dictionary == null) + { + return; + } + _innerDictionary = new Dictionary(dictionary); + } + + public ChangeTrackingDictionary(IReadOnlyDictionary dictionary) + { + if (dictionary == null) + { + return; + } + _innerDictionary = new Dictionary(); + foreach (var pair in dictionary) + { + _innerDictionary.Add(pair); + } + } + + public bool IsUndefined => _innerDictionary == null; + + public int Count => IsUndefined ? 0 : EnsureDictionary().Count; + + public bool IsReadOnly => IsUndefined ? false : EnsureDictionary().IsReadOnly; + + public ICollection Keys => IsUndefined ? Array.Empty() : EnsureDictionary().Keys; + + public ICollection Values => IsUndefined ? Array.Empty() : EnsureDictionary().Values; + + public TValue this[TKey key] + { + get + { + if (IsUndefined) + { + throw new KeyNotFoundException(nameof(key)); + } + return EnsureDictionary()[key]; + } + set + { + EnsureDictionary()[key] = value; + } + } + + IEnumerable IReadOnlyDictionary.Keys => Keys; + + IEnumerable IReadOnlyDictionary.Values => Values; + + public IEnumerator> GetEnumerator() + { + if (IsUndefined) + { + IEnumerator> enumerateEmpty() + { + yield break; + } + return enumerateEmpty(); + } + return EnsureDictionary().GetEnumerator(); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + + public void Add(KeyValuePair item) + { + EnsureDictionary().Add(item); + } + + public void Clear() + { + EnsureDictionary().Clear(); + } + + public bool Contains(KeyValuePair item) + { + if (IsUndefined) + { + return false; + } + return EnsureDictionary().Contains(item); + } + + public void CopyTo(KeyValuePair[] array, int index) + { + if (IsUndefined) + { + return; + } + EnsureDictionary().CopyTo(array, index); + } + + public bool Remove(KeyValuePair item) + { + if (IsUndefined) + { + return false; + } + return EnsureDictionary().Remove(item); + } + + public void Add(TKey key, TValue value) + { + EnsureDictionary().Add(key, value); + } + + public bool ContainsKey(TKey key) + { + if (IsUndefined) + { + return false; + } + return EnsureDictionary().ContainsKey(key); + } + + public bool Remove(TKey key) + { + if (IsUndefined) + { + return false; + } + return EnsureDictionary().Remove(key); + } + + public bool TryGetValue(TKey key, out TValue value) + { + if (IsUndefined) + { + value = default; + return false; + } + return EnsureDictionary().TryGetValue(key, out value); + } + + public IDictionary EnsureDictionary() + { + return _innerDictionary ??= new Dictionary(); + } + } +} diff --git a/sdk/trustedsigning/Azure.Developer.Signing/src/Generated/Internal/ChangeTrackingList.cs b/sdk/trustedsigning/Azure.Developer.Signing/src/Generated/Internal/ChangeTrackingList.cs new file mode 100644 index 000000000000..a7156c01324a --- /dev/null +++ b/sdk/trustedsigning/Azure.Developer.Signing/src/Generated/Internal/ChangeTrackingList.cs @@ -0,0 +1,153 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; + +namespace Azure.Developer.Signing +{ + internal class ChangeTrackingList : IList, IReadOnlyList + { + private IList _innerList; + + public ChangeTrackingList() + { + } + + public ChangeTrackingList(IList innerList) + { + if (innerList != null) + { + _innerList = innerList; + } + } + + public ChangeTrackingList(IReadOnlyList innerList) + { + if (innerList != null) + { + _innerList = innerList.ToList(); + } + } + + public bool IsUndefined => _innerList == null; + + public int Count => IsUndefined ? 0 : EnsureList().Count; + + public bool IsReadOnly => IsUndefined ? false : EnsureList().IsReadOnly; + + public T this[int index] + { + get + { + if (IsUndefined) + { + throw new ArgumentOutOfRangeException(nameof(index)); + } + return EnsureList()[index]; + } + set + { + if (IsUndefined) + { + throw new ArgumentOutOfRangeException(nameof(index)); + } + EnsureList()[index] = value; + } + } + + public void Reset() + { + _innerList = null; + } + + public IEnumerator GetEnumerator() + { + if (IsUndefined) + { + IEnumerator enumerateEmpty() + { + yield break; + } + return enumerateEmpty(); + } + return EnsureList().GetEnumerator(); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + + public void Add(T item) + { + EnsureList().Add(item); + } + + public void Clear() + { + EnsureList().Clear(); + } + + public bool Contains(T item) + { + if (IsUndefined) + { + return false; + } + return EnsureList().Contains(item); + } + + public void CopyTo(T[] array, int arrayIndex) + { + if (IsUndefined) + { + return; + } + EnsureList().CopyTo(array, arrayIndex); + } + + public bool Remove(T item) + { + if (IsUndefined) + { + return false; + } + return EnsureList().Remove(item); + } + + public int IndexOf(T item) + { + if (IsUndefined) + { + return -1; + } + return EnsureList().IndexOf(item); + } + + public void Insert(int index, T item) + { + EnsureList().Insert(index, item); + } + + public void RemoveAt(int index) + { + if (IsUndefined) + { + throw new ArgumentOutOfRangeException(nameof(index)); + } + EnsureList().RemoveAt(index); + } + + public IList EnsureList() + { + return _innerList ??= new List(); + } + } +} diff --git a/sdk/trustedsigning/Azure.Developer.Signing/src/Generated/Internal/ModelSerializationExtensions.cs b/sdk/trustedsigning/Azure.Developer.Signing/src/Generated/Internal/ModelSerializationExtensions.cs new file mode 100644 index 000000000000..6cee265dd20a --- /dev/null +++ b/sdk/trustedsigning/Azure.Developer.Signing/src/Generated/Internal/ModelSerializationExtensions.cs @@ -0,0 +1,398 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Diagnostics; +using System.Globalization; +using System.Text.Json; +using System.Xml; +using Azure.Core; + +namespace Azure.Developer.Signing +{ + internal static class ModelSerializationExtensions + { + internal static readonly ModelReaderWriterOptions WireOptions = new ModelReaderWriterOptions("W"); + + public static object GetObject(this JsonElement element) + { + switch (element.ValueKind) + { + case JsonValueKind.String: + return element.GetString(); + case JsonValueKind.Number: + if (element.TryGetInt32(out int intValue)) + { + return intValue; + } + if (element.TryGetInt64(out long longValue)) + { + return longValue; + } + return element.GetDouble(); + case JsonValueKind.True: + return true; + case JsonValueKind.False: + return false; + case JsonValueKind.Undefined: + case JsonValueKind.Null: + return null; + case JsonValueKind.Object: + var dictionary = new Dictionary(); + foreach (var jsonProperty in element.EnumerateObject()) + { + dictionary.Add(jsonProperty.Name, jsonProperty.Value.GetObject()); + } + return dictionary; + case JsonValueKind.Array: + var list = new List(); + foreach (var item in element.EnumerateArray()) + { + list.Add(item.GetObject()); + } + return list.ToArray(); + default: + throw new NotSupportedException($"Not supported value kind {element.ValueKind}"); + } + } + + public static byte[] GetBytesFromBase64(this JsonElement element, string format) + { + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + + return format switch + { + "U" => TypeFormatters.FromBase64UrlString(element.GetRequiredString()), + "D" => element.GetBytesFromBase64(), + _ => throw new ArgumentException($"Format is not supported: '{format}'", nameof(format)) + }; + } + + public static DateTimeOffset GetDateTimeOffset(this JsonElement element, string format) => format switch + { + "U" when element.ValueKind == JsonValueKind.Number => DateTimeOffset.FromUnixTimeSeconds(element.GetInt64()), + _ => TypeFormatters.ParseDateTimeOffset(element.GetString(), format) + }; + + public static TimeSpan GetTimeSpan(this JsonElement element, string format) => TypeFormatters.ParseTimeSpan(element.GetString(), format); + + public static char GetChar(this JsonElement element) + { + if (element.ValueKind == JsonValueKind.String) + { + var text = element.GetString(); + if (text == null || text.Length != 1) + { + throw new NotSupportedException($"Cannot convert \"{text}\" to a char"); + } + return text[0]; + } + else + { + throw new NotSupportedException($"Cannot convert {element.ValueKind} to a char"); + } + } + + [Conditional("DEBUG")] + public static void ThrowNonNullablePropertyIsNull(this JsonProperty property) + { + throw new JsonException($"A property '{property.Name}' defined as non-nullable but received as null from the service. This exception only happens in DEBUG builds of the library and would be ignored in the release build"); + } + + public static string GetRequiredString(this JsonElement element) + { + var value = element.GetString(); + if (value == null) + { + throw new InvalidOperationException($"The requested operation requires an element of type 'String', but the target element has type '{element.ValueKind}'."); + } + return value; + } + + public static void WriteStringValue(this Utf8JsonWriter writer, DateTimeOffset value, string format) + { + writer.WriteStringValue(TypeFormatters.ToString(value, format)); + } + + public static void WriteStringValue(this Utf8JsonWriter writer, DateTime value, string format) + { + writer.WriteStringValue(TypeFormatters.ToString(value, format)); + } + + public static void WriteStringValue(this Utf8JsonWriter writer, TimeSpan value, string format) + { + writer.WriteStringValue(TypeFormatters.ToString(value, format)); + } + + public static void WriteStringValue(this Utf8JsonWriter writer, char value) + { + writer.WriteStringValue(value.ToString(CultureInfo.InvariantCulture)); + } + + public static void WriteBase64StringValue(this Utf8JsonWriter writer, byte[] value, string format) + { + if (value == null) + { + writer.WriteNullValue(); + return; + } + switch (format) + { + case "U": + writer.WriteStringValue(TypeFormatters.ToBase64UrlString(value)); + break; + case "D": + writer.WriteBase64StringValue(value); + break; + default: + throw new ArgumentException($"Format is not supported: '{format}'", nameof(format)); + } + } + + public static void WriteNumberValue(this Utf8JsonWriter writer, DateTimeOffset value, string format) + { + if (format != "U") + { + throw new ArgumentOutOfRangeException(nameof(format), "Only 'U' format is supported when writing a DateTimeOffset as a Number."); + } + writer.WriteNumberValue(value.ToUnixTimeSeconds()); + } + + public static void WriteObjectValue(this Utf8JsonWriter writer, T value, ModelReaderWriterOptions options = null) + { + switch (value) + { + case null: + writer.WriteNullValue(); + break; + case IJsonModel jsonModel: + jsonModel.Write(writer, options ?? WireOptions); + break; + case IUtf8JsonSerializable serializable: + serializable.Write(writer); + break; + case byte[] bytes: + writer.WriteBase64StringValue(bytes); + break; + case BinaryData bytes0: + writer.WriteBase64StringValue(bytes0); + break; + case JsonElement json: + json.WriteTo(writer); + break; + case int i: + writer.WriteNumberValue(i); + break; + case decimal d: + writer.WriteNumberValue(d); + break; + case double d0: + if (double.IsNaN(d0)) + { + writer.WriteStringValue("NaN"); + } + else + { + writer.WriteNumberValue(d0); + } + break; + case float f: + writer.WriteNumberValue(f); + break; + case long l: + writer.WriteNumberValue(l); + break; + case string s: + writer.WriteStringValue(s); + break; + case bool b: + writer.WriteBooleanValue(b); + break; + case Guid g: + writer.WriteStringValue(g); + break; + case DateTimeOffset dateTimeOffset: + writer.WriteStringValue(dateTimeOffset, "O"); + break; + case DateTime dateTime: + writer.WriteStringValue(dateTime, "O"); + break; + case IEnumerable> enumerable: + writer.WriteStartObject(); + foreach (var pair in enumerable) + { + writer.WritePropertyName(pair.Key); + writer.WriteObjectValue(pair.Value, options); + } + writer.WriteEndObject(); + break; + case IEnumerable objectEnumerable: + writer.WriteStartArray(); + foreach (var item in objectEnumerable) + { + writer.WriteObjectValue(item, options); + } + writer.WriteEndArray(); + break; + case TimeSpan timeSpan: + writer.WriteStringValue(timeSpan, "P"); + break; + default: + throw new NotSupportedException($"Not supported type {value.GetType()}"); + } + } + + public static void WriteObjectValue(this Utf8JsonWriter writer, object value, ModelReaderWriterOptions options = null) + { + writer.WriteObjectValue(value, options); + } + + internal static class TypeFormatters + { + private const string RoundtripZFormat = "yyyy-MM-ddTHH:mm:ss.fffffffZ"; + public const string DefaultNumberFormat = "G"; + + public static string ToString(bool value) => value ? "true" : "false"; + + public static string ToString(DateTime value, string format) => value.Kind switch + { + DateTimeKind.Utc => ToString((DateTimeOffset)value, format), + _ => throw new NotSupportedException($"DateTime {value} has a Kind of {value.Kind}. Azure SDK requires it to be UTC. You can call DateTime.SpecifyKind to change Kind property value to DateTimeKind.Utc.") + }; + + public static string ToString(DateTimeOffset value, string format) => format switch + { + "D" => value.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture), + "U" => value.ToUnixTimeSeconds().ToString(CultureInfo.InvariantCulture), + "O" => value.ToUniversalTime().ToString(RoundtripZFormat, CultureInfo.InvariantCulture), + "o" => value.ToUniversalTime().ToString(RoundtripZFormat, CultureInfo.InvariantCulture), + "R" => value.ToString("r", CultureInfo.InvariantCulture), + _ => value.ToString(format, CultureInfo.InvariantCulture) + }; + + public static string ToString(TimeSpan value, string format) => format switch + { + "P" => XmlConvert.ToString(value), + _ => value.ToString(format, CultureInfo.InvariantCulture) + }; + + public static string ToString(byte[] value, string format) => format switch + { + "U" => ToBase64UrlString(value), + "D" => Convert.ToBase64String(value), + _ => throw new ArgumentException($"Format is not supported: '{format}'", nameof(format)) + }; + + public static string ToBase64UrlString(byte[] value) + { + int numWholeOrPartialInputBlocks = checked(value.Length + 2) / 3; + int size = checked(numWholeOrPartialInputBlocks * 4); + char[] output = new char[size]; + + int numBase64Chars = Convert.ToBase64CharArray(value, 0, value.Length, output, 0); + + int i = 0; + for (; i < numBase64Chars; i++) + { + char ch = output[i]; + if (ch == '+') + { + output[i] = '-'; + } + else + { + if (ch == '/') + { + output[i] = '_'; + } + else + { + if (ch == '=') + { + break; + } + } + } + } + + return new string(output, 0, i); + } + + public static byte[] FromBase64UrlString(string value) + { + int paddingCharsToAdd = (value.Length % 4) switch + { + 0 => 0, + 2 => 2, + 3 => 1, + _ => throw new InvalidOperationException("Malformed input") + }; + char[] output = new char[(value.Length + paddingCharsToAdd)]; + int i = 0; + for (; i < value.Length; i++) + { + char ch = value[i]; + if (ch == '-') + { + output[i] = '+'; + } + else + { + if (ch == '_') + { + output[i] = '/'; + } + else + { + output[i] = ch; + } + } + } + + for (; i < output.Length; i++) + { + output[i] = '='; + } + + return Convert.FromBase64CharArray(output, 0, output.Length); + } + + public static DateTimeOffset ParseDateTimeOffset(string value, string format) => format switch + { + "U" => DateTimeOffset.FromUnixTimeSeconds(long.Parse(value, CultureInfo.InvariantCulture)), + _ => DateTimeOffset.Parse(value, CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal) + }; + + public static TimeSpan ParseTimeSpan(string value, string format) => format switch + { + "P" => XmlConvert.ToTimeSpan(value), + _ => TimeSpan.ParseExact(value, format, CultureInfo.InvariantCulture) + }; + + public static string ConvertToString(object value, string format = null) => value switch + { + null => "null", + string s => s, + bool b => ToString(b), + int or float or double or long or decimal => ((IFormattable)value).ToString(DefaultNumberFormat, CultureInfo.InvariantCulture), + byte[] b0 when format != null => ToString(b0, format), + IEnumerable s0 => string.Join(",", s0), + DateTimeOffset dateTime when format != null => ToString(dateTime, format), + TimeSpan timeSpan when format != null => ToString(timeSpan, format), + TimeSpan timeSpan0 => XmlConvert.ToString(timeSpan0), + Guid guid => guid.ToString(), + BinaryData binaryData => ConvertToString(binaryData.ToArray(), format), + _ => value.ToString() + }; + } + } +} diff --git a/sdk/trustedsigning/Azure.Developer.Signing/src/Generated/Internal/Optional.cs b/sdk/trustedsigning/Azure.Developer.Signing/src/Generated/Internal/Optional.cs new file mode 100644 index 000000000000..235b4beded8b --- /dev/null +++ b/sdk/trustedsigning/Azure.Developer.Signing/src/Generated/Internal/Optional.cs @@ -0,0 +1,51 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System.Collections.Generic; +using System.Text.Json; + +namespace Azure.Developer.Signing +{ + internal static class Optional + { + public static bool IsCollectionDefined(IEnumerable collection) + { + return !(collection is ChangeTrackingList changeTrackingList && changeTrackingList.IsUndefined); + } + + public static bool IsCollectionDefined(IDictionary collection) + { + return !(collection is ChangeTrackingDictionary changeTrackingDictionary && changeTrackingDictionary.IsUndefined); + } + + public static bool IsCollectionDefined(IReadOnlyDictionary collection) + { + return !(collection is ChangeTrackingDictionary changeTrackingDictionary && changeTrackingDictionary.IsUndefined); + } + + public static bool IsDefined(T? value) + where T : struct + { + return value.HasValue; + } + + public static bool IsDefined(object value) + { + return value != null; + } + + public static bool IsDefined(JsonElement value) + { + return value.ValueKind != JsonValueKind.Undefined; + } + + public static bool IsDefined(string value) + { + return value != null; + } + } +} diff --git a/sdk/trustedsigning/Azure.Developer.Signing/src/Generated/Internal/Utf8JsonRequestContent.cs b/sdk/trustedsigning/Azure.Developer.Signing/src/Generated/Internal/Utf8JsonRequestContent.cs new file mode 100644 index 000000000000..4b699033ee5e --- /dev/null +++ b/sdk/trustedsigning/Azure.Developer.Signing/src/Generated/Internal/Utf8JsonRequestContent.cs @@ -0,0 +1,55 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System.IO; +using System.Text.Json; +using System.Threading; +using System.Threading.Tasks; +using Azure.Core; + +namespace Azure.Developer.Signing +{ + internal class Utf8JsonRequestContent : RequestContent + { + private readonly MemoryStream _stream; + private readonly RequestContent _content; + + public Utf8JsonRequestContent() + { + _stream = new MemoryStream(); + _content = Create(_stream); + JsonWriter = new Utf8JsonWriter(_stream); + } + + public Utf8JsonWriter JsonWriter { get; } + + public override async Task WriteToAsync(Stream stream, CancellationToken cancellationToken = default) + { + await JsonWriter.FlushAsync().ConfigureAwait(false); + await _content.WriteToAsync(stream, cancellationToken).ConfigureAwait(false); + } + + public override void WriteTo(Stream stream, CancellationToken cancellationToken = default) + { + JsonWriter.Flush(); + _content.WriteTo(stream, cancellationToken); + } + + public override bool TryComputeLength(out long length) + { + length = JsonWriter.BytesCommitted + JsonWriter.BytesPending; + return true; + } + + public override void Dispose() + { + JsonWriter.Dispose(); + _content.Dispose(); + _stream.Dispose(); + } + } +} diff --git a/sdk/trustedsigning/Azure.Developer.Signing/src/Generated/OperationState.cs b/sdk/trustedsigning/Azure.Developer.Signing/src/Generated/OperationState.cs new file mode 100644 index 000000000000..17efc7bc7424 --- /dev/null +++ b/sdk/trustedsigning/Azure.Developer.Signing/src/Generated/OperationState.cs @@ -0,0 +1,60 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System; +using System.ComponentModel; + +namespace Azure.Developer.Signing +{ + /// Enum describing allowed operation states. + public readonly partial struct OperationState : IEquatable + { + private readonly string _value; + + /// Initializes a new instance of . + /// is null. + public OperationState(string value) + { + _value = value ?? throw new ArgumentNullException(nameof(value)); + } + + private const string NotStartedValue = "NotStarted"; + private const string RunningValue = "Running"; + private const string SucceededValue = "Succeeded"; + private const string FailedValue = "Failed"; + private const string CanceledValue = "Canceled"; + + /// The operation has not started. + public static OperationState NotStarted { get; } = new OperationState(NotStartedValue); + /// The operation is in progress. + public static OperationState Running { get; } = new OperationState(RunningValue); + /// The operation has completed successfully. + public static OperationState Succeeded { get; } = new OperationState(SucceededValue); + /// The operation has failed. + public static OperationState Failed { get; } = new OperationState(FailedValue); + /// The operation has been canceled by the user. + public static OperationState Canceled { get; } = new OperationState(CanceledValue); + /// Determines if two values are the same. + public static bool operator ==(OperationState left, OperationState right) => left.Equals(right); + /// Determines if two values are not the same. + public static bool operator !=(OperationState left, OperationState right) => !left.Equals(right); + /// Converts a string to a . + public static implicit operator OperationState(string value) => new OperationState(value); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object obj) => obj is OperationState other && Equals(other); + /// + public bool Equals(OperationState other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() => _value != null ? StringComparer.InvariantCultureIgnoreCase.GetHashCode(_value) : 0; + /// + public override string ToString() => _value; + } +} diff --git a/sdk/trustedsigning/Azure.Developer.Signing/src/Generated/OperationStatusSignResultError.Serialization.cs b/sdk/trustedsigning/Azure.Developer.Signing/src/Generated/OperationStatusSignResultError.Serialization.cs new file mode 100644 index 000000000000..ce3785a205bb --- /dev/null +++ b/sdk/trustedsigning/Azure.Developer.Signing/src/Generated/OperationStatusSignResultError.Serialization.cs @@ -0,0 +1,173 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; +using Azure.Core; + +namespace Azure.Developer.Signing +{ + public partial class OperationStatusSignResultError : IUtf8JsonSerializable, IJsonModel + { + void IUtf8JsonSerializable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, ModelSerializationExtensions.WireOptions); + + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(OperationStatusSignResultError)} does not support writing '{format}' format."); + } + + writer.WriteStartObject(); + writer.WritePropertyName("id"u8); + writer.WriteStringValue(Id); + writer.WritePropertyName("status"u8); + writer.WriteStringValue(Status.ToString()); + if (Optional.IsDefined(Error)) + { + writer.WritePropertyName("error"u8); + JsonSerializer.Serialize(writer, Error); + } + if (Optional.IsDefined(Result)) + { + writer.WritePropertyName("result"u8); + writer.WriteObjectValue(Result, options); + } + if (options.Format != "W" && _serializedAdditionalRawData != null) + { + foreach (var item in _serializedAdditionalRawData) + { + writer.WritePropertyName(item.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(item.Value); +#else + using (JsonDocument document = JsonDocument.Parse(item.Value)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + } + writer.WriteEndObject(); + } + + OperationStatusSignResultError IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(OperationStatusSignResultError)} does not support reading '{format}' format."); + } + + using JsonDocument document = JsonDocument.ParseValue(ref reader); + return DeserializeOperationStatusSignResultError(document.RootElement, options); + } + + internal static OperationStatusSignResultError DeserializeOperationStatusSignResultError(JsonElement element, ModelReaderWriterOptions options = null) + { + options ??= ModelSerializationExtensions.WireOptions; + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + string id = default; + OperationState status = default; + ResponseError error = default; + SignResult result = default; + IDictionary serializedAdditionalRawData = default; + Dictionary rawDataDictionary = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("id"u8)) + { + id = property.Value.GetString(); + continue; + } + if (property.NameEquals("status"u8)) + { + status = new OperationState(property.Value.GetString()); + continue; + } + if (property.NameEquals("error"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + error = JsonSerializer.Deserialize(property.Value.GetRawText()); + continue; + } + if (property.NameEquals("result"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + result = SignResult.DeserializeSignResult(property.Value, options); + continue; + } + if (options.Format != "W") + { + rawDataDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + serializedAdditionalRawData = rawDataDictionary; + return new OperationStatusSignResultError(id, status, error, result, serializedAdditionalRawData); + } + + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + return ModelReaderWriter.Write(this, options); + default: + throw new FormatException($"The model {nameof(OperationStatusSignResultError)} does not support writing '{options.Format}' format."); + } + } + + OperationStatusSignResultError IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + { + using JsonDocument document = JsonDocument.Parse(data); + return DeserializeOperationStatusSignResultError(document.RootElement, options); + } + default: + throw new FormatException($"The model {nameof(OperationStatusSignResultError)} does not support reading '{options.Format}' format."); + } + } + + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + + /// Deserializes the model from a raw response. + /// The response to deserialize the model from. + internal static OperationStatusSignResultError FromResponse(Response response) + { + using var document = JsonDocument.Parse(response.Content); + return DeserializeOperationStatusSignResultError(document.RootElement); + } + + /// Convert into a . + internal virtual RequestContent ToRequestContent() + { + var content = new Utf8JsonRequestContent(); + content.JsonWriter.WriteObjectValue(this, ModelSerializationExtensions.WireOptions); + return content; + } + } +} diff --git a/sdk/trustedsigning/Azure.Developer.Signing/src/Generated/OperationStatusSignResultError.cs b/sdk/trustedsigning/Azure.Developer.Signing/src/Generated/OperationStatusSignResultError.cs new file mode 100644 index 000000000000..03ebb218f310 --- /dev/null +++ b/sdk/trustedsigning/Azure.Developer.Signing/src/Generated/OperationStatusSignResultError.cs @@ -0,0 +1,89 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System; +using System.Collections.Generic; + +namespace Azure.Developer.Signing +{ + /// Provides status details for long running operations. + public partial class OperationStatusSignResultError + { + /// + /// Keeps track of any properties unknown to the library. + /// + /// To assign an object to the value of this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + private IDictionary _serializedAdditionalRawData; + + /// Initializes a new instance of . + /// The unique ID of the operation. + /// The status of the operation. + /// is null. + internal OperationStatusSignResultError(string id, OperationState status) + { + Argument.AssertNotNull(id, nameof(id)); + + Id = id; + Status = status; + } + + /// Initializes a new instance of . + /// The unique ID of the operation. + /// The status of the operation. + /// Error object that describes the error when status is "Failed". + /// The result of the operation. + /// Keeps track of any properties unknown to the library. + internal OperationStatusSignResultError(string id, OperationState status, ResponseError error, SignResult result, IDictionary serializedAdditionalRawData) + { + Id = id; + Status = status; + Error = error; + Result = result; + _serializedAdditionalRawData = serializedAdditionalRawData; + } + + /// Initializes a new instance of for deserialization. + internal OperationStatusSignResultError() + { + } + + /// The unique ID of the operation. + public string Id { get; } + /// The status of the operation. + public OperationState Status { get; } + /// Error object that describes the error when status is "Failed". + public ResponseError Error { get; } + /// The result of the operation. + public SignResult Result { get; } + } +} diff --git a/sdk/trustedsigning/Azure.Developer.Signing/src/Generated/SignResult.Serialization.cs b/sdk/trustedsigning/Azure.Developer.Signing/src/Generated/SignResult.Serialization.cs new file mode 100644 index 000000000000..4cab54c24cf6 --- /dev/null +++ b/sdk/trustedsigning/Azure.Developer.Signing/src/Generated/SignResult.Serialization.cs @@ -0,0 +1,157 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; +using Azure.Core; + +namespace Azure.Developer.Signing +{ + public partial class SignResult : IUtf8JsonSerializable, IJsonModel + { + void IUtf8JsonSerializable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, ModelSerializationExtensions.WireOptions); + + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(SignResult)} does not support writing '{format}' format."); + } + + writer.WriteStartObject(); + if (Optional.IsDefined(Signature)) + { + writer.WritePropertyName("signature"u8); + writer.WriteBase64StringValue(Signature.ToArray(), "D"); + } + if (Optional.IsDefined(SigningCertificate)) + { + writer.WritePropertyName("signingCertificate"u8); + writer.WriteBase64StringValue(SigningCertificate.ToArray(), "D"); + } + if (options.Format != "W" && _serializedAdditionalRawData != null) + { + foreach (var item in _serializedAdditionalRawData) + { + writer.WritePropertyName(item.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(item.Value); +#else + using (JsonDocument document = JsonDocument.Parse(item.Value)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + } + writer.WriteEndObject(); + } + + SignResult IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(SignResult)} does not support reading '{format}' format."); + } + + using JsonDocument document = JsonDocument.ParseValue(ref reader); + return DeserializeSignResult(document.RootElement, options); + } + + internal static SignResult DeserializeSignResult(JsonElement element, ModelReaderWriterOptions options = null) + { + options ??= ModelSerializationExtensions.WireOptions; + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + BinaryData signature = default; + BinaryData signingCertificate = default; + IDictionary serializedAdditionalRawData = default; + Dictionary rawDataDictionary = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("signature"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + signature = BinaryData.FromBytes(property.Value.GetBytesFromBase64("D")); + continue; + } + if (property.NameEquals("signingCertificate"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + signingCertificate = BinaryData.FromBytes(property.Value.GetBytesFromBase64("D")); + continue; + } + if (options.Format != "W") + { + rawDataDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + serializedAdditionalRawData = rawDataDictionary; + return new SignResult(signature, signingCertificate, serializedAdditionalRawData); + } + + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + return ModelReaderWriter.Write(this, options); + default: + throw new FormatException($"The model {nameof(SignResult)} does not support writing '{options.Format}' format."); + } + } + + SignResult IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + { + using JsonDocument document = JsonDocument.Parse(data); + return DeserializeSignResult(document.RootElement, options); + } + default: + throw new FormatException($"The model {nameof(SignResult)} does not support reading '{options.Format}' format."); + } + } + + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + + /// Deserializes the model from a raw response. + /// The response to deserialize the model from. + internal static SignResult FromResponse(Response response) + { + using var document = JsonDocument.Parse(response.Content); + return DeserializeSignResult(document.RootElement); + } + + /// Convert into a . + internal virtual RequestContent ToRequestContent() + { + var content = new Utf8JsonRequestContent(); + content.JsonWriter.WriteObjectValue(this, ModelSerializationExtensions.WireOptions); + return content; + } + } +} diff --git a/sdk/trustedsigning/Azure.Developer.Signing/src/Generated/SignResult.cs b/sdk/trustedsigning/Azure.Developer.Signing/src/Generated/SignResult.cs new file mode 100644 index 000000000000..a59cd64ea4db --- /dev/null +++ b/sdk/trustedsigning/Azure.Developer.Signing/src/Generated/SignResult.cs @@ -0,0 +1,103 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System; +using System.Collections.Generic; + +namespace Azure.Developer.Signing +{ + /// The sign status model. + public partial class SignResult + { + /// + /// Keeps track of any properties unknown to the library. + /// + /// To assign an object to the value of this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + private IDictionary _serializedAdditionalRawData; + + /// Initializes a new instance of . + internal SignResult() + { + } + + /// Initializes a new instance of . + /// Digital signature of the requested content digest. + /// + /// Signing certificate corresponding to the private key used to sign the requested + /// digest. + /// + /// Keeps track of any properties unknown to the library. + internal SignResult(BinaryData signature, BinaryData signingCertificate, IDictionary serializedAdditionalRawData) + { + Signature = signature; + SigningCertificate = signingCertificate; + _serializedAdditionalRawData = serializedAdditionalRawData; + } + + /// + /// Digital signature of the requested content digest. + /// + /// To assign a byte[] to this property use . + /// The byte[] will be serialized to a Base64 encoded string. + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromBytes(new byte[] { 1, 2, 3 }) + /// Creates a payload of "AQID". + /// + /// + /// + /// + public BinaryData Signature { get; } + /// + /// Signing certificate corresponding to the private key used to sign the requested + /// digest. + /// + /// To assign a byte[] to this property use . + /// The byte[] will be serialized to a Base64 encoded string. + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromBytes(new byte[] { 1, 2, 3 }) + /// Creates a payload of "AQID". + /// + /// + /// + /// + public BinaryData SigningCertificate { get; } + } +} diff --git a/sdk/trustedsigning/Azure.Developer.Signing/src/Generated/SignatureAlgorithm.Serialization.cs b/sdk/trustedsigning/Azure.Developer.Signing/src/Generated/SignatureAlgorithm.Serialization.cs new file mode 100644 index 000000000000..a17160c054da --- /dev/null +++ b/sdk/trustedsigning/Azure.Developer.Signing/src/Generated/SignatureAlgorithm.Serialization.cs @@ -0,0 +1,44 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System; + +namespace Azure.Developer.Signing +{ + internal static partial class SignatureAlgorithmExtensions + { + public static string ToSerialString(this SignatureAlgorithm value) => value switch + { + SignatureAlgorithm.RS256 => "RS256", + SignatureAlgorithm.RS384 => "RS384", + SignatureAlgorithm.RS512 => "RS512", + SignatureAlgorithm.PS256 => "PS256", + SignatureAlgorithm.PS384 => "PS384", + SignatureAlgorithm.PS512 => "PS512", + SignatureAlgorithm.ES256 => "ES256", + SignatureAlgorithm.ES384 => "ES384", + SignatureAlgorithm.ES512 => "ES512", + SignatureAlgorithm.ES256K => "ES256K", + _ => throw new ArgumentOutOfRangeException(nameof(value), value, "Unknown SignatureAlgorithm value.") + }; + + public static SignatureAlgorithm ToSignatureAlgorithm(this string value) + { + if (StringComparer.OrdinalIgnoreCase.Equals(value, "RS256")) return SignatureAlgorithm.RS256; + if (StringComparer.OrdinalIgnoreCase.Equals(value, "RS384")) return SignatureAlgorithm.RS384; + if (StringComparer.OrdinalIgnoreCase.Equals(value, "RS512")) return SignatureAlgorithm.RS512; + if (StringComparer.OrdinalIgnoreCase.Equals(value, "PS256")) return SignatureAlgorithm.PS256; + if (StringComparer.OrdinalIgnoreCase.Equals(value, "PS384")) return SignatureAlgorithm.PS384; + if (StringComparer.OrdinalIgnoreCase.Equals(value, "PS512")) return SignatureAlgorithm.PS512; + if (StringComparer.OrdinalIgnoreCase.Equals(value, "ES256")) return SignatureAlgorithm.ES256; + if (StringComparer.OrdinalIgnoreCase.Equals(value, "ES384")) return SignatureAlgorithm.ES384; + if (StringComparer.OrdinalIgnoreCase.Equals(value, "ES512")) return SignatureAlgorithm.ES512; + if (StringComparer.OrdinalIgnoreCase.Equals(value, "ES256K")) return SignatureAlgorithm.ES256K; + throw new ArgumentOutOfRangeException(nameof(value), value, "Unknown SignatureAlgorithm value."); + } + } +} diff --git a/sdk/trustedsigning/Azure.Developer.Signing/src/Generated/SignatureAlgorithm.cs b/sdk/trustedsigning/Azure.Developer.Signing/src/Generated/SignatureAlgorithm.cs new file mode 100644 index 000000000000..67e586813187 --- /dev/null +++ b/sdk/trustedsigning/Azure.Developer.Signing/src/Generated/SignatureAlgorithm.cs @@ -0,0 +1,34 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +namespace Azure.Developer.Signing +{ + /// Algorithms supported for signing. + public enum SignatureAlgorithm + { + /// RSASSA-PKCS1-v1_5 using SHA-256 hash algorithm. + RS256, + /// RSASSA-PKCS1-v1_5 using SHA-384 hash algorithm. + RS384, + /// RSASSA-PKCS1-v1_5 using SHA-512 hash algorithm. + RS512, + /// RSASSA-PSS using SHA-256 hash algorithm. + PS256, + /// RSASSA-PSS using SHA-384 hash algorithm. + PS384, + /// RSASSA-PSS using SHA-512 hash algorithm. + PS512, + /// ECDSA using P-256 and SHA-256 hash algorithm. + ES256, + /// ECDSA using P-384 and SHA-384 hash algorithm. + ES384, + /// ECDSA using P-521 and SHA-512 hash algorithm. + ES512, + /// ECDSA using secp256k1 and SHA-256 hash algorithm. + ES256K + } +} diff --git a/sdk/trustedsigning/Azure.Developer.Signing/src/Generated/SigningClient.cs b/sdk/trustedsigning/Azure.Developer.Signing/src/Generated/SigningClient.cs new file mode 100644 index 000000000000..1885a47c3018 --- /dev/null +++ b/sdk/trustedsigning/Azure.Developer.Signing/src/Generated/SigningClient.cs @@ -0,0 +1,71 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System; +using Azure.Core; +using Azure.Core.Pipeline; + +namespace Azure.Developer.Signing +{ + // Data plane generated client. + /// The Signing service client. + public partial class SigningClient + { + private static readonly string[] AuthorizationScopes = new string[] { "https://codesigning.azure.net/.default" }; + private readonly TokenCredential _tokenCredential; + private readonly HttpPipeline _pipeline; + private readonly string _region; + + /// The ClientDiagnostics is used to provide tracing support for the client library. + internal ClientDiagnostics ClientDiagnostics { get; } + + /// The HTTP pipeline for sending and receiving REST requests and responses. + public virtual HttpPipeline Pipeline => _pipeline; + + /// Initializes a new instance of SigningClient for mocking. + protected SigningClient() + { + } + + /// Initializes a new instance of SigningClient. + /// The Azure region wherein requests for signing will be sent. + /// A credential used to authenticate to an Azure Service. + /// or is null. + /// is an empty string, and was expected to be non-empty. + public SigningClient(string region, TokenCredential credential) : this(region, credential, new SigningClientOptions()) + { + } + + /// Initializes a new instance of SigningClient. + /// The Azure region wherein requests for signing will be sent. + /// A credential used to authenticate to an Azure Service. + /// The options for configuring the client. + /// or is null. + /// is an empty string, and was expected to be non-empty. + public SigningClient(string region, TokenCredential credential, SigningClientOptions options) + { + Argument.AssertNotNullOrEmpty(region, nameof(region)); + Argument.AssertNotNull(credential, nameof(credential)); + options ??= new SigningClientOptions(); + + ClientDiagnostics = new ClientDiagnostics(options, true); + _tokenCredential = credential; + _pipeline = HttpPipelineBuilder.Build(options, Array.Empty(), new HttpPipelinePolicy[] { new BearerTokenAuthenticationPolicy(_tokenCredential, AuthorizationScopes) }, new ResponseClassifier()); + _region = region; + } + + /// Initializes a new instance of CertificateProfile. + /// The API version to use for this operation. + /// is null. + public virtual CertificateProfile GetCertificateProfileClient(string apiVersion = "2023-06-15-preview") + { + Argument.AssertNotNull(apiVersion, nameof(apiVersion)); + + return new CertificateProfile(ClientDiagnostics, _pipeline, _tokenCredential, _region, apiVersion); + } + } +} diff --git a/sdk/trustedsigning/Azure.Developer.Signing/src/Generated/SigningClientOptions.cs b/sdk/trustedsigning/Azure.Developer.Signing/src/Generated/SigningClientOptions.cs new file mode 100644 index 000000000000..28c59f1516fc --- /dev/null +++ b/sdk/trustedsigning/Azure.Developer.Signing/src/Generated/SigningClientOptions.cs @@ -0,0 +1,37 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System; +using Azure.Core; + +namespace Azure.Developer.Signing +{ + /// Client options for SigningClient. + public partial class SigningClientOptions : ClientOptions + { + private const ServiceVersion LatestVersion = ServiceVersion.V2023_06_15_Preview; + + /// The version of the service to use. + public enum ServiceVersion + { + /// Service version "2023-06-15-preview". + V2023_06_15_Preview = 1, + } + + internal string Version { get; } + + /// Initializes new instance of SigningClientOptions. + public SigningClientOptions(ServiceVersion version = LatestVersion) + { + Version = version switch + { + ServiceVersion.V2023_06_15_Preview => "2023-06-15-preview", + _ => throw new NotSupportedException() + }; + } + } +} diff --git a/sdk/trustedsigning/Azure.Developer.Signing/src/Generated/SigningPayloadOptions.Serialization.cs b/sdk/trustedsigning/Azure.Developer.Signing/src/Generated/SigningPayloadOptions.Serialization.cs new file mode 100644 index 000000000000..90359bf8133b --- /dev/null +++ b/sdk/trustedsigning/Azure.Developer.Signing/src/Generated/SigningPayloadOptions.Serialization.cs @@ -0,0 +1,217 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; +using Azure.Core; + +namespace Azure.Developer.Signing +{ + internal partial class SigningPayloadOptions : IUtf8JsonSerializable, IJsonModel + { + void IUtf8JsonSerializable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, ModelSerializationExtensions.WireOptions); + + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(SigningPayloadOptions)} does not support writing '{format}' format."); + } + + writer.WriteStartObject(); + writer.WritePropertyName("signatureAlgorithm"u8); + writer.WriteStringValue(SignatureAlgorithm.ToSerialString()); + writer.WritePropertyName("digest"u8); + writer.WriteBase64StringValue(Digest.ToArray(), "D"); + if (Optional.IsCollectionDefined(FileHashList)) + { + writer.WritePropertyName("fileHashList"u8); + writer.WriteStartArray(); + foreach (var item in FileHashList) + { + if (item == null) + { + writer.WriteNullValue(); + continue; + } + writer.WriteBase64StringValue(item.ToArray(), "D"); + } + writer.WriteEndArray(); + } + if (Optional.IsCollectionDefined(AuthenticodeHashList)) + { + writer.WritePropertyName("authenticodeHashList"u8); + writer.WriteStartArray(); + foreach (var item in AuthenticodeHashList) + { + if (item == null) + { + writer.WriteNullValue(); + continue; + } + writer.WriteBase64StringValue(item.ToArray(), "D"); + } + writer.WriteEndArray(); + } + if (options.Format != "W" && _serializedAdditionalRawData != null) + { + foreach (var item in _serializedAdditionalRawData) + { + writer.WritePropertyName(item.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(item.Value); +#else + using (JsonDocument document = JsonDocument.Parse(item.Value)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + } + writer.WriteEndObject(); + } + + SigningPayloadOptions IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(SigningPayloadOptions)} does not support reading '{format}' format."); + } + + using JsonDocument document = JsonDocument.ParseValue(ref reader); + return DeserializeSigningPayloadOptions(document.RootElement, options); + } + + internal static SigningPayloadOptions DeserializeSigningPayloadOptions(JsonElement element, ModelReaderWriterOptions options = null) + { + options ??= ModelSerializationExtensions.WireOptions; + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + SignatureAlgorithm signatureAlgorithm = default; + BinaryData digest = default; + IList fileHashList = default; + IList authenticodeHashList = default; + IDictionary serializedAdditionalRawData = default; + Dictionary rawDataDictionary = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("signatureAlgorithm"u8)) + { + signatureAlgorithm = property.Value.GetString().ToSignatureAlgorithm(); + continue; + } + if (property.NameEquals("digest"u8)) + { + digest = BinaryData.FromBytes(property.Value.GetBytesFromBase64("D")); + continue; + } + if (property.NameEquals("fileHashList"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + List array = new List(); + foreach (var item in property.Value.EnumerateArray()) + { + if (item.ValueKind == JsonValueKind.Null) + { + array.Add(null); + } + else + { + array.Add(BinaryData.FromBytes(item.GetBytesFromBase64("D"))); + } + } + fileHashList = array; + continue; + } + if (property.NameEquals("authenticodeHashList"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + List array = new List(); + foreach (var item in property.Value.EnumerateArray()) + { + if (item.ValueKind == JsonValueKind.Null) + { + array.Add(null); + } + else + { + array.Add(BinaryData.FromBytes(item.GetBytesFromBase64("D"))); + } + } + authenticodeHashList = array; + continue; + } + if (options.Format != "W") + { + rawDataDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + serializedAdditionalRawData = rawDataDictionary; + return new SigningPayloadOptions(signatureAlgorithm, digest, fileHashList ?? new ChangeTrackingList(), authenticodeHashList ?? new ChangeTrackingList(), serializedAdditionalRawData); + } + + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + return ModelReaderWriter.Write(this, options); + default: + throw new FormatException($"The model {nameof(SigningPayloadOptions)} does not support writing '{options.Format}' format."); + } + } + + SigningPayloadOptions IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + { + using JsonDocument document = JsonDocument.Parse(data); + return DeserializeSigningPayloadOptions(document.RootElement, options); + } + default: + throw new FormatException($"The model {nameof(SigningPayloadOptions)} does not support reading '{options.Format}' format."); + } + } + + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + + /// Deserializes the model from a raw response. + /// The response to deserialize the model from. + internal static SigningPayloadOptions FromResponse(Response response) + { + using var document = JsonDocument.Parse(response.Content); + return DeserializeSigningPayloadOptions(document.RootElement); + } + + /// Convert into a . + internal virtual RequestContent ToRequestContent() + { + var content = new Utf8JsonRequestContent(); + content.JsonWriter.WriteObjectValue(this, ModelSerializationExtensions.WireOptions); + return content; + } + } +} diff --git a/sdk/trustedsigning/Azure.Developer.Signing/src/Generated/SigningPayloadOptions.cs b/sdk/trustedsigning/Azure.Developer.Signing/src/Generated/SigningPayloadOptions.cs new file mode 100644 index 000000000000..1df124463831 --- /dev/null +++ b/sdk/trustedsigning/Azure.Developer.Signing/src/Generated/SigningPayloadOptions.cs @@ -0,0 +1,136 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System; +using System.Collections.Generic; + +namespace Azure.Developer.Signing +{ + /// The artifact request information to be signed by the service. + internal partial class SigningPayloadOptions + { + /// + /// Keeps track of any properties unknown to the library. + /// + /// To assign an object to the value of this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + private IDictionary _serializedAdditionalRawData; + + /// Initializes a new instance of . + /// The supported signature algorithm identifiers. + /// Content digest to sign. + /// is null. + public SigningPayloadOptions(SignatureAlgorithm signatureAlgorithm, BinaryData digest) + { + Argument.AssertNotNull(digest, nameof(digest)); + + SignatureAlgorithm = signatureAlgorithm; + Digest = digest; + FileHashList = new ChangeTrackingList(); + AuthenticodeHashList = new ChangeTrackingList(); + } + + /// Initializes a new instance of . + /// The supported signature algorithm identifiers. + /// Content digest to sign. + /// List of full file digital signatures. + /// List of authenticode digital signatures. + /// Keeps track of any properties unknown to the library. + internal SigningPayloadOptions(SignatureAlgorithm signatureAlgorithm, BinaryData digest, IList fileHashList, IList authenticodeHashList, IDictionary serializedAdditionalRawData) + { + SignatureAlgorithm = signatureAlgorithm; + Digest = digest; + FileHashList = fileHashList; + AuthenticodeHashList = authenticodeHashList; + _serializedAdditionalRawData = serializedAdditionalRawData; + } + + /// Initializes a new instance of for deserialization. + internal SigningPayloadOptions() + { + } + + /// The supported signature algorithm identifiers. + public SignatureAlgorithm SignatureAlgorithm { get; } + /// + /// Content digest to sign. + /// + /// To assign a byte[] to this property use . + /// The byte[] will be serialized to a Base64 encoded string. + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromBytes(new byte[] { 1, 2, 3 }) + /// Creates a payload of "AQID". + /// + /// + /// + /// + public BinaryData Digest { get; } + /// + /// List of full file digital signatures. + /// + /// To assign a byte[] to the element of this property use . + /// The byte[] will be serialized to a Base64 encoded string. + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromBytes(new byte[] { 1, 2, 3 }) + /// Creates a payload of "AQID". + /// + /// + /// + /// + public IList FileHashList { get; } + /// + /// List of authenticode digital signatures. + /// + /// To assign a byte[] to the element of this property use . + /// The byte[] will be serialized to a Base64 encoded string. + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromBytes(new byte[] { 1, 2, 3 }) + /// Creates a payload of "AQID". + /// + /// + /// + /// + public IList AuthenticodeHashList { get; } + } +} diff --git a/sdk/trustedsigning/Azure.Developer.Signing/src/GlobalSuppressions.cs b/sdk/trustedsigning/Azure.Developer.Signing/src/GlobalSuppressions.cs new file mode 100644 index 000000000000..5d687dd1af0a --- /dev/null +++ b/sdk/trustedsigning/Azure.Developer.Signing/src/GlobalSuppressions.cs @@ -0,0 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System.Diagnostics.CodeAnalysis; + +[assembly: SuppressMessage("Naming", "AZC0030:Improper model name suffix", Justification = "Temporary suppression", Scope = "type", Target = "~T:Azure.Developer.Signing.SigningPayloadOptions")] diff --git a/sdk/trustedsigning/Azure.Developer.Signing/src/Properties/AssemblyInfo.cs b/sdk/trustedsigning/Azure.Developer.Signing/src/Properties/AssemblyInfo.cs new file mode 100644 index 000000000000..3f9923346ff3 --- /dev/null +++ b/sdk/trustedsigning/Azure.Developer.Signing/src/Properties/AssemblyInfo.cs @@ -0,0 +1,11 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System.Runtime.CompilerServices; + +[assembly: InternalsVisibleTo("Azure.Developer.Signing.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100d15ddcb29688295338af4b7686603fe614abd555e09efba8fb88ee09e1f7b1ccaeed2e8f823fa9eef3fdd60217fc012ea67d2479751a0b8c087a4185541b851bd8b16f8d91b840e51b1cb0ba6fe647997e57429265e85ef62d565db50a69ae1647d54d7bd855e4db3d8a91510e5bcbd0edfbbecaa20a7bd9ae74593daa7b11b4")] + +// Replace Microsoft.Test with the correct resource provider namepace for your service and uncomment. +// See https://docs.microsoft.com/en-us/azure/azure-resource-manager/management/azure-services-resource-providers +// for the list of possible values. +[assembly: Azure.Core.AzureResourceProviderNamespace("Microsoft.CodeSigning")] diff --git a/sdk/trustedsigning/Azure.Developer.Signing/tests/Azure.Developer.Signing.Tests.csproj b/sdk/trustedsigning/Azure.Developer.Signing/tests/Azure.Developer.Signing.Tests.csproj new file mode 100644 index 000000000000..b4854622e37e --- /dev/null +++ b/sdk/trustedsigning/Azure.Developer.Signing/tests/Azure.Developer.Signing.Tests.csproj @@ -0,0 +1,25 @@ + + + $(RequiredTargetFrameworks) + + + $(NoWarn);CS1591 + + + + + + + + + + + + + + + + + + + diff --git a/sdk/trustedsigning/Azure.Developer.Signing/tests/DevSigningClientTestEnvironment.cs b/sdk/trustedsigning/Azure.Developer.Signing/tests/DevSigningClientTestEnvironment.cs new file mode 100644 index 000000000000..5eed1f4c3723 --- /dev/null +++ b/sdk/trustedsigning/Azure.Developer.Signing/tests/DevSigningClientTestEnvironment.cs @@ -0,0 +1,18 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using Azure.Core.TestFramework; + +namespace Azure.Developer.Signing.Tests +{ + public class DevSigningClientTestEnvironment : TestEnvironment + { + public Uri Endpoint => new(GetRecordedVariable("DEVSIGNING_ENDPOINT")); + public string Region => GetRecordedVariable("DEVSIGNING_REGION"); + public string ProfileName => GetRecordedVariable("DEVSIGNING_PROFILE_NAME"); + public string AccountName => GetRecordedVariable("DEVSIGNING_ACCOUNT_NAME"); + + public RequestContext context = null; + } +} diff --git a/sdk/trustedsigning/Azure.Developer.Signing/tests/DevSigningClientTests.cs b/sdk/trustedsigning/Azure.Developer.Signing/tests/DevSigningClientTests.cs new file mode 100644 index 000000000000..e80cecf0ccd8 --- /dev/null +++ b/sdk/trustedsigning/Azure.Developer.Signing/tests/DevSigningClientTests.cs @@ -0,0 +1,103 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Security.Cryptography.X509Certificates; +using System.Text.Json; +using System.Threading.Tasks; +using Azure.Core; +using Azure.Core.TestFramework; +using NUnit.Framework; + +namespace Azure.Developer.Signing.Tests +{ + public class DevSigningClientTests : RecordedTestBase + { + private CertificateProfile _certificateProfileClient; + + public DevSigningClientTests(bool isAsync) : base(isAsync) + { + } + + internal CertificateProfile GetCertificateProfileClient() => + InstrumentClient(new SigningClient(TestEnvironment.Region, TestEnvironment.Credential, InstrumentClientOptions(new SigningClientOptions())) + .GetCertificateProfileClient()); + + [SetUp] + public void SetUp() + { + _certificateProfileClient = GetCertificateProfileClient(); + } + + [RecordedTest] + public async Task GetRootCertificateSuccess() + { + Response rootCertResponse = await _certificateProfileClient.GetSignRootCertificateAsync(TestEnvironment.AccountName, TestEnvironment.ProfileName, TestEnvironment.context); + + //Valid X509Certificate2 byte array + Assert.AreEqual(200, rootCertResponse.Status); + Assert.DoesNotThrow(() => new X509Certificate2(rootCertResponse.Content.ToArray())); + } + + [RecordedTest] + [AsyncOnly] + public async Task GetCustomerCertificateEkuSuccess() + { + const string eku = "eku"; + + await foreach (BinaryData item in _certificateProfileClient.GetExtendedKeyUsagesAsync(TestEnvironment.AccountName, TestEnvironment.ProfileName, TestEnvironment.context)) + { + JsonElement result = JsonDocument.Parse(item.ToStream()).RootElement; + + if (!result.TryGetProperty(eku, out JsonElement ekuElement)) + { + FailDueToMissingProperty(eku); + } + + Assert.True(ekuElement.ToString().Contains("1.3.6.1.4.1.311")); + } + } + + [RecordedTest] + public async Task SignSuccess() + { + const string signature = "signature"; + const string signingCert = "signingCertificate"; + const string result = "result"; + const string signatureAlgorithm = "RS256"; + byte[] digest = Convert.FromBase64String("s+y8+MNE4zKv9b0/ZAf3hxt0yixaYoLiXAspe7EnZ5U="); + + using RequestContent content = RequestContent.Create(new + { + signatureAlgorithm, + digest, + }); + + Operation operation = await _certificateProfileClient.SignAsync(WaitUntil.Completed, TestEnvironment.AccountName, TestEnvironment.ProfileName, content); + BinaryData responseData = operation.Value; + + JsonElement operationElement = JsonDocument.Parse(responseData.ToStream()).RootElement; + JsonElement resultElement = operationElement.GetProperty(result); + + if (!resultElement.TryGetProperty(signature, out JsonElement signatureElement)) + { + FailDueToMissingProperty(signature); + } + + if (!resultElement.TryGetProperty(signingCert, out JsonElement signingCertElement)) + { + FailDueToMissingProperty(signingCert); + } + + string signingCertValue = signingCertElement.ToString(); + string signatureValue = signatureElement.ToString(); + + Assert.IsNotEmpty(signatureValue, signingCertValue); + } + + private static void FailDueToMissingProperty(string propertyName) + { + Assert.Fail($"The JSON response received from the service does not include the necessary property: {propertyName}"); + } + } +} diff --git a/sdk/trustedsigning/Azure.Developer.Signing/tests/Generated/Samples/Samples_CertificateProfile.cs b/sdk/trustedsigning/Azure.Developer.Signing/tests/Generated/Samples/Samples_CertificateProfile.cs new file mode 100644 index 000000000000..41bfa8a84537 --- /dev/null +++ b/sdk/trustedsigning/Azure.Developer.Signing/tests/Generated/Samples/Samples_CertificateProfile.cs @@ -0,0 +1,473 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System; +using System.Text.Json; +using System.Threading.Tasks; +using Azure.Core; +using Azure.Identity; +using NUnit.Framework; + +namespace Azure.Developer.Signing.Samples +{ + public partial class Samples_CertificateProfile + { + [Test] + [Ignore("Only validating compilation of examples")] + public void Example_CertificateProfileOperations_GetSigningStatus_ShortVersion() + { + TokenCredential credential = new DefaultAzureCredential(); + CertificateProfile client = new SigningClient("", credential).GetCertificateProfileClient(apiVersion: "2023-06-15-preview"); + + Response response = client.GetSigningStatus("", "", "", null); + + JsonElement result = JsonDocument.Parse(response.ContentStream).RootElement; + Console.WriteLine(result.GetProperty("id").ToString()); + Console.WriteLine(result.GetProperty("status").ToString()); + } + + [Test] + [Ignore("Only validating compilation of examples")] + public async Task Example_CertificateProfileOperations_GetSigningStatus_ShortVersion_Async() + { + TokenCredential credential = new DefaultAzureCredential(); + CertificateProfile client = new SigningClient("", credential).GetCertificateProfileClient(apiVersion: "2023-06-15-preview"); + + Response response = await client.GetSigningStatusAsync("", "", "", null); + + JsonElement result = JsonDocument.Parse(response.ContentStream).RootElement; + Console.WriteLine(result.GetProperty("id").ToString()); + Console.WriteLine(result.GetProperty("status").ToString()); + } + + [Test] + [Ignore("Only validating compilation of examples")] + public void Example_CertificateProfileOperations_GetSigningStatus_ShortVersion_Convenience() + { + TokenCredential credential = new DefaultAzureCredential(); + CertificateProfile client = new SigningClient("", credential).GetCertificateProfileClient(apiVersion: "2023-06-15-preview"); + + Response response = client.GetSigningStatus("", "", ""); + } + + [Test] + [Ignore("Only validating compilation of examples")] + public async Task Example_CertificateProfileOperations_GetSigningStatus_ShortVersion_Convenience_Async() + { + TokenCredential credential = new DefaultAzureCredential(); + CertificateProfile client = new SigningClient("", credential).GetCertificateProfileClient(apiVersion: "2023-06-15-preview"); + + Response response = await client.GetSigningStatusAsync("", "", ""); + } + + [Test] + [Ignore("Only validating compilation of examples")] + public void Example_CertificateProfileOperations_GetSigningStatus_AllParameters() + { + TokenCredential credential = new DefaultAzureCredential(); + CertificateProfile client = new SigningClient("", credential).GetCertificateProfileClient(apiVersion: "2023-06-15-preview"); + + Response response = client.GetSigningStatus("", "", "", null); + + JsonElement result = JsonDocument.Parse(response.ContentStream).RootElement; + Console.WriteLine(result.GetProperty("id").ToString()); + Console.WriteLine(result.GetProperty("status").ToString()); + Console.WriteLine(result.GetProperty("error").GetProperty("code").ToString()); + Console.WriteLine(result.GetProperty("error").GetProperty("message").ToString()); + Console.WriteLine(result.GetProperty("error").GetProperty("target").ToString()); + Console.WriteLine(result.GetProperty("error").GetProperty("innererror").GetProperty("code").ToString()); + Console.WriteLine(result.GetProperty("result").GetProperty("signature").ToString()); + Console.WriteLine(result.GetProperty("result").GetProperty("signingCertificate").ToString()); + } + + [Test] + [Ignore("Only validating compilation of examples")] + public async Task Example_CertificateProfileOperations_GetSigningStatus_AllParameters_Async() + { + TokenCredential credential = new DefaultAzureCredential(); + CertificateProfile client = new SigningClient("", credential).GetCertificateProfileClient(apiVersion: "2023-06-15-preview"); + + Response response = await client.GetSigningStatusAsync("", "", "", null); + + JsonElement result = JsonDocument.Parse(response.ContentStream).RootElement; + Console.WriteLine(result.GetProperty("id").ToString()); + Console.WriteLine(result.GetProperty("status").ToString()); + Console.WriteLine(result.GetProperty("error").GetProperty("code").ToString()); + Console.WriteLine(result.GetProperty("error").GetProperty("message").ToString()); + Console.WriteLine(result.GetProperty("error").GetProperty("target").ToString()); + Console.WriteLine(result.GetProperty("error").GetProperty("innererror").GetProperty("code").ToString()); + Console.WriteLine(result.GetProperty("result").GetProperty("signature").ToString()); + Console.WriteLine(result.GetProperty("result").GetProperty("signingCertificate").ToString()); + } + + [Test] + [Ignore("Only validating compilation of examples")] + public void Example_CertificateProfileOperations_GetSigningStatus_AllParameters_Convenience() + { + TokenCredential credential = new DefaultAzureCredential(); + CertificateProfile client = new SigningClient("", credential).GetCertificateProfileClient(apiVersion: "2023-06-15-preview"); + + Response response = client.GetSigningStatus("", "", ""); + } + + [Test] + [Ignore("Only validating compilation of examples")] + public async Task Example_CertificateProfileOperations_GetSigningStatus_AllParameters_Convenience_Async() + { + TokenCredential credential = new DefaultAzureCredential(); + CertificateProfile client = new SigningClient("", credential).GetCertificateProfileClient(apiVersion: "2023-06-15-preview"); + + Response response = await client.GetSigningStatusAsync("", "", ""); + } + + [Test] + [Ignore("Only validating compilation of examples")] + public void Example_CertificateProfileOperations_GetSignRootCertificate_ShortVersion() + { + TokenCredential credential = new DefaultAzureCredential(); + CertificateProfile client = new SigningClient("", credential).GetCertificateProfileClient(apiVersion: "2023-06-15-preview"); + + Response response = client.GetSignRootCertificate("", "", null); + + JsonElement result = JsonDocument.Parse(response.ContentStream).RootElement; + Console.WriteLine(result.ToString()); + } + + [Test] + [Ignore("Only validating compilation of examples")] + public async Task Example_CertificateProfileOperations_GetSignRootCertificate_ShortVersion_Async() + { + TokenCredential credential = new DefaultAzureCredential(); + CertificateProfile client = new SigningClient("", credential).GetCertificateProfileClient(apiVersion: "2023-06-15-preview"); + + Response response = await client.GetSignRootCertificateAsync("", "", null); + + JsonElement result = JsonDocument.Parse(response.ContentStream).RootElement; + Console.WriteLine(result.ToString()); + } + + [Test] + [Ignore("Only validating compilation of examples")] + public void Example_CertificateProfileOperations_GetSignRootCertificate_ShortVersion_Convenience() + { + TokenCredential credential = new DefaultAzureCredential(); + CertificateProfile client = new SigningClient("", credential).GetCertificateProfileClient(apiVersion: "2023-06-15-preview"); + + Response response = client.GetSignRootCertificate("", ""); + } + + [Test] + [Ignore("Only validating compilation of examples")] + public async Task Example_CertificateProfileOperations_GetSignRootCertificate_ShortVersion_Convenience_Async() + { + TokenCredential credential = new DefaultAzureCredential(); + CertificateProfile client = new SigningClient("", credential).GetCertificateProfileClient(apiVersion: "2023-06-15-preview"); + + Response response = await client.GetSignRootCertificateAsync("", ""); + } + + [Test] + [Ignore("Only validating compilation of examples")] + public void Example_CertificateProfileOperations_GetSignRootCertificate_AllParameters() + { + TokenCredential credential = new DefaultAzureCredential(); + CertificateProfile client = new SigningClient("", credential).GetCertificateProfileClient(apiVersion: "2023-06-15-preview"); + + Response response = client.GetSignRootCertificate("", "", null); + + JsonElement result = JsonDocument.Parse(response.ContentStream).RootElement; + Console.WriteLine(result.ToString()); + } + + [Test] + [Ignore("Only validating compilation of examples")] + public async Task Example_CertificateProfileOperations_GetSignRootCertificate_AllParameters_Async() + { + TokenCredential credential = new DefaultAzureCredential(); + CertificateProfile client = new SigningClient("", credential).GetCertificateProfileClient(apiVersion: "2023-06-15-preview"); + + Response response = await client.GetSignRootCertificateAsync("", "", null); + + JsonElement result = JsonDocument.Parse(response.ContentStream).RootElement; + Console.WriteLine(result.ToString()); + } + + [Test] + [Ignore("Only validating compilation of examples")] + public void Example_CertificateProfileOperations_GetSignRootCertificate_AllParameters_Convenience() + { + TokenCredential credential = new DefaultAzureCredential(); + CertificateProfile client = new SigningClient("", credential).GetCertificateProfileClient(apiVersion: "2023-06-15-preview"); + + Response response = client.GetSignRootCertificate("", ""); + } + + [Test] + [Ignore("Only validating compilation of examples")] + public async Task Example_CertificateProfileOperations_GetSignRootCertificate_AllParameters_Convenience_Async() + { + TokenCredential credential = new DefaultAzureCredential(); + CertificateProfile client = new SigningClient("", credential).GetCertificateProfileClient(apiVersion: "2023-06-15-preview"); + + Response response = await client.GetSignRootCertificateAsync("", ""); + } + + [Test] + [Ignore("Only validating compilation of examples")] + public void Example_ExtendedKeyUsage_GetExtendedKeyUsages_ShortVersion() + { + TokenCredential credential = new DefaultAzureCredential(); + CertificateProfile client = new SigningClient("", credential).GetCertificateProfileClient(apiVersion: "2023-06-15-preview"); + + foreach (BinaryData item in client.GetExtendedKeyUsages("", "", null)) + { + JsonElement result = JsonDocument.Parse(item.ToStream()).RootElement; + Console.WriteLine(result.GetProperty("eku").ToString()); + } + } + + [Test] + [Ignore("Only validating compilation of examples")] + public async Task Example_ExtendedKeyUsage_GetExtendedKeyUsages_ShortVersion_Async() + { + TokenCredential credential = new DefaultAzureCredential(); + CertificateProfile client = new SigningClient("", credential).GetCertificateProfileClient(apiVersion: "2023-06-15-preview"); + + await foreach (BinaryData item in client.GetExtendedKeyUsagesAsync("", "", null)) + { + JsonElement result = JsonDocument.Parse(item.ToStream()).RootElement; + Console.WriteLine(result.GetProperty("eku").ToString()); + } + } + + [Test] + [Ignore("Only validating compilation of examples")] + public void Example_ExtendedKeyUsage_GetExtendedKeyUsages_ShortVersion_Convenience() + { + TokenCredential credential = new DefaultAzureCredential(); + CertificateProfile client = new SigningClient("", credential).GetCertificateProfileClient(apiVersion: "2023-06-15-preview"); + + foreach (ExtendedKeyUsage item in client.GetExtendedKeyUsages("", "")) + { + } + } + + [Test] + [Ignore("Only validating compilation of examples")] + public async Task Example_ExtendedKeyUsage_GetExtendedKeyUsages_ShortVersion_Convenience_Async() + { + TokenCredential credential = new DefaultAzureCredential(); + CertificateProfile client = new SigningClient("", credential).GetCertificateProfileClient(apiVersion: "2023-06-15-preview"); + + await foreach (ExtendedKeyUsage item in client.GetExtendedKeyUsagesAsync("", "")) + { + } + } + + [Test] + [Ignore("Only validating compilation of examples")] + public void Example_ExtendedKeyUsage_GetExtendedKeyUsages_AllParameters() + { + TokenCredential credential = new DefaultAzureCredential(); + CertificateProfile client = new SigningClient("", credential).GetCertificateProfileClient(apiVersion: "2023-06-15-preview"); + + foreach (BinaryData item in client.GetExtendedKeyUsages("", "", null)) + { + JsonElement result = JsonDocument.Parse(item.ToStream()).RootElement; + Console.WriteLine(result.GetProperty("eku").ToString()); + } + } + + [Test] + [Ignore("Only validating compilation of examples")] + public async Task Example_ExtendedKeyUsage_GetExtendedKeyUsages_AllParameters_Async() + { + TokenCredential credential = new DefaultAzureCredential(); + CertificateProfile client = new SigningClient("", credential).GetCertificateProfileClient(apiVersion: "2023-06-15-preview"); + + await foreach (BinaryData item in client.GetExtendedKeyUsagesAsync("", "", null)) + { + JsonElement result = JsonDocument.Parse(item.ToStream()).RootElement; + Console.WriteLine(result.GetProperty("eku").ToString()); + } + } + + [Test] + [Ignore("Only validating compilation of examples")] + public void Example_ExtendedKeyUsage_GetExtendedKeyUsages_AllParameters_Convenience() + { + TokenCredential credential = new DefaultAzureCredential(); + CertificateProfile client = new SigningClient("", credential).GetCertificateProfileClient(apiVersion: "2023-06-15-preview"); + + foreach (ExtendedKeyUsage item in client.GetExtendedKeyUsages("", "")) + { + } + } + + [Test] + [Ignore("Only validating compilation of examples")] + public async Task Example_ExtendedKeyUsage_GetExtendedKeyUsages_AllParameters_Convenience_Async() + { + TokenCredential credential = new DefaultAzureCredential(); + CertificateProfile client = new SigningClient("", credential).GetCertificateProfileClient(apiVersion: "2023-06-15-preview"); + + await foreach (ExtendedKeyUsage item in client.GetExtendedKeyUsagesAsync("", "")) + { + } + } + + [Test] + [Ignore("Only validating compilation of examples")] + public void Example_CertificateProfileOperations_Sign_ShortVersion() + { + TokenCredential credential = new DefaultAzureCredential(); + CertificateProfile client = new SigningClient("", credential).GetCertificateProfileClient(apiVersion: "2023-06-15-preview"); + + using RequestContent content = RequestContent.Create(new + { + signatureAlgorithm = "RS256", + digest = new object(), + }); + Operation operation = client.Sign(WaitUntil.Completed, "", "", content); + BinaryData responseData = operation.Value; + + JsonElement result = JsonDocument.Parse(responseData.ToStream()).RootElement; + Console.WriteLine(result.ToString()); + } + + [Test] + [Ignore("Only validating compilation of examples")] + public async Task Example_CertificateProfileOperations_Sign_ShortVersion_Async() + { + TokenCredential credential = new DefaultAzureCredential(); + CertificateProfile client = new SigningClient("", credential).GetCertificateProfileClient(apiVersion: "2023-06-15-preview"); + + using RequestContent content = RequestContent.Create(new + { + signatureAlgorithm = "RS256", + digest = new object(), + }); + Operation operation = await client.SignAsync(WaitUntil.Completed, "", "", content); + BinaryData responseData = operation.Value; + + JsonElement result = JsonDocument.Parse(responseData.ToStream()).RootElement; + Console.WriteLine(result.ToString()); + } + + [Test] + [Ignore("Only validating compilation of examples")] + public void Example_CertificateProfileOperations_Sign_ShortVersion_Convenience() + { + TokenCredential credential = new DefaultAzureCredential(); + CertificateProfile client = new SigningClient("", credential).GetCertificateProfileClient(apiVersion: "2023-06-15-preview"); + + Operation operation = client.Sign(WaitUntil.Completed, "", "", SignatureAlgorithm.RS256, BinaryData.FromObjectAsJson(new object())); + SignResult responseData = operation.Value; + } + + [Test] + [Ignore("Only validating compilation of examples")] + public async Task Example_CertificateProfileOperations_Sign_ShortVersion_Convenience_Async() + { + TokenCredential credential = new DefaultAzureCredential(); + CertificateProfile client = new SigningClient("", credential).GetCertificateProfileClient(apiVersion: "2023-06-15-preview"); + + Operation operation = await client.SignAsync(WaitUntil.Completed, "", "", SignatureAlgorithm.RS256, BinaryData.FromObjectAsJson(new object())); + SignResult responseData = operation.Value; + } + + [Test] + [Ignore("Only validating compilation of examples")] + public void Example_CertificateProfileOperations_Sign_AllParameters() + { + TokenCredential credential = new DefaultAzureCredential(); + CertificateProfile client = new SigningClient("", credential).GetCertificateProfileClient(apiVersion: "2023-06-15-preview"); + + using RequestContent content = RequestContent.Create(new + { + signatureAlgorithm = "RS256", + digest = new object(), + fileHashList = new object[] + { +new object() + }, + authenticodeHashList = new object[] + { +new object() + }, + }); + Operation operation = client.Sign(WaitUntil.Completed, "", "", content, clientVersion: "", xCorrelationId: ""); + BinaryData responseData = operation.Value; + + JsonElement result = JsonDocument.Parse(responseData.ToStream()).RootElement; + Console.WriteLine(result.GetProperty("signature").ToString()); + Console.WriteLine(result.GetProperty("signingCertificate").ToString()); + } + + [Test] + [Ignore("Only validating compilation of examples")] + public async Task Example_CertificateProfileOperations_Sign_AllParameters_Async() + { + TokenCredential credential = new DefaultAzureCredential(); + CertificateProfile client = new SigningClient("", credential).GetCertificateProfileClient(apiVersion: "2023-06-15-preview"); + + using RequestContent content = RequestContent.Create(new + { + signatureAlgorithm = "RS256", + digest = new object(), + fileHashList = new object[] + { +new object() + }, + authenticodeHashList = new object[] + { +new object() + }, + }); + Operation operation = await client.SignAsync(WaitUntil.Completed, "", "", content, clientVersion: "", xCorrelationId: ""); + BinaryData responseData = operation.Value; + + JsonElement result = JsonDocument.Parse(responseData.ToStream()).RootElement; + Console.WriteLine(result.GetProperty("signature").ToString()); + Console.WriteLine(result.GetProperty("signingCertificate").ToString()); + } + + [Test] + [Ignore("Only validating compilation of examples")] + public void Example_CertificateProfileOperations_Sign_AllParameters_Convenience() + { + TokenCredential credential = new DefaultAzureCredential(); + CertificateProfile client = new SigningClient("", credential).GetCertificateProfileClient(apiVersion: "2023-06-15-preview"); + + Operation operation = client.Sign(WaitUntil.Completed, "", "", SignatureAlgorithm.RS256, BinaryData.FromObjectAsJson(new object()), fileHashList: new BinaryData[] + { +BinaryData.FromObjectAsJson(new object()) + }, authenticodeHashList: new BinaryData[] + { +BinaryData.FromObjectAsJson(new object()) + }, clientVersion: "", xCorrelationId: ""); + SignResult responseData = operation.Value; + } + + [Test] + [Ignore("Only validating compilation of examples")] + public async Task Example_CertificateProfileOperations_Sign_AllParameters_Convenience_Async() + { + TokenCredential credential = new DefaultAzureCredential(); + CertificateProfile client = new SigningClient("", credential).GetCertificateProfileClient(apiVersion: "2023-06-15-preview"); + + Operation operation = await client.SignAsync(WaitUntil.Completed, "", "", SignatureAlgorithm.RS256, BinaryData.FromObjectAsJson(new object()), fileHashList: new BinaryData[] + { +BinaryData.FromObjectAsJson(new object()) + }, authenticodeHashList: new BinaryData[] + { +BinaryData.FromObjectAsJson(new object()) + }, clientVersion: "", xCorrelationId: ""); + SignResult responseData = operation.Value; + } + } +} diff --git a/sdk/trustedsigning/Azure.Developer.Signing/tests/Samples/README.md b/sdk/trustedsigning/Azure.Developer.Signing/tests/Samples/README.md new file mode 100644 index 000000000000..2e596b120c94 --- /dev/null +++ b/sdk/trustedsigning/Azure.Developer.Signing/tests/Samples/README.md @@ -0,0 +1,3 @@ +Source files in this directory are written as tests from which samples are extracted. +They are not intended to be viewed directly and help ensure our samples compile and work correctly. +See our [list of samples](https://github.com/Azure/azure-sdk-for-net/tree/main/sdk/trustedsigning/Azure.Developer.Signing/samples) for more explanation about how to use this client library. diff --git a/sdk/trustedsigning/Azure.Developer.Signing/tests/Samples/Sample_CreateCertificateProfileClient.cs b/sdk/trustedsigning/Azure.Developer.Signing/tests/Samples/Sample_CreateCertificateProfileClient.cs new file mode 100644 index 000000000000..069599728953 --- /dev/null +++ b/sdk/trustedsigning/Azure.Developer.Signing/tests/Samples/Sample_CreateCertificateProfileClient.cs @@ -0,0 +1,23 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using Azure.Core.TestFramework; +using NUnit.Framework; + +namespace Azure.Developer.Signing.Tests.Samples +{ + public partial class DeveloperSigningSample : SamplesBase + { + [Test] + public void CreateClients(string region) + { + #region Snippet:Azure_Developer_Signing_CreateCertificateProfileClient + + var credential = new DefaultAzureCredential(); + CertificateProfile certificateProfileClient = new SigningClient(region, credential).GetCertificateProfileClient(); + + #endregion Snippet:Azure_Developer_Signing_CreateCertificateProfileClient + } + } +} diff --git a/sdk/trustedsigning/Azure.Developer.Signing/tests/Samples/Sample_GetCustomerEku.cs b/sdk/trustedsigning/Azure.Developer.Signing/tests/Samples/Sample_GetCustomerEku.cs new file mode 100644 index 000000000000..6ea02c4c7e87 --- /dev/null +++ b/sdk/trustedsigning/Azure.Developer.Signing/tests/Samples/Sample_GetCustomerEku.cs @@ -0,0 +1,37 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.Text.Json; +using Azure.Core.TestFramework; +using NUnit.Framework; + +namespace Azure.Developer.Signing.Tests.Samples +{ + public partial class Sample_GetCustomerEku : SamplesBase + { + [Test] + public void GetExtendedKeyUsages() + { + string accountName = TestEnvironment.AccountName; + string profileName = TestEnvironment.ProfileName; + string region = TestEnvironment.Region; + var credential = new DefaultAzureCredential(); + + #region Snippet:Azure_Developer_Signing_GetExtendedKeyUsages + CertificateProfile certificateProfileClient = new SigningClient(region, credential).GetCertificateProfileClient(); + + List ekus = new(); + + foreach (BinaryData item in certificateProfileClient.GetExtendedKeyUsages(accountName, profileName, null)) + { + JsonElement result = JsonDocument.Parse(item.ToStream()).RootElement; + string eku = result.GetProperty("eku").ToString(); + + ekus.Add(eku); + } + #endregion Snippet:Azure_Developer_Signing_GetExtendedKeyUsages + } + } +} diff --git a/sdk/trustedsigning/Azure.Developer.Signing/tests/Samples/Sample_GetSignRootCertificate.cs b/sdk/trustedsigning/Azure.Developer.Signing/tests/Samples/Sample_GetSignRootCertificate.cs new file mode 100644 index 000000000000..74896e27cf74 --- /dev/null +++ b/sdk/trustedsigning/Azure.Developer.Signing/tests/Samples/Sample_GetSignRootCertificate.cs @@ -0,0 +1,29 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using Azure.Core.TestFramework; +using NUnit.Framework; + +namespace Azure.Developer.Signing.Tests.Samples +{ + public partial class Sample_GetSignRootCertificate : SamplesBase + { + [Test] + public void GetSignRootCertificate() + { + string accountName = TestEnvironment.AccountName; + string profileName = TestEnvironment.ProfileName; + string region = TestEnvironment.Region; + var credential = new DefaultAzureCredential(); + + #region Snippet:Azure_Developer_Signing_GetSignRootCertificate + CertificateProfile certificateProfileClient = new SigningClient(region, credential).GetCertificateProfileClient(); + + Response response = certificateProfileClient.GetSignRootCertificate(accountName, profileName); + + byte[] rootCertificate = response.Value.ToArray(); + #endregion Snippet:Azure_Developer_Signing_GetSignRootCertificate + } + } +} diff --git a/sdk/trustedsigning/Azure.Developer.Signing/tests/Samples/Sample_SignBytes.cs b/sdk/trustedsigning/Azure.Developer.Signing/tests/Samples/Sample_SignBytes.cs new file mode 100644 index 000000000000..7becc72f0c42 --- /dev/null +++ b/sdk/trustedsigning/Azure.Developer.Signing/tests/Samples/Sample_SignBytes.cs @@ -0,0 +1,44 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Text.Json; +using Azure.Core; +using Azure.Core.TestFramework; +using NUnit.Framework; + +namespace Azure.Developer.Signing.Tests.Samples +{ + public partial class Sample_SignBytes : SamplesBase + { + [Test] + public void SignBytes() + { + string accountName = TestEnvironment.AccountName; + string profileName = TestEnvironment.ProfileName; + string region = TestEnvironment.Region; + var credential = new DefaultAzureCredential(); + + const string signatureAlgorithm = "RS256"; + + byte[] digest = new byte[32]; + var random = new Random(); + random.NextBytes(digest); + + #region Snippet:Azure_Developer_Signing_SigningBytes + CertificateProfile certificateProfileClient = new SigningClient(region, credential).GetCertificateProfileClient(); + + using RequestContent content = RequestContent.Create(new + { + signatureAlgorithm, + digest, + }); + + Operation operation = certificateProfileClient.Sign(WaitUntil.Completed, accountName, profileName, content); + BinaryData responseData = operation.Value; + + JsonElement result = JsonDocument.Parse(responseData.ToStream()).RootElement; + #endregion Snippet:Azure_Developer_Signing_SigningBytes + } + } +} diff --git a/sdk/trustedsigning/Azure.Developer.Signing/tsp-location.yaml b/sdk/trustedsigning/Azure.Developer.Signing/tsp-location.yaml new file mode 100644 index 000000000000..6e69b1f39fa7 --- /dev/null +++ b/sdk/trustedsigning/Azure.Developer.Signing/tsp-location.yaml @@ -0,0 +1,5 @@ +commit: 4b78e28e66c0514d14c0fcf68ca2593f489c1c69 +additionalDirectories: [] +directory: specification/developersigning/DeveloperSigning +repo: Azure/azure-rest-api-specs + diff --git a/sdk/trustedsigning/ci.yml b/sdk/trustedsigning/ci.yml new file mode 100644 index 000000000000..6d667c8cc257 --- /dev/null +++ b/sdk/trustedsigning/ci.yml @@ -0,0 +1,35 @@ +# NOTE: Please refer to https://aka.ms/azsdk/engsys/ci-yaml before editing this file. + +trigger: + branches: + include: + - main + - hotfix/* + - release/* + paths: + include: + - sdk/trustedsigning + - sdk/trustedsigning/ci.yml + - sdk/trustedsigning/Azure.Developer.Signing + +pr: + branches: + include: + - main + - feature/* + - hotfix/* + - release/* + paths: + include: + - sdk/trustedsigning + - sdk/trustedsigning/ci.yml + - sdk/trustedsigning/Azure.Developer.Signing + +extends: + template: /eng/pipelines/templates/stages/archetype-sdk-client.yml + parameters: + ServiceDirectory: trustedsigning + ArtifactName: packages + Artifacts: + - name: Azure.Developer.Signing + safeName: AzureDeveloperSigning diff --git a/sdk/trustedsigning/test-resources.bicep b/sdk/trustedsigning/test-resources.bicep new file mode 100644 index 000000000000..13bd0de0c128 --- /dev/null +++ b/sdk/trustedsigning/test-resources.bicep @@ -0,0 +1,59 @@ +param location string = az.resourceGroup().location + +@description('A signing account name to provision.') +@minLength(3) +@maxLength(15) +param accountName string = uniqueString(az.resourceGroup().id) + +@description('A certificate profile to provision.') +@minLength(3) +@maxLength(15) +param profileName string = uniqueString(az.resourceGroup().id) + +@description('The identity validation id to be use for the certificate profile provisioning.') +param identityValidationId string = 'f0bde931-daf1-497b-a4fa-789a4d9fc6c0' + +//Short name regions +var shortLocation = { + eastus: 'eus' + centraluseuap: 'scus' + northeurope: 'neu' + westcentralus: 'wcus' + westeurope: 'weu' + westus: 'wus' + westus2: 'wus2' +} + +@description('Profile type for the certificate profile creation.') +@allowed([ + 'PublicTrust' + 'PrivateTrust' + 'PrivateTrustCIPolicy' + 'PublicTrustTest' + 'VBSEnclave' +]) +param profileType string = 'PublicTrustTest' + +resource account 'Microsoft.CodeSigning/codeSigningAccounts@2024-02-05-preview' = { + location: location + name: accountName + properties: { + sku: { + name: 'Basic' + } + } +} + +resource profile 'Microsoft.CodeSigning/codeSigningAccounts/certificateProfiles@2024-02-05-preview' = { + parent: account + name: profileName + properties: { + profileType: profileType + identityValidationId: identityValidationId + } +} + +output DEVSIGNING_REGION string = shortLocation[toLower(replace(location, ' ', ''))] +output DEVSIGNING_ACCOUNT_NAME string = account.name +output DEVSIGNING_PROFILE_NAME string = profile.name +output DEVSIGNING_ENDPOINT string = account.properties.accountUri diff --git a/sdk/trustedsigning/tests.yml b/sdk/trustedsigning/tests.yml new file mode 100644 index 000000000000..1033641b598f --- /dev/null +++ b/sdk/trustedsigning/tests.yml @@ -0,0 +1,8 @@ +trigger: none + +extends: + template: ../../eng/pipelines/templates/stages/archetype-sdk-tests.yml + parameters: + SDKType: client + ServiceDirectory: trustedsigning + Location: westeurope \ No newline at end of file