Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Key Vault] TypeSpec for Security Domain library #31060

Open
wants to merge 9 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are these files ending in "-sdk"? They are for the service which we don't consider an "SDK" typically. Can't it just be "securitydomain.json"? This also matches what service swaggers are now for Key Vault, and what all the other TSPs should be doing.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added -sdk for this and the other conversions' swaggers because it's not totally aligned with the original swaggers. In this case, the Security Domain spec is constructed from common.json and securitydomain.json, so the swagger generated from it is the combination of those two

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that's fine. common.json was also an implementation detail anyway and was just for humans to avoid duplication. Given we're emitting these swaggers, I don't see a need to differentiate. I worry that "sdk" will make orgs that want to generate their own clients (from swagger) think these aren't the service specs.

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import "@azure-tools/typespec-client-generator-core";
import "@typespec/rest";
import "@typespec/http";
import "@typespec/versioning";
import "./main.tsp";

using Azure.ClientGenerator.Core;
using KeyVault;

@TypeSpec.Versioning.useDependency(Azure.Core.Versions.v1_0_Preview_2)
@TypeSpec.Versioning.useDependency(KeyVault.Versions.`v7.5`)
namespace ClientCustomizations;

@client({
name: "SecurityDomainClient",
service: KeyVault,
})
interface SecurityDomainClient {
#suppress "@azure-tools/typespec-azure-core/use-standard-operations" "Foundations.Operation necessary for Key Vault"
getDownloadStatus is HsmSecurityDomain.downloadPending;
#suppress "@azure-tools/typespec-azure-core/use-standard-operations" "Foundations.Operation necessary for Key Vault"
download is HsmSecurityDomain.download;
#suppress "@azure-tools/typespec-azure-core/use-standard-operations" "Foundations.Operation necessary for Key Vault"
getUploadStatus is HsmSecurityDomain.uploadPending;
#suppress "@azure-tools/typespec-azure-core/use-standard-operations" "Foundations.Operation necessary for Key Vault"
upload is HsmSecurityDomain.upload;
#suppress "@azure-tools/typespec-azure-core/use-standard-operations" "Foundations.Operation necessary for Key Vault"
getTransferKey is HsmSecurityDomain.transferKey;
}

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"parameters": {
"vaultBaseUrl": "https://myvault.vault.azure.net/",
"api-version": "7.5"
},
"responses": {
"200": {
"body": {
"status": "InProgress",
"status_details": ""
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"parameters": {
"vaultBaseUrl": "https://myvault.vault.azure.net/",
"api-version": "7.5"
},
"responses": {
"200": {
"body": {
"key_format": "jwk",
"transfer_key": {
"kid": "https://myvault.vault.azure.net/transfer_key",
"kty": "RSA",
"key_ops": [
"encrypt"
],
"n": "2HJAE5fU3Cw2Rt9hEuq-F6XjINKGa-zskfISVqopqUy60GOs2eyhxbWbJBeUXNor_gf-tXtNeuqeBgitLeVa640UDvnEjYTKWjCniTxZRaU7ewY8BfTSk-7KxoDdLsPSpX_MX4rwlAx-_1UGk5t4sQgTbm9T6Fm2oqFd37dsz5-Gj27UP2GTAShfJPFD7MqU_zIgOI0pfqsbNL5xTQVM29K6rX4jSPtylZV3uWJtkoQIQnrIHhk1d0SC0KwlBV3V7R_LVYjiXLyIXsFzSNYgQ68ZjAwt8iL7I8Osa-ehQLM13DVvLASaf7Jnu3sC3CWl3Gyirgded6cfMmswJzY87w",
"e": "AQAB",
"alg": "RSA-OAEP-256",
"x5c": [
"MIIEnTCCBAgIBATANBgkAoWgAwIqhkiG9w0BAQsFADAQMQ4wDAYDVQQDDAVjZXJ0QTAeFw0yMDA0MjYwM/mivTQ26aDwb1Pd8h+SGcgJNy1VOnmI5+uvgfh9Qj6glJZHEyvh6dat6f4DDTwRVf6Vvc5noB/yiilaMj1GPW0Bwg5u5atZcjzTb6wOFYOGd2Y1WFBwQqqxriWo62Fp/TO5+kQigYkgVZXcPjbm2c0hdkisPt+APqEdMotmYTANxtC6McP+9KOO8+12K2fj2a9NEhRJOboGQeZ0M7DJoQDl4wg8f2nswxH/36Vfc5ad+nxRYwYObRYfgOh8vpYaw3cpj5+UHBaPQ8ZiQNDoWHJWvX5z1nTmCc2NmLHdi3ijkoc7AKHIv/ZX7qbNhv11a76gJRi/IoHkcf1UTpxCoD+eTbo8Isxt4c9fBTk1vS4wSGsJCewxcyMlTB9FHufPM8k5Uz/ZCOrc+RoaznKPGamgMJOOwbPE1WcBnxuG4rQcskdCa59NiZXyZsx5vsCAwEAAaMCMAAwDQYJKoZIhvcNAQELBQADggIBAAjHy9GCPejDYIVb/iv8Wo40n317LQN7H6ay+YB5L2byEQATvC1ixde6VqwU6k9VdoQOTfP3xJhfstKrO+n5mFJBL4KG8BZBbd6XQu/ggPLKEIVZFbeQkX6o03K54gY8GxYjHr6gF12I6heLWVKA/Qi480GqSlp2Nz+LE1jgPp9u52xpUPjsvRHXtxYZ7Q3O2jhPToNr3D/TZSu3tmQOeqj9M/igLDe9TxqN9C9jraUGR7Lr4zN1srtvIKhxGMS3Q9kC4Mq+ZNNIwC9+jzzd8fB2pGJP/iTFDzB0pDh9Jz0/CR4O4aGoYqkQEx629aZH2TzhOh2yf04TaniwkHXnUEsPTxrpY8ty/OUG3HzBMHCDhS08ZSimrrxhiWyH6g0OEglXVGrI2nH6nnQIn1MTNILcjUTMRt/WSOz6G07oZciAouKD2YS/W1qPap600kGhTya81BuYThGmFoXVMs7Mk3XBzZ81b6hJ6ncwCLb3g4YzqeQ8bOf42jYJctq4tPNaXTfoC7N0FX7lPVJpRdh6BFcHYcg0NPWJsdk6LtSJB6bp2qptRAgJ5S94s843FRd8PRFE10TKDfj3YFRBNkx7qDjwUhtN8/JC9+RHHw0Ngd0x2/BLqeCEMAQaJoC53h0aMLW6PSyovnsLvdJbN/rYc15qUXSz8TtjaHFpjsy/Fo5H"
],
"x5t": "dJKBile6IJDrRGqa3k5d8_IKFdI",
"x5t#S256": "gIBQCTDDN"
}
}
}
}
}

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/**
* PLEASE DO NOT REMOVE - USED FOR CONVERTER METRICS
* Generated by package: @autorest/openapi-to-typespec
* Version: 0.10.0
* Date: 2024-10-02T23:18:13.583Z
*/
import "@typespec/rest";
import "@typespec/http";
import "./routes.tsp";

using TypeSpec.Rest;
using TypeSpec.Http;
using TypeSpec.Versioning;

/**
* The key vault client performs cryptographic key operations and vault operations
* against the Key Vault service.
*/
@useAuth(
OAuth2Auth<[
{
type: OAuth2FlowType.implicit,
authorizationUrl: "https://login.microsoftonline.com/common/oauth2/authorize",
scopes: ["https://vault.azure.net/.default"],
}
]>
)
@service({
title: "Key Vault",
})
@versioned(Versions)
@server(
"{vaultBaseUrl}",
"The key vault client performs cryptographic key operations and vault operations against the Key Vault service.",
{
vaultBaseUrl: url,
}
)
namespace KeyVault;

/**
* The available API versions.
*/
enum Versions {
/**
* The 7.5 API version.
*/
@useDependency(Azure.Core.Versions.v1_0_Preview_2)
`v7.5`: "7.5",
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,226 @@
import "@azure-tools/typespec-azure-core";
import "@typespec/rest";
import "@typespec/http";

using Azure.Core;
using TypeSpec.Rest;
using TypeSpec.Http;

namespace KeyVault;

/**
* Operation status.
*/
@lroStatus
union OperationStatus {
string,

/** The operation succeeded. */
@lroSucceeded
Success: "Success", // The correct response should be "Succeeded", but this has already shipped.

/** The operation is in progress. */
InProgress: "InProgress",

/** The operation failed. */
@lroFailed
Failed: "Failed",
}

/**
* The Security Domain operation status.
*/
model SecurityDomainOperationStatus {
/**
* Operation status.
*/
status?: OperationStatus;

/**
* Details of the operation status.
*/
@encodedName("application/json", "status_details")
statusDetails?: string;
}

/**
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These appear to be normal Azure Core errors. Can't we use those instead of redefining?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Key Vault error is a little different in its definition, but I do think it's functionally equivalent to the Azure Core error. If I'm not mistaken, KV's custom error has an additional innerError property.

* The key vault error exception.
*/
@error
model KeyVaultError {
/**
* The key vault server error.
*/
@visibility("read")
error?: Error;
}

/**
* The key vault server error.
*/
model Error {
/**
* The error code.
*/
@visibility("read")
code?: string;

/**
* The error message.
*/
@visibility("read")
message?: string;

/**
* The key vault server error.
*/
@visibility("read")
@encodedName("application/json", "innererror")
innerError?: Error;
}

/**
* The Security Domain download operation requires customer to provide N certificates (minimum 3 and maximum 10)
* containing a public key in JWK format.
*/
model CertificateInfoObject {
/**
* Certificates needed from customer.
*/
@maxItems(10)
@minItems(3)
certificates: SecurityDomainJsonWebKey[]; // TODO: These need to be unique items

/**
* Customer to specify the number of certificates (minimum 2 and maximum 10) to restore Security Domain.
*/
@maxValue(10)
@minValue(2)
required?: int32 = 2;
}

/**
* A JSON Web Key (JWK) for use in a security domain operation.
*/
model SecurityDomainJsonWebKey {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: seems we should be defining common types like JWKs in a common tsp further up. I won't block on this, but we should consider it. We don't want JWKs - an industry standard - diverging accidentally or incidentally.

/**
* Key identifier.
*/
kid: string;

/**
* JsonWebKey Key Type (kty), as defined in
* https://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-40. For
* Security Domain this value must be RSA.
*/
kty: string;

/**
* Supported key operations.
*/
@encodedName("application/json", "key_ops")
keyOps: string[];

/**
* RSA modulus.
*/
n: string;

/**
* RSA public exponent.
*/
e: string;

/**
* X509 certificate chain parameter.
*/
@encodedName("application/json", "x5c")
x5C: string[];

/**
* Public Key Use Parameter. This is optional and if present must be enc.
*/
use?: string;

/**
* X509 certificate SHA1 thumbprint. This is optional.
*/
@encodedName("application/json", "x5t")
x5T?: string;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems this should be x5t just as it is below (x5tS256). That's the industry standard anyway, and won't impact casing rules in client emitters anyway...or shouldn't, anyway.


/**
* X509 certificate SHA256 thumbprint.
*/
@encodedName("application/json", "x5t#S256")
x5tS256: string;

/**
* Algorithm intended for use with the key.
*/
alg: string;
}

/**
* The Security Domain.
*/
model SecurityDomainObject {
/**
* The Security Domain.
*/
value: string;
}

/**
* Security Domain transfer key.
*/
model TransferKey {
/**
* Specifies the format of the transfer key.
*/
@encodedName("application/json", "key_format")
keyFormat?: string = "jwk";

/**
* Specifies the transfer key in JWK format.
*/
@encodedName("application/json", "transfer_key")
transferKeyJwk: SecurityDomainJsonWebKey;
}

/**
* The object attributes managed by the KeyVault service.
*/
model Attributes {
/**
* Determines whether the object is enabled.
*/
enabled?: boolean;

/**
* Not before date in UTC.
*/
@encodedName("application/json", "nbf")
@encode("unixTimestamp", int32)
notBefore?: utcDateTime;

/**
* Expiry date in UTC.
*/
@encodedName("application/json", "exp")
@encode("unixTimestamp", int32)
expires?: utcDateTime;

/**
* Creation time in UTC.
*/
@visibility("read")
@encode("unixTimestamp", int32)
created?: utcDateTime;

/**
* Last updated time in UTC.
*/
@visibility("read")
@encode("unixTimestamp", int32)
updated?: utcDateTime;
}
Loading
Loading