diff --git a/.gitignore b/.gitignore index 13f279f4bc95..14ccc9c20822 100644 --- a/.gitignore +++ b/.gitignore @@ -48,3 +48,5 @@ p-examples/ .mono go.work* *.sln + +**/.claude/settings.local.json diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 000000000000..69cfdf730e51 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,160 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## Repository Overview + +This repository contains the Pulumi Azure Native provider, which enables Pulumi users to manage Azure resources using TypeScript, Python, Go, .NET, and Java. The provider directly calls the Azure Resource Manager (ARM) REST API, providing comprehensive coverage of Azure services. + +## Build and Development Commands + +### Setup and Dependencies + +- **Dependencies**: + - Go 1.21+ + - NodeJS 18.X.X+ + - Python 3.10+ + - .NET 6+ + - Gradle 8+ + +### Core Build Commands + +```bash +# Full build (generate schema, SDKs, and build the provider) +make + +# Generate schema only +make schema + +# Regenerate schema and update docs +make generate_schema generate_docs + +# Generate SDKs for all languages +make generate + +# Build the provider binary +make provider + +# Install the provider locally (used for testing) +make install_provider + +# Clean the build +make clean +``` + +### SDK Generation and Building + +```bash +# Generate SDKs for specific languages +make generate_java +make generate_nodejs +make generate_python +make generate_dotnet +make generate_go + +# Build SDKs for specific languages +make build_nodejs +make build_python +make build_dotnet +make build_java +make build_go +``` + +### Testing + +```bash +# Run all tests +make test + +# Run tests for specific languages +make test_dotnet +make test_python +make test_go +make test_nodejs + +# Run provider tests +make test_provider + +# Run specific test by name +make test TEST_NAME=TestXXX + +# Run specific test category +make test TEST_TAGS=nodejs +``` + +### Schema Management + +```bash +# Generate schema squeeze (for major version releases) +make schema_squeeze +``` + +## Code Architecture + +### Key Components + +1. **Azure Specifications**: The repository uses Azure's REST API specifications from the `azure-rest-api-specs` submodule. + +2. **Provider**: The core provider implementation is in `provider/pkg`, which handles: + - Authentication with Azure + - CRUD operations for resources + - Type conversions between Pulumi and Azure + - Handling of special cases and customizations + +3. **Code Generator**: The `pulumi-gen-azure-native` tool generates schemas and SDKs based on Azure's OpenAPI specifications. + +4. **SDKs**: Generated SDKs for multiple languages in the `sdk/` directory: + - TypeScript/JavaScript (`sdk/nodejs`) + - Python (`sdk/python`) + - .NET (`sdk/dotnet`) + - Go (`sdk/go`) + - Java (`sdk/java`) + +5. **Version Management**: The provider supports multiple API versions through configuration in the `versions/` directory: + - Each major version has its own configuration + - API versions are selectively included based on compatibility and features + +### Important Subsystems + +#### Sub-Resources + +The provider handles "sub-resource properties" specially. These are resources that can be defined inline with a parent resource or as standalone resources. The provider ensures that: +- On Create: Default values are set for unset sub-resource properties +- On Update: Existing sub-resources are preserved during updates +- On Read: Unset sub-resource properties are reset to empty values + +#### Custom Resources + +Some Azure resources require special handling beyond what can be generated from the OpenAPI specs. These custom implementations are in `provider/pkg/resources/customresources/`. + +## Development Workflow + +1. **Understanding API Versions**: Azure's REST API has many versions with ISO date format (e.g., `2020-01-01`). + - Not all versions contain all resources + - Preview versions (`-preview` suffix) are sometimes stable for everyday use + - The provider selectively includes versions to maintain compatibility + +2. **Making Changes**: + - For schema changes, modify files in `versions/` directory + - For provider behavior changes, modify files in `provider/pkg/` + - For custom resource implementations, modify files in `provider/pkg/resources/customresources/` + +3. **Testing Changes**: + - Run unit tests with `make test_provider` + - Test examples with `make test` or language-specific tests + +4. **Adding Resource Documentation**: + - Add documentation in `docs/resources/` folder + - File naming follows the pattern: `[module]-[Resource].md` (e.g., `sql-Server.md`) + - Regenerate docs with `make generate generate_docs` + +## Common Issues and Solutions + +1. **Schema Generation**: If schema generation fails, check that the Azure REST API specs submodule is properly initialized: + ```bash + git submodule update --init --recursive + ``` + +2. **Sub-resource Handling**: When troubleshooting issues with resources that contain sub-resources, check the implementation in `provider/pkg/provider/`. + +3. **Version Compatibility**: When adding support for new API versions, check for compatibility with existing versions in the `versions/` directory. \ No newline at end of file diff --git a/examples/cdn-custom-domain-https/Pulumi.yaml b/examples/cdn-custom-domain-https/Pulumi.yaml new file mode 100644 index 000000000000..025d62167fcd --- /dev/null +++ b/examples/cdn-custom-domain-https/Pulumi.yaml @@ -0,0 +1,3 @@ +name: cdn-custom-domain-https +runtime: nodejs +description: A Pulumi example demonstrating how to enable HTTPS on a CDN custom domain \ No newline at end of file diff --git a/examples/cdn-custom-domain-https/index.ts b/examples/cdn-custom-domain-https/index.ts new file mode 100644 index 000000000000..955c1bf44d6e --- /dev/null +++ b/examples/cdn-custom-domain-https/index.ts @@ -0,0 +1,52 @@ +import * as pulumi from "@pulumi/pulumi"; +import * as resources from "@pulumi/azure-native/resources"; +import * as cdn from "@pulumi/azure-native/cdn"; + +// Create a resource group +const resourceGroup = new resources.ResourceGroup("resourceGroup"); + +// Create a CDN profile +const cdnProfile = new cdn.Profile("cdnProfile", { + resourceGroupName: resourceGroup.name, + location: resourceGroup.location, + sku: { + name: "Standard_Microsoft", + }, +}); + +// Create a CDN endpoint +const cdnEndpoint = new cdn.Endpoint("cdnEndpoint", { + resourceGroupName: resourceGroup.name, + profileName: cdnProfile.name, + location: resourceGroup.location, + originHostHeader: "www.contoso.com", + origins: [{ + name: "contoso", + hostName: "www.contoso.com", + }], +}); + +// Create a custom domain +const customDomain = new cdn.CustomDomain("customDomain", { + resourceGroupName: resourceGroup.name, + profileName: cdnProfile.name, + endpointName: cdnEndpoint.name, + hostName: "cdn.contoso.com", +}); + +// Enable HTTPS on the custom domain using CDN-managed certificate +const customDomainHttps = new cdn.CustomDomainHttps("customDomainHttps", { + resourceGroupName: resourceGroup.name, + profileName: cdnProfile.name, + endpointName: cdnEndpoint.name, + customDomainName: customDomain.name, + httpsEnabled: true, + certificateSource: "Cdn", + protocolType: "ServerNameIndication", + certificateType: "Shared", + minimumTlsVersion: "TLS12", +}); + +// Export the custom domain name and HTTPS status +export const customDomainName = customDomain.name; +export const httpsEnabled = customDomainHttps.httpsEnabled; \ No newline at end of file diff --git a/examples/cdn-custom-domain-https/package.json b/examples/cdn-custom-domain-https/package.json new file mode 100644 index 000000000000..cbed0fd1620b --- /dev/null +++ b/examples/cdn-custom-domain-https/package.json @@ -0,0 +1,10 @@ +{ + "name": "cdn-custom-domain-https", + "devDependencies": { + "@types/node": "^10.0.0" + }, + "dependencies": { + "@pulumi/pulumi": "^3.0.0", + "@pulumi/azure-native": "^2.0.0" + } +} \ No newline at end of file diff --git a/examples/cdn-custom-domain-https/tsconfig.json b/examples/cdn-custom-domain-https/tsconfig.json new file mode 100644 index 000000000000..2d8048165621 --- /dev/null +++ b/examples/cdn-custom-domain-https/tsconfig.json @@ -0,0 +1,19 @@ +{ + "compilerOptions": { + "outDir": "bin", + "target": "es2016", + "module": "commonjs", + "moduleResolution": "node", + "sourceMap": true, + "experimentalDecorators": true, + "pretty": true, + "noFallthroughCasesInSwitch": true, + "noImplicitAny": true, + "noImplicitReturns": true, + "forceConsistentCasingInFileNames": true, + "strictNullChecks": true + }, + "files": [ + "index.ts" + ] +} \ No newline at end of file diff --git a/implementation_guide.md b/implementation_guide.md new file mode 100644 index 000000000000..82d667d5447e --- /dev/null +++ b/implementation_guide.md @@ -0,0 +1,499 @@ +# Implementation Guide: Enabling SSL on CDN Custom Domains + +## Problem + +Currently, the Pulumi Azure Native provider lacks the ability to enable HTTPS (SSL) on CDN custom domains. The Azure REST API supports this feature through the following endpoint: + +``` +POST /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Cdn/profiles/{profileName}/endpoints/{endpointName}/customDomains/{customDomainName}/enableCustomHttps +``` + +However, this functionality is not exposed in the Pulumi Azure Native SDK because it's a POST action rather than a standard resource property that can be set via PUT operations. + +## Solution Overview + +We need to implement a custom resource in the provider that will handle enabling and disabling HTTPS on CDN custom domains. This solution will be similar to other custom resources in the provider, such as `BlobContainerLegalHold`. + +The solution will: + +1. Create a new `CdnCustomDomainHttps` custom resource +2. Implement POST operations to enable and disable HTTPS +3. Add appropriate schema definitions to expose the resource in the Pulumi SDK +4. Implement necessary CRUD operations +5. Register the custom resource with the provider + +## Implementation Steps + +### 1. Create Custom Resource Definition + +Create a new file at `provider/pkg/resources/customresources/custom_cdn_domain_https.go` that will define the custom resource: + +```go +package customresources + +import ( + "context" + "strings" + + "github.com/pkg/errors" + "github.com/pulumi/pulumi-azure-native/v2/provider/pkg/azure" + . "github.com/pulumi/pulumi-azure-native/v2/provider/pkg/resources" + "github.com/pulumi/pulumi-azure-native/v2/provider/pkg/util" + "github.com/pulumi/pulumi-azure-native/v2/provider/pkg/versionLookup" + "github.com/pulumi/pulumi/pkg/v3/codegen/schema" + "github.com/pulumi/pulumi/sdk/v3/go/common/resource" + "github.com/pulumi/pulumi/sdk/v3/go/common/util/logging" +) + +const cdnCustomDomainHttpsPath = "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Cdn/profiles/{profileName}/endpoints/{endpointName}/customDomains/{customDomainName}/customHttps" + +// Common properties required for the resource +var cdnCustomDomainHttpsProperties = map[string]schema.PropertySpec{ + resourceGroupName: { + TypeSpec: schema.TypeSpec{Type: "string"}, + Description: "Name of the resource group that contains the CDN profile.", + }, + "profileName": { + TypeSpec: schema.TypeSpec{Type: "string"}, + Description: "Name of the CDN profile.", + }, + "endpointName": { + TypeSpec: schema.TypeSpec{Type: "string"}, + Description: "Name of the endpoint under the profile.", + }, + "customDomainName": { + TypeSpec: schema.TypeSpec{Type: "string"}, + Description: "Name of the custom domain.", + }, + "httpsEnabled": { + TypeSpec: schema.TypeSpec{Type: "boolean"}, + Description: "Whether HTTPS is enabled on the custom domain.", + }, + "certificateSource": { + TypeSpec: schema.TypeSpec{Type: "string"}, + Description: "Certificate source for the custom domain. One of: 'Cdn', 'AzureKeyVault'.", + }, + "protocolType": { + TypeSpec: schema.TypeSpec{Type: "string"}, + Description: "TLS extension protocol. One of: 'ServerNameIndication', 'IPBased'.", + }, + "minimumTlsVersion": { + TypeSpec: schema.TypeSpec{Type: "string"}, + Description: "TLS protocol version that will be used for HTTPS. One of: 'None', 'TLS10', 'TLS12'.", + }, + "certificateType": { + TypeSpec: schema.TypeSpec{Type: "string"}, + Description: "Certificate type (applicable for CDN-managed certificates). One of: 'Shared', 'Dedicated'.", + }, + // KeyVault certificate parameters (if using AzureKeyVault as certificate source) + "keyVaultSubscriptionId": { + TypeSpec: schema.TypeSpec{Type: "string"}, + Description: "Azure subscription ID containing the Key Vault.", + }, + "keyVaultResourceGroupName": { + TypeSpec: schema.TypeSpec{Type: "string"}, + Description: "Resource group containing the Key Vault.", + }, + "keyVaultVaultName": { + TypeSpec: schema.TypeSpec{Type: "string"}, + Description: "Name of the Key Vault.", + }, + "keyVaultSecretName": { + TypeSpec: schema.TypeSpec{Type: "string"}, + Description: "Name of the secret in Key Vault.", + }, + "keyVaultSecretVersion": { + TypeSpec: schema.TypeSpec{Type: "string"}, + Description: "Version of the secret in Key Vault.", + }, +} + +func cdnCustomDomainHttps(azureClient azure.AzureClient) *CustomResource { + apiVersion, ok := versionLookup.GetDefaultApiVersionForResource("Cdn", "CustomDomain") + if !ok { + // default as of 2024-05-01 + apiVersion = "2024-05-01" + logging.V(3).Infof("Warning: could not find default API version for Cdn:CustomDomain. Using %s", apiVersion) + } + + return &CustomResource{ + tok: "azure-native:cdn:CustomDomainHttps", + path: cdnCustomDomainHttpsPath, + LegacySchema: &schema.ResourceSpec{ + ObjectTypeSpec: schema.ObjectTypeSpec{ + Description: "Enables or disables HTTPS on a CDN custom domain.", + Type: "object", + Properties: cdnCustomDomainHttpsProperties, + }, + InputProperties: cdnCustomDomainHttpsProperties, + RequiredInputs: []string{ + resourceGroupName, "profileName", "endpointName", "customDomainName", + "httpsEnabled", "certificateSource", "protocolType", + }, + }, + Meta: &AzureAPIResource{ + Path: cdnCustomDomainHttpsPath, + PutParameters: []AzureAPIParameter{ + {Name: subscriptionId, Location: "path", IsRequired: true, Value: &AzureAPIProperty{Type: "string"}}, + {Name: resourceGroupName, Location: "path", IsRequired: true, Value: &AzureAPIProperty{Type: "string"}}, + {Name: "profileName", Location: "path", IsRequired: true, Value: &AzureAPIProperty{Type: "string"}}, + {Name: "endpointName", Location: "path", IsRequired: true, Value: &AzureAPIProperty{Type: "string"}}, + {Name: "customDomainName", Location: "path", IsRequired: true, Value: &AzureAPIProperty{Type: "string"}}, + { + Name: "properties", + Location: "body", + Body: &AzureAPIType{ + Properties: map[string]AzureAPIProperty{ + "httpsEnabled": { + Type: "boolean", + }, + "certificateSource": { + Type: "string", + }, + "protocolType": { + Type: "string", + }, + "minimumTlsVersion": { + Type: "string", + }, + "certificateType": { + Type: "string", + }, + "keyVaultSubscriptionId": { + Type: "string", + }, + "keyVaultResourceGroupName": { + Type: "string", + }, + "keyVaultVaultName": { + Type: "string", + }, + "keyVaultSecretName": { + Type: "string", + }, + "keyVaultSecretVersion": { + Type: "string", + }, + }, + RequiredProperties: []string{"httpsEnabled"}, + }, + }, + }, + }, + Create: func(ctx context.Context, id string, properties resource.PropertyMap) (map[string]any, error) { + return updateCdnCustomDomainHttps(ctx, id, properties, azureClient, apiVersion) + }, + Read: func(ctx context.Context, id string, properties resource.PropertyMap) (map[string]any, bool, error) { + // Extract the custom domain ID from the CustomDomainHttps ID + cdnCustomDomainId := strings.TrimSuffix(id, "/customHttps") + + // Read the custom domain to get its HTTPS settings + customDomain, err := azureClient.Get(ctx, cdnCustomDomainId, apiVersion, nil) + if err != nil { + if azure.IsNotFound(err) { + return nil, false, nil + } + return nil, false, err + } + + // Extract HTTPS settings + result := map[string]any{ + "httpsEnabled": false, + } + + props, ok := customDomain["properties"].(map[string]any) + if !ok { + return result, true, nil + } + + provisioningState, ok := props["customHttpsProvisioningState"].(string) + if !ok { + return result, true, nil + } + + // If HTTPS is enabled + if provisioningState == "Enabled" { + result["httpsEnabled"] = true + + // Extract HTTPS parameters if available + if httpsParams, ok := props["customHttpsParameters"].(map[string]any); ok { + result["certificateSource"] = httpsParams["certificateSource"] + result["protocolType"] = httpsParams["protocolType"] + + if minTls, ok := httpsParams["minimumTlsVersion"]; ok { + result["minimumTlsVersion"] = minTls + } + + if certParams, ok := httpsParams["certificateSourceParameters"].(map[string]any); ok { + if typeName, ok := certParams["typeName"].(string); ok { + if typeName == "CdnCertificateSourceParameters" { + if certType, ok := certParams["certificateType"].(string); ok { + result["certificateType"] = certType + } + } else if typeName == "KeyVaultCertificateSourceParameters" { + if kv, ok := certParams["subscriptionId"].(string); ok { + result["keyVaultSubscriptionId"] = kv + } + if kv, ok := certParams["resourceGroupName"].(string); ok { + result["keyVaultResourceGroupName"] = kv + } + if kv, ok := certParams["vaultName"].(string); ok { + result["keyVaultVaultName"] = kv + } + if kv, ok := certParams["secretName"].(string); ok { + result["keyVaultSecretName"] = kv + } + if kv, ok := certParams["secretVersion"].(string); ok { + result["keyVaultSecretVersion"] = kv + } + } + } + } + } + } + + return result, true, nil + }, + Update: func(ctx context.Context, id string, news, olds resource.PropertyMap) (map[string]any, error) { + return updateCdnCustomDomainHttps(ctx, id, news, azureClient, apiVersion) + }, + Delete: func(ctx context.Context, id string, inputs, state resource.PropertyMap) error { + // Extract the custom domain ID + customDomainId := strings.TrimSuffix(id, "/customHttps") + + // For delete, we'll disable HTTPS + path := customDomainId + "/disableCustomHttps" + + queryParams := map[string]any{ + "api-version": apiVersion, + } + + _, err := azureClient.Post(ctx, path, map[string]any{}, queryParams) + return err + }, + } +} + +func updateCdnCustomDomainHttps(ctx context.Context, id string, properties resource.PropertyMap, azureClient azure.AzureClient, apiVersion string) (map[string]any, error) { + props := properties.Mappable() + + // Extract the custom domain ID + customDomainId := strings.TrimSuffix(id, "/customHttps") + + httpsEnabled, ok := props["httpsEnabled"].(bool) + if !ok { + return nil, errors.New("missing required property 'httpsEnabled'") + } + + queryParams := map[string]any{ + "api-version": apiVersion, + } + + // If HTTPS is being disabled + if !httpsEnabled { + path := customDomainId + "/disableCustomHttps" + _, err := azureClient.Post(ctx, path, map[string]any{}, queryParams) + if err != nil { + return nil, err + } + return props, nil + } + + // HTTPS is being enabled + path := customDomainId + "/enableCustomHttps" + + certificateSource, ok := props["certificateSource"].(string) + if !ok { + return nil, errors.New("missing required property 'certificateSource'") + } + + protocolType, ok := props["protocolType"].(string) + if !ok { + return nil, errors.New("missing required property 'protocolType'") + } + + // Prepare the request body for enabling HTTPS + body := map[string]any{ + "certificateSource": certificateSource, + "protocolType": protocolType, + } + + if minimumTlsVersion, ok := props["minimumTlsVersion"].(string); ok { + body["minimumTlsVersion"] = minimumTlsVersion + } + + // Configure certificate source parameters based on certificate source + certificateSourceParams := map[string]any{} + + if certificateSource == "Cdn" { + if certificateType, ok := props["certificateType"].(string); ok { + certificateSourceParams["certificateType"] = certificateType + } else { + // Default to Shared if not specified + certificateSourceParams["certificateType"] = "Shared" + } + } else if certificateSource == "AzureKeyVault" { + // Validate required parameters for Key Vault + requiredParams := []string{ + "keyVaultSubscriptionId", + "keyVaultResourceGroupName", + "keyVaultVaultName", + "keyVaultSecretName", + } + + for _, param := range requiredParams { + if _, ok := props[param].(string); !ok { + return nil, errors.New("missing required property '" + param + "' for AzureKeyVault certificate source") + } + } + + certificateSourceParams["subscriptionId"] = props["keyVaultSubscriptionId"] + certificateSourceParams["resourceGroupName"] = props["keyVaultResourceGroupName"] + certificateSourceParams["vaultName"] = props["keyVaultVaultName"] + certificateSourceParams["secretName"] = props["keyVaultSecretName"] + + if secretVersion, ok := props["keyVaultSecretVersion"].(string); ok { + certificateSourceParams["secretVersion"] = secretVersion + } + + // Default update and delete rules + certificateSourceParams["updateRule"] = "NoAction" + certificateSourceParams["deleteRule"] = "NoAction" + } + + body["certificateSourceParameters"] = certificateSourceParams + + _, err := azureClient.Post(ctx, path, body, queryParams) + if err != nil { + return nil, err + } + + return props, nil +} +``` + +### 2. Register the Custom Resource + +Modify `provider/pkg/resources/customresources/customresources.go` to add the new custom resource to the `BuildCustomResources` function: + +```go +func BuildCustomResources(env *azureEnv.Environment, + azureClient azure.AzureClient, + lookupResource ResourceLookupFunc, + crudClientFactory crud.ResourceCrudClientFactory, + subscriptionID string, + bearerAuth autorest.Authorizer, + tokenAuth autorest.Authorizer, + kvBearerAuth autorest.Authorizer, + userAgent string, + tokenCred azcore.TokenCredential) (map[string]*CustomResource, error) { + + // ... existing code ... + + resources := []*CustomResource{ + keyVaultAccessPolicy(armKVClient), + + // Customization of regular resources + blobContainerLegalHold(azureClient), + portalDashboard(), + customWebApp, + customWebAppSlot, + postgresConf, + protectedItem, + pimRoleManagementPolicy, + pimRoleEligibilitySchedule, + // Add the new custom resource + cdnCustomDomainHttps(azureClient), + } + + // ... rest of the function ... +} +``` + +### 3. Add Example Code + +Create an example in the `examples` directory to demonstrate usage of the new resource: + +```typescript +// examples/cdn-custom-domain-https/index.ts +import * as pulumi from "@pulumi/pulumi"; +import * as resources from "@pulumi/azure-native/resources"; +import * as cdn from "@pulumi/azure-native/cdn"; + +// Create a resource group +const resourceGroup = new resources.ResourceGroup("resourceGroup"); + +// Create a CDN profile +const cdnProfile = new cdn.Profile("cdnProfile", { + resourceGroupName: resourceGroup.name, + location: resourceGroup.location, + sku: { + name: "Standard_Microsoft", + }, +}); + +// Create a CDN endpoint +const cdnEndpoint = new cdn.Endpoint("cdnEndpoint", { + resourceGroupName: resourceGroup.name, + profileName: cdnProfile.name, + location: resourceGroup.location, + originHostHeader: "www.contoso.com", + origins: [{ + name: "contoso", + hostName: "www.contoso.com", + }], +}); + +// Create a custom domain +const customDomain = new cdn.CustomDomain("customDomain", { + resourceGroupName: resourceGroup.name, + profileName: cdnProfile.name, + endpointName: cdnEndpoint.name, + hostName: "cdn.contoso.com", +}); + +// Enable HTTPS on the custom domain using CDN-managed certificate +const customDomainHttps = new cdn.CustomDomainHttps("customDomainHttps", { + resourceGroupName: resourceGroup.name, + profileName: cdnProfile.name, + endpointName: cdnEndpoint.name, + customDomainName: customDomain.name, + httpsEnabled: true, + certificateSource: "Cdn", + protocolType: "ServerNameIndication", + certificateType: "Shared", + minimumTlsVersion: "TLS12", +}); + +// Export the custom domain name +export const customDomainName = customDomain.name; +export const httpsEnabled = customDomainHttps.httpsEnabled; +``` + +## Testing Plan + +1. Unit Tests: + - Create tests for the CustomDomainHttps resource in the provider + - Test both CDN-managed and Key Vault-based certificate scenarios + - Test enabling and disabling HTTPS + +2. Integration Tests: + - Test the full workflow in a real Azure environment + - Verify correct HTTPS provisioning state + +## Notes + +- The implementation follows the pattern used by other custom resources in the provider, particularly the BlobContainerLegalHold resource +- The resource is designed to be idempotent, handling both the creation and updating of HTTPS settings +- Error handling ensures proper validation of required parameters based on certificate source +- Since the actual HTTPS provisioning may take time, the resource doesn't wait for completion - users should check the CustomDomain's `customHttpsProvisioningState` property to monitor the process + +## Future Enhancements + +1. Add a way to track the provisioning status of the HTTPS enablement process +2. Consider supporting additional certificate sources if Azure adds them +3. Improve error handling for certificate validation failures + +--- + +Once this implementation is complete, users will be able to enable and disable HTTPS on CDN custom domains directly through Pulumi, eliminating the need for external scripts or manual Azure portal steps. \ No newline at end of file diff --git a/implementation_guide_api_spec.md b/implementation_guide_api_spec.md new file mode 100644 index 000000000000..8cbef411592b --- /dev/null +++ b/implementation_guide_api_spec.md @@ -0,0 +1,802 @@ +# Implementation Guide: Semi-Automated Integration with Azure API Specs + +## Overview + +This guide describes how to integrate a new or updated Azure API into the Pulumi Azure Native provider in a semi-automated way by leveraging the existing schema generation tools. This approach is ideal for adding support for new Azure services or updating existing ones to support new functionality. + +## Prerequisites + +1. **Environment Setup**: + - Go 1.21+ + - NodeJS 18.X.X+ + - Python 3.10+ (for testing) + - Azure REST API specs submodule properly initialized + +2. **Understanding the Azure Specs**: + - Familiarity with the [Azure REST API specifications](https://github.com/Azure/azure-rest-api-specs) + - Understanding of the API version format (e.g., `2020-01-01`, `2020-01-01-preview`) + +## High-Level Process + +The process of integrating a new Azure API or updating an existing one consists of these steps: + +1. **Update the API specs submodule** (if needed) +2. **Configure version selection** +3. **Generate the schema** +4. **Handle custom behaviors** (if needed) +5. **Test and validate** + +This guide will walk through each step in detail. + +## Detailed Steps + +### 1. Update API Specs Submodule + +If you're working with a new API or a more recent version than what's currently included: + +```bash +cd azure-rest-api-specs +git checkout main +git pull origin main +cd .. +``` + +After updating, run: + +```bash +make update_submodules +``` + +This command updates the API specs and refreshes the Azure provider list. + +### 2. Configure Version Selection + +The Pulumi Azure Native provider is selective about which API versions to include. This selection is managed in the `versions/` directory. + +#### 2.1 Identify New API Versions + +To check if new versions are available for a service: + +```bash +bin/pulumi-gen-azure-native schema +``` + +This will generate reports in the `reports/` directory. Check: +- `allResourceVersionsByResource.json` - All available API versions by resource +- `allResourcesByVersion.json` - All resources available in each API version + +#### 2.2 Controlling Which Specs Are Generated + +There are several ways to control which API specs are processed: + +##### Using Environment Variables for Targeted Schema Generation + +For development and testing, you can use environment variables to limit which API specs are processed: + +```bash +# Filter by a specific namespace (e.g., Compute, Storage, Network) +DEBUG_CODEGEN_NAMESPACES=Compute make schema + +# Filter by multiple namespaces (comma-separated) +DEBUG_CODEGEN_NAMESPACES=Compute,Storage make schema + +# Filter by API version pattern +DEBUG_CODEGEN_APIVERSIONS="2023*" make schema + +# Combine namespace and version filters +DEBUG_CODEGEN_NAMESPACES=Compute DEBUG_CODEGEN_APIVERSIONS="2023*" make schema +``` + +These environment variables are processed in the `pulumi-gen-azure-native` tool and help you focus on specific parts of the API when developing. + +##### Version Configuration Files + +For permanent configuration, use the following files in the `versions/` directory: + +1. **Base Version Configuration**: `versions/v{MAJOR_VERSION}.yaml` + - Contains baseline configuration for each major version + - Generated automatically by the tooling + - Don't edit this file directly + +2. **Default Version Configuration**: `versions/v{MAJOR_VERSION}-spec.yaml` + - Defines which API version to use for each resource + - Controls which API version is the default when users don't specify a version + +3. **Custom Configuration**: `versions/v{MAJOR_VERSION}-config.yaml` + - Where you make your customizations to include additional versions + - Add new services or resources here + +4. **Exclusion Configuration**: `versions/v{MAJOR_VERSION}-removed.json` + - Defines resources to exclude from generation + - Used for problematic or deprecated resources + +###### Structure of Configuration Files + +The configuration files use a hierarchical structure: + +```yaml +# Add specific versions for a namespace +additionalVersions: + Storage: # Namespace + "2023-01-01": # API Version + resources: # Resources to include + - BlobContainer + - StorageAccount + + Compute: + "2023-03-01": + resources: + - VirtualMachine + # You can also exclude specific resources within a version + exclude: + - DiskEncryptionSet + +# Change default versions for resources +defaultVersionUpdates: + Storage: + BlobContainer: "2023-01-01" + StorageAccount: "2023-01-01" + +# Exclude resources entirely +remove: + Storage: + - Queue # Exclude Queue resource from all versions +``` + +##### Resource Filtering Options + +You can also control which resources are included or excluded from specific API versions: + +```yaml +additionalVersions: + Network: + "2022-11-01": + # Include only these resources + resources: + - VirtualNetwork + - NetworkInterface + - PublicIPAddress + + # Exclude these specific resources + exclude: + - RouteTable + - RouteFilter + + # Include all resources from a specific version + Security: + "2023-01-01": + includeAllResources: true # Include all resources from this version +``` + +When working with additional versions, keep these points in mind: +- Use `includeAllResources: true` with caution as it may include many resources +- Always test thoroughly after adding new versions +- Be mindful of breaking changes between API versions + +#### 2.3 Update Version Configuration + +Based on your needs, edit the appropriate version configuration file: + +- For the current major version, edit `versions/v{MAJOR_VERSION}-config.yaml` +- Follow the existing format to add your service/resource + +Example configuration entry: + +```yaml +# Add support for new storage API +additionalVersions: + Storage: + "2023-01-01": + resources: + - BlobContainer + - StorageAccount +``` + +To make a version the default for new resources: + +```yaml +defaultVersionUpdates: + Storage: + BlobContainer: "2023-01-01" + StorageAccount: "2023-01-01" +``` + +### 3. Generate the Schema + +After configuration changes, generate the schema: + +```bash +make generate_schema generate_docs +``` + +This will: +1. Process the Azure API specs +2. Apply your version configurations +3. Generate the Pulumi schema and documentation +4. Create SDK resources for all selected API versions + +#### 3.1 Schema Generation Process + +The schema generation process follows these steps: + +1. The `pulumi-gen-azure-native schema` command: + - Reads the Azure REST API specifications + - Applies version configuration from the `versions/` directory + - Filters resources based on your configuration + - Generates a unified Pulumi schema + - Creates metadata for the provider + +2. It outputs several files: + - `bin/schema-full.json` - Complete schema with all included versions + - `bin/schema-default-versions.json` - Schema with only default versions + - `bin/metadata-compact.json` - Metadata for the provider + +3. These files are then used to generate language-specific SDKs and documentation. + +#### 3.2 Regenerating After Changes + +When you make configuration changes, use these commands to regenerate: + +```bash +# Regenerate all schemas +make generate_schema + +# Regenerate schemas and documentation +make generate_schema generate_docs + +# Regenerate and build all SDKs +make +``` + +If you're only interested in specific SDKs, you can use: + +```bash +# Generate schemas and TypeScript SDK +make generate_schema generate_nodejs + +# Generate schemas and Python SDK +make generate_schema generate_python +``` + +### 4. Handle Custom Behaviors (If Needed) + +Some Azure APIs require special handling due to limitations in the OpenAPI specifications or to support specific Pulumi patterns. + +#### 4.1 Recognize When Custom Code Is Needed + +Custom code may be needed when: +- The API uses POST operations to perform actions (like enabling/disabling features) +- Resources have special parent/child relationships +- Special data transformations are required +- Error handling needs customization + +#### If the functionality can be represented as a standard resource, prefer to implement a custom resource that provides a familiar CRUD interface to Pulumi users, even if the underlying API uses different operations. + +## Action-Based Custom Resources + +Many Azure APIs expose functionality through POST operations rather than standard PUT/GET/DELETE operations. These are often referred to as "actions" and require special handling in the Pulumi provider. + +### Recognizing Action-Based APIs + +Action-based APIs have these characteristics: +- Functionality exposed via POST endpoints (often ending with verbs like `/enable`, `/disable`, `/start`, etc.) +- Operations that don't map cleanly to CRUD lifecycle +- Often operate on existing resources rather than creating new ones +- Configuration is provided in the request body rather than as path parameters + +Common examples include: +- Enabling features on a resource (like HTTPS on CDN domains) +- Regenerating access keys or secrets +- Starting/stopping/restarting services +- Triggering operations on resources (like backups, syncs, validations) + +### Implementing Action-Based Custom Resources + +Action-based APIs are implemented as custom resources that use the underlying POST operations but expose a standard resource interface to Pulumi users. + +#### Step 1: Research the API + +Start by understanding the API from the Azure documentation and OpenAPI specs: + +1. Identify the base resource path and action endpoints +2. Understand the request/response structure +3. Determine how to map user-provided properties to API parameters +4. Check for long-running operations or async patterns + +For example, with CDN Custom Domain HTTPS: +- Base resource path: `/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Cdn/profiles/{profileName}/endpoints/{endpointName}/customDomains/{customDomainName}` +- Action endpoints: `/enableCustomHttps` and `/disableCustomHttps` +- Property mapping: `certificateSource`, `protocolType`, etc. in the request body + +#### Step 2: Design the Custom Resource Interface + +Design a Pulumi resource that presents a clean, declarative interface: + +1. Define the resource token and path +2. Create input/output properties that make sense to Pulumi users +3. Choose appropriate property types and validation +4. Decide how to represent the desired state + +For example, `CdnCustomDomainHttps` uses boolean `httpsEnabled` property to control enabling/disabling. + +#### Step 3: Implement the Custom Resource Code + +Create a new file in `provider/pkg/resources/customresources/`, following this pattern: + +```go +package customresources + +import ( + "context" + "strings" + + "github.com/pkg/errors" + "github.com/pulumi/pulumi-azure-native/v2/provider/pkg/azure" + . "github.com/pulumi/pulumi-azure-native/v2/provider/pkg/resources" + "github.com/pulumi/pulumi-azure-native/v2/provider/pkg/util" + "github.com/pulumi/pulumi/pkg/v3/codegen/schema" + "github.com/pulumi/pulumi/sdk/v3/go/common/resource" +) + +// Define the base path and action paths +const myCustomResourceBasePath = "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Service/resources/{resourceName}" +const myCustomEnableActionPath = myCustomResourceBasePath + "/enableFeature" +const myCustomDisableActionPath = myCustomResourceBasePath + "/disableFeature" + +// Define input/output properties +var myCustomResourceProperties = map[string]schema.PropertySpec{ + resourceGroupName: { + TypeSpec: schema.TypeSpec{Type: "string"}, + Description: "Name of the resource group.", + }, + "resourceName": { + TypeSpec: schema.TypeSpec{Type: "string"}, + Description: "Name of the resource.", + }, + "featureEnabled": { + TypeSpec: schema.TypeSpec{Type: "boolean"}, + Description: "Whether the feature is enabled.", + }, + // Additional properties specific to your resource +} + +// Implement the custom resource +func myCustomResource(azureClient azure.AzureClient) *CustomResource { + apiVersion := "2023-01-01" + + return &CustomResource{ + tok: "azure-native:myservice:MyCustomFeature", + path: myCustomResourceBasePath + "/customFeature", // Logical path for Pulumi resource ID + LegacySchema: &schema.ResourceSpec{ + ObjectTypeSpec: schema.ObjectTypeSpec{ + Description: "Controls the custom feature settings for a resource.", + Type: "object", + Properties: myCustomResourceProperties, + }, + InputProperties: myCustomResourceProperties, + RequiredInputs: []string{ + resourceGroupName, "resourceName", "featureEnabled", + }, + }, + Create: func(ctx context.Context, id string, properties resource.PropertyMap) (map[string]any, error) { + return updateMyCustomResource(ctx, id, properties, azureClient, apiVersion) + }, + Read: func(ctx context.Context, id string, properties resource.PropertyMap) (map[string]any, bool, error) { + // Extract the base resource ID from the custom feature ID + baseResourceId := strings.TrimSuffix(id, "/customFeature") + + // Read the base resource to determine the current state + baseResource, err := azureClient.Get(ctx, baseResourceId, apiVersion, nil) + if err != nil { + if azure.IsNotFound(err) { + return nil, false, nil + } + return nil, false, err + } + + // Extract feature state from the resource properties + result := map[string]any{ + "featureEnabled": false, // Default state + } + + props, ok := baseResource["properties"].(map[string]any) + if !ok { + return result, true, nil + } + + // Set actual state based on resource properties + if featureState, ok := props["featureState"].(string); ok && featureState == "Enabled" { + result["featureEnabled"] = true + } + + return result, true, nil + }, + Update: func(ctx context.Context, id string, news, olds resource.PropertyMap) (map[string]any, error) { + return updateMyCustomResource(ctx, id, news, azureClient, apiVersion) + }, + Delete: func(ctx context.Context, id string, inputs, state resource.PropertyMap) error { + // For most action-based resources, delete means reverting to a default state + // Extract the base resource ID + baseResourceId := strings.TrimSuffix(id, "/customFeature") + + // Disable the feature + path := strings.TrimSuffix(id, "/customFeature") + "/disableFeature" + + queryParams := map[string]any{ + "api-version": apiVersion, + } + + _, err := azureClient.Post(ctx, path, map[string]any{}, queryParams) + return err + }, + } +} + +// Helper function for Create and Update operations +func updateMyCustomResource(ctx context.Context, id string, properties resource.PropertyMap, azureClient azure.AzureClient, apiVersion string) (map[string]any, error) { + props := properties.Mappable() + + // Extract the base resource ID + baseResourceId := strings.TrimSuffix(id, "/customFeature") + + featureEnabled, ok := props["featureEnabled"].(bool) + if !ok { + return nil, errors.New("missing required property 'featureEnabled'") + } + + queryParams := map[string]any{ + "api-version": apiVersion, + } + + // Determine whether to enable or disable based on featureEnabled flag + var path string + var body map[string]any + + if featureEnabled { + path = baseResourceId + "/enableFeature" + + // Build the request body for enabling + body = map[string]any{ + // Include required properties from the user input + "property1": props["property1"], + "property2": props["property2"], + } + } else { + path = baseResourceId + "/disableFeature" + // Usually disable operations take no parameters or minimal ones + body = map[string]any{} + } + + // Make the POST request to the appropriate action endpoint + _, err := azureClient.Post(ctx, path, body, queryParams) + if err != nil { + return nil, err + } + + return props, nil +} +``` + +#### Step 4: Register the Custom Resource + +Add your resource to the `BuildCustomResources` function in `provider/pkg/resources/customresources/customresources.go`: + +```go +func BuildCustomResources(env *azureEnv.Environment, + azureClient azure.AzureClient, + // ... other parameters ... +) (map[string]*CustomResource, error) { + + // ... existing code ... + + resources := []*CustomResource{ + keyVaultAccessPolicy(armKVClient), + // ... other resources ... + + // Add your new custom resource + myCustomResource(azureClient), + } + + // ... rest of the function ... +} +``` + +### Real-World Example: CDN Custom Domain HTTPS + +Let's examine how the Pulumi Azure Native provider implements the custom resource for enabling HTTPS on CDN custom domains. + +#### Understanding the API + +The Azure API exposes two POST endpoints for managing HTTPS on CDN custom domains: +- `/enableCustomHttps` - Enables HTTPS with certificate settings +- `/disableCustomHttps` - Disables HTTPS + +These don't map cleanly to standard CRUD operations, but users expect a declarative resource that handles the underlying complexity. + +#### Resource Implementation + +The implementation consists of: + +1. **Resource Definition**: +```go +const cdnCustomDomainHttpsPath = "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Cdn/profiles/{profileName}/endpoints/{endpointName}/customDomains/{customDomainName}/customHttps" + +var cdnCustomDomainHttpsProperties = map[string]schema.PropertySpec{ + resourceGroupName: { + TypeSpec: schema.TypeSpec{Type: "string"}, + Description: "Name of the resource group that contains the CDN profile.", + }, + // ... other properties ... + "httpsEnabled": { + TypeSpec: schema.TypeSpec{Type: "boolean"}, + Description: "Whether HTTPS is enabled on the custom domain.", + }, + "certificateSource": { + TypeSpec: schema.TypeSpec{Type: "string"}, + Description: "Certificate source for the custom domain. One of: 'Cdn', 'AzureKeyVault'.", + }, + // ... additional certificate properties ... +} +``` + +2. **CRUD Operations**: + - **Create/Update**: Calls `enableCustomHttps` or `disableCustomHttps` POST endpoints based on the `httpsEnabled` property + - **Read**: Reads the parent `CustomDomain` resource and checks its HTTPS provisioning state + - **Delete**: Calls the `disableCustomHttps` endpoint to revert to the default state + +3. **ID Composition**: + - The resource ID is the base custom domain path with "/customHttps" appended + - Operations extract the base resource ID when needed to call the appropriate endpoints + +4. **Implementation Details**: +```go +func updateCdnCustomDomainHttps(ctx context.Context, id string, properties resource.PropertyMap, azureClient azure.AzureClient, apiVersion string) (map[string]any, error) { + props := properties.Mappable() + + // Extract the custom domain ID + customDomainId := strings.TrimSuffix(id, "/customHttps") + + httpsEnabled, ok := props["httpsEnabled"].(bool) + if !ok { + return nil, errors.New("missing required property 'httpsEnabled'") + } + + // Choose the appropriate endpoint based on httpsEnabled + if !httpsEnabled { + path := customDomainId + "/disableCustomHttps" + _, err := azureClient.Post(ctx, path, map[string]any{}, queryParams) + // ... + } else { + path := customDomainId + "/enableCustomHttps" + // Build the request body with certificate information + body := map[string]any{ + "certificateSource": certificateSource, + "protocolType": protocolType, + // ... + } + _, err := azureClient.Post(ctx, path, body, queryParams) + // ... + } + + return props, nil +} +``` + +### Handling Long-Running Operations + +Many Azure action APIs are asynchronous and return a 202 Accepted response with an operation location header. For these operations: + +1. Use the `azure.LongRunningOperation` interface to track operation status +2. In the Read operation, check for transitional states +3. Use the parent resource's status properties to determine the current state + +Example for handling async operations: + +```go +// In Create/Update function +operation, err := azureClient.PostLongRunning(ctx, path, body, queryParams) +if err != nil { + return nil, err +} + +// Wait for the operation to complete (optional, based on your needs) +if err = operation.WaitForCompletion(ctx); err != nil { + return nil, err +} + +// In Read function +// Check the provisioning state of the parent resource +if provisioningState, ok := props["provisioningState"].(string); ok { + // Handle transitional states + if provisioningState == "Updating" || provisioningState == "Provisioning" { + // Resource is still being updated + // You may want to return the last known state + } +} +``` + +### Best Practices for Action-Based Resources + +1. **Use Boolean Toggles**: When possible, use boolean properties like `enabled` to control action-based features +2. **Map to Familiar Patterns**: Make the resource feel like a standard resource to users +3. **Handle Transitional States**: Check for and handle in-progress operations +4. **Detailed Error Messages**: Provide clear error messages for API-specific failures +5. **Document Thoroughly**: Explain the behavior and expected states in the resource documentation + +### Example Usage in Pulumi + +The implementation allows users to use a declarative pattern: + +```typescript +// Example usage of the CDN Custom Domain HTTPS resource +const customDomainHttps = new cdn.CustomDomainHttps("customDomainHttps", { + resourceGroupName: resourceGroup.name, + profileName: cdnProfile.name, + endpointName: cdnEndpoint.name, + customDomainName: customDomain.name, + httpsEnabled: true, + certificateSource: "Cdn", + protocolType: "ServerNameIndication", + certificateType: "Shared", + minimumTlsVersion: "TLS12", +}); +``` + +### Summary + +Action-based custom resources allow you to present a standard resource interface for Azure APIs that use POST operations. By hiding the complexity of these operations, you provide a more consistent and intuitive experience for Pulumi users. + +## Creating Standard Custom Resources + +If your API conforms more closely to standard Azure resource patterns with PUT/GET/DELETE operations, you can implement a custom resource with a more straightforward mapping. + +#### 4.2 Create a Standard Custom Resource + +For standard resource patterns: + +1. Create a new file in `provider/pkg/resources/customresources/` +2. Implement the custom resource following this pattern: + +```go +// Define token and path +const myCustomResourcePath = "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/..." + +// Define properties +var myCustomResourceProperties = map[string]schema.PropertySpec{ + // Standard properties + resourceGroupName: { + TypeSpec: schema.TypeSpec{Type: "string"}, + Description: "Name of the resource group.", + }, + // Custom properties for your resource + "myProperty": { + TypeSpec: schema.TypeSpec{Type: "string"}, + Description: "Description of the property.", + }, +} + +// Create the custom resource +func myCustomResource(azureClient azure.AzureClient) *CustomResource { + apiVersion := "2023-01-01" // Use appropriate version + + return &CustomResource{ + tok: "azure-native:myservice:MyCustomResource", // Use appropriate module and name + path: myCustomResourcePath, + LegacySchema: &schema.ResourceSpec{ + ObjectTypeSpec: schema.ObjectTypeSpec{ + Description: "Manages a custom Azure resource.", + Type: "object", + Properties: myCustomResourceProperties, + }, + InputProperties: myCustomResourceProperties, + RequiredInputs: []string{ + resourceGroupName, "requiredProperty1", "requiredProperty2", + }, + }, + // Implement CRUD operations + Create: func(ctx context.Context, id string, properties resource.PropertyMap) (map[string]any, error) { + // Implementation details + }, + Read: func(ctx context.Context, id string, properties resource.PropertyMap) (map[string]any, bool, error) { + // Implementation details + }, + Update: func(ctx context.Context, id string, news, olds resource.PropertyMap) (map[string]any, error) { + // Implementation details + }, + Delete: func(ctx context.Context, id string, inputs, state resource.PropertyMap) error { + // Implementation details + }, + } +} +``` + +3. Register the custom resource in `provider/pkg/resources/customresources/customresources.go` + +### 5. Test and Validate + +#### 5.1 Build the Provider and SDKs + +```bash +make +``` + +#### 5.2 Create Integration Tests + +Create an example that uses your new resource: + +1. Add a new example directory in `examples/` +2. Create the basic resource configuration +3. Test the example using `make test` + +For a specific test: + +```bash +make test TEST_NAME=TestMyExample +``` + +#### 5.3 Test With Local Provider + +To test with the local provider: + +```bash +make install_provider +cd examples/my-example +pulumi up +``` + +## Advanced Topics + +### Adding Custom Documentation + +For important resources, add documentation in `docs/resources/`: + +1. Create a file following the pattern `[module]-[Resource].md` +2. Include proper documentation with examples +3. Regenerate docs with `make generate generate_docs` + +### API Version Lifecycle Management + +When managing multiple API versions: + +1. Keep the previous version as a fallback +2. Test backward compatibility +3. Consider using `versions/v{MAJOR_VERSION}-removed.json` if resources need to be excluded + +### Handling API Changes + +When Azure makes breaking changes: + +1. Record the changes in `versions/v{MAJOR_VERSION}-removed.json` +2. Create custom adapters if needed for compatibility +3. Document breaking changes for users + +## Troubleshooting + +### Common Issues + +1. **Schema Generation Failures**: + - Ensure the specs submodule is properly initialized + - Check for syntax errors in version configuration files + - Look at error messages for specific resources or API versions + +2. **Resource Not Found**: + - Confirm the resource exists in the selected API version + - Check resource naming in the version configuration + - Verify the correct module name is being used + +3. **Custom Resource Issues**: + - Debug paths and parameter mappings + - Check REST API documentation for any undocumented requirements + - Test direct HTTP requests using the Azure CLI or Postman + +4. **Action-Based Resource Issues**: + - Ensure you're using the correct action endpoints + - Check for required properties in the request body + - Verify the parent resource exists before attempting actions + - Handle asynchronous operations correctly + +## References + +- Azure REST API Specifications: https://github.com/Azure/azure-rest-api-specs +- Azure SDK Generation Process: https://github.com/Azure/azure-sdk-for-go +- Pulumi Schema Reference: https://www.pulumi.com/docs/reference/pkg/ \ No newline at end of file diff --git a/provider/pkg/resources/customresources/custom_cdn_domain_https.go b/provider/pkg/resources/customresources/custom_cdn_domain_https.go new file mode 100644 index 000000000000..880b69b37bad --- /dev/null +++ b/provider/pkg/resources/customresources/custom_cdn_domain_https.go @@ -0,0 +1,417 @@ +package customresources + +import ( + "context" + "strings" + + "github.com/pkg/errors" + "github.com/pulumi/pulumi-azure-native/v2/provider/pkg/azure" + . "github.com/pulumi/pulumi-azure-native/v2/provider/pkg/resources" + "github.com/pulumi/pulumi-azure-native/v2/provider/pkg/versionLookup" + "github.com/pulumi/pulumi/pkg/v3/codegen/schema" + "github.com/pulumi/pulumi/sdk/v3/go/common/resource" + "github.com/pulumi/pulumi/sdk/v3/go/common/util/logging" +) + +const cdnCustomDomainHttpsPath = "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Cdn/profiles/{profileName}/endpoints/{endpointName}/customDomains/{customDomainName}/customHttps" + +// Define certificate source type constants +const ( + CertificateSourceCdn = "Cdn" + CertificateSourceKeyVault = "AzureKeyVault" + ProtocolTypeServerNameIndication = "ServerNameIndication" + ProtocolTypeIPBased = "IPBased" +) + +// Certificate source parameters types +var cdnCertificateSourceParametersProperties = map[string]schema.PropertySpec{ + "certificateType": { + TypeSpec: schema.TypeSpec{Type: "string"}, + Description: "Certificate type for CDN managed certificates. One of: 'Shared', 'Dedicated'.", + }, +} + +var keyVaultCertificateSourceParametersProperties = map[string]schema.PropertySpec{ + "subscriptionId": { + TypeSpec: schema.TypeSpec{Type: "string"}, + Description: "Azure subscription ID containing the Key Vault.", + }, + "resourceGroupName": { + TypeSpec: schema.TypeSpec{Type: "string"}, + Description: "Resource group containing the Key Vault.", + }, + "vaultName": { + TypeSpec: schema.TypeSpec{Type: "string"}, + Description: "Name of the Key Vault.", + }, + "secretName": { + TypeSpec: schema.TypeSpec{Type: "string"}, + Description: "Name of the secret in Key Vault.", + }, + "secretVersion": { + TypeSpec: schema.TypeSpec{Type: "string"}, + Description: "Version of the secret in Key Vault.", + }, +} + +// Define type specifications +var keyVaultCertificateSourceParametersTypeSpec = schema.ComplexTypeSpec{ + ObjectTypeSpec: schema.ObjectTypeSpec{ + Type: "object", + Description: "Key Vault certificate parameters for custom domain HTTPS configuration.", + Properties: keyVaultCertificateSourceParametersProperties, + Required: []string{"subscriptionId", "resourceGroupName", "vaultName", "secretName"}, + }, +} + +var cdnCertificateSourceParametersTypeSpec = schema.ComplexTypeSpec{ + ObjectTypeSpec: schema.ObjectTypeSpec{ + Type: "object", + Description: "CDN certificate parameters for custom domain HTTPS configuration.", + Properties: cdnCertificateSourceParametersProperties, + }, +} + +// HTTPS configuration properties +var httpsConfigurationProperties = map[string]schema.PropertySpec{ + "certificateSource": { + TypeSpec: schema.TypeSpec{Type: "string"}, + Description: "Certificate source for the custom domain. One of: 'Cdn', 'AzureKeyVault'.", + }, + "protocolType": { + TypeSpec: schema.TypeSpec{Type: "string"}, + Description: "TLS extension protocol. One of: 'ServerNameIndication', 'IPBased'.", + }, + "minimumTlsVersion": { + TypeSpec: schema.TypeSpec{Type: "string"}, + Description: "TLS protocol version that will be used for HTTPS. One of: 'None', 'TLS10', 'TLS12'.", + }, + "cdnCertificateSourceParameters": { + TypeSpec: schema.TypeSpec{Ref: "#/types/azure-native:cdn:CdnCertificateSourceParameters"}, + Description: "Parameters required for using CDN managed certificates.", + }, + "keyVaultCertificateSourceParameters": { + TypeSpec: schema.TypeSpec{Ref: "#/types/azure-native:cdn:KeyVaultCertificateSourceParameters"}, + Description: "Parameters required for using certificates stored in Azure KeyVault.", + }, +} + +// Common properties required for the resource +var cdnCustomDomainHttpsProperties = map[string]schema.PropertySpec{ + "customDomainId": { + TypeSpec: schema.TypeSpec{Type: "string"}, + Description: "The resource ID of the CDN Custom Domain.", + }, + "httpsEnabled": { + TypeSpec: schema.TypeSpec{Type: "boolean"}, + Description: "Whether HTTPS is enabled on the custom domain.", + }, + "httpsConfiguration": { + TypeSpec: schema.TypeSpec{Ref: "#/types/azure-native:cdn:HttpsConfiguration"}, + Description: "HTTPS configuration when HTTPS is enabled.", + }, +} + +func cdnCustomDomainHttps(azureClient azure.AzureClient) *CustomResource { + apiVersion, ok := versionLookup.GetDefaultApiVersionForResource("Cdn", "CustomDomain") + if !ok { + // default as of 2024-05-01 + apiVersion = "2024-05-01" + logging.V(3).Infof("Warning: could not find default API version for Cdn:CustomDomain. Using %s", apiVersion) + } + + httpsConfigType := schema.ComplexTypeSpec{ + ObjectTypeSpec: schema.ObjectTypeSpec{ + Type: "object", + Description: "HTTPS configuration for CDN custom domain.", + Properties: httpsConfigurationProperties, + Required: []string{"certificateSource", "protocolType"}, + }, + } + + return &CustomResource{ + tok: "azure-native:cdn:CustomDomainHttps", + path: cdnCustomDomainHttpsPath, + Types: map[string]schema.ComplexTypeSpec{ + "azure-native:cdn:CdnCertificateSourceParameters": cdnCertificateSourceParametersTypeSpec, + "azure-native:cdn:KeyVaultCertificateSourceParameters": keyVaultCertificateSourceParametersTypeSpec, + "azure-native:cdn:HttpsConfiguration": httpsConfigType, + }, + LegacySchema: &schema.ResourceSpec{ + ObjectTypeSpec: schema.ObjectTypeSpec{ + Description: "Enables or disables HTTPS on a CDN custom domain.", + Type: "object", + Properties: cdnCustomDomainHttpsProperties, + }, + InputProperties: cdnCustomDomainHttpsProperties, + RequiredInputs: []string{"customDomainId", "httpsEnabled"}, + }, + Meta: &AzureAPIResource{ + Path: cdnCustomDomainHttpsPath, + PutParameters: []AzureAPIParameter{ + {Name: subscriptionId, Location: "path", IsRequired: true, Value: &AzureAPIProperty{Type: "string"}}, + {Name: resourceGroupName, Location: "path", IsRequired: true, Value: &AzureAPIProperty{Type: "string"}}, + {Name: "profileName", Location: "path", IsRequired: true, Value: &AzureAPIProperty{Type: "string"}}, + {Name: "endpointName", Location: "path", IsRequired: true, Value: &AzureAPIProperty{Type: "string"}}, + {Name: "customDomainName", Location: "path", IsRequired: true, Value: &AzureAPIProperty{Type: "string"}}, + { + Name: "properties", + Location: "body", + Body: &AzureAPIType{ + Properties: map[string]AzureAPIProperty{ + "httpsEnabled": { + Type: "boolean", + }, + "certificateSource": { + Type: "string", + }, + "protocolType": { + Type: "string", + }, + "minimumTlsVersion": { + Type: "string", + }, + }, + RequiredProperties: []string{"httpsEnabled"}, + }, + }, + }, + }, + Create: func(ctx context.Context, id string, properties resource.PropertyMap) (map[string]any, error) { + // For create, ensure we have either a valid customDomainId in properties or a valid id path + props := properties.Mappable() + if _, hasId := props["customDomainId"].(string); !hasId && !strings.Contains(id, "/customDomains/") { + return nil, errors.New("missing required property 'customDomainId' or invalid resource ID") + } + return updateCdnCustomDomainHttps(ctx, id, properties, azureClient, apiVersion) + }, + Read: func(ctx context.Context, id string, properties resource.PropertyMap) (map[string]any, bool, error) { + // Extract the custom domain ID from the CustomDomainHttps ID + cdnCustomDomainId := strings.TrimSuffix(id, "/customHttps") + + // Read the custom domain to get its HTTPS settings + customDomain, err := azureClient.Get(ctx, cdnCustomDomainId, apiVersion, nil) + if err != nil { + if azure.IsNotFound(err) { + return nil, false, nil + } + return nil, false, err + } + + // Extract HTTPS settings + result := map[string]any{ + "customDomainId": cdnCustomDomainId, + "httpsEnabled": false, + } + + props, ok := customDomain["properties"].(map[string]any) + if !ok { + return result, true, nil + } + + provisioningState, ok := props["customHttpsProvisioningState"].(string) + if !ok { + return result, true, nil + } + + // If HTTPS is enabled + if provisioningState == "Enabled" { + result["httpsEnabled"] = true + + // Extract HTTPS parameters if available + httpsConfig := map[string]any{} + + if httpsParams, ok := props["customHttpsParameters"].(map[string]any); ok { + httpsConfig["certificateSource"] = httpsParams["certificateSource"] + httpsConfig["protocolType"] = httpsParams["protocolType"] + + if minTls, ok := httpsParams["minimumTlsVersion"]; ok { + httpsConfig["minimumTlsVersion"] = minTls + } + + if certParams, ok := httpsParams["certificateSourceParameters"].(map[string]any); ok { + if typeName, ok := certParams["typeName"].(string); ok { + if typeName == "CdnCertificateSourceParameters" { + cdnParams := map[string]any{} + if certType, ok := certParams["certificateType"].(string); ok { + cdnParams["certificateType"] = certType + } + httpsConfig["cdnCertificateSourceParameters"] = cdnParams + } else if typeName == "KeyVaultCertificateSourceParameters" { + kvParams := map[string]any{} + if val, ok := certParams["subscriptionId"].(string); ok { + kvParams["subscriptionId"] = val + } + if val, ok := certParams["resourceGroupName"].(string); ok { + kvParams["resourceGroupName"] = val + } + if val, ok := certParams["vaultName"].(string); ok { + kvParams["vaultName"] = val + } + if val, ok := certParams["secretName"].(string); ok { + kvParams["secretName"] = val + } + if val, ok := certParams["secretVersion"].(string); ok { + kvParams["secretVersion"] = val + } + httpsConfig["keyVaultCertificateSourceParameters"] = kvParams + } + } + } + } + + result["httpsConfiguration"] = httpsConfig + } + + return result, true, nil + }, + Update: func(ctx context.Context, id string, news, olds resource.PropertyMap) (map[string]any, error) { + return updateCdnCustomDomainHttps(ctx, id, news, azureClient, apiVersion) + }, + Delete: func(ctx context.Context, id string, inputs, state resource.PropertyMap) error { + // Extract the custom domain ID + customDomainId := strings.TrimSuffix(id, "/customHttps") + + // For delete, we'll disable HTTPS + path := customDomainId + "/disableCustomHttps" + + queryParams := map[string]any{ + "api-version": apiVersion, + } + + _, err := azureClient.Post(ctx, path, map[string]any{}, queryParams) + return err + }, + } +} + +func updateCdnCustomDomainHttps(ctx context.Context, id string, properties resource.PropertyMap, azureClient azure.AzureClient, apiVersion string) (map[string]any, error) { + props := properties.Mappable() + + // Extract or get the custom domain ID + customDomainId, ok := props["customDomainId"].(string) + if !ok { + // If not provided directly, extract from the resource ID + customDomainId = strings.TrimSuffix(id, "/customHttps") + } + + httpsEnabled, ok := props["httpsEnabled"].(bool) + if !ok { + return nil, errors.New("missing required property 'httpsEnabled'") + } + + queryParams := map[string]any{ + "api-version": apiVersion, + } + + // If HTTPS is being disabled + if !httpsEnabled { + path := customDomainId + "/disableCustomHttps" + _, err := azureClient.Post(ctx, path, map[string]any{}, queryParams) + if err != nil { + return nil, err + } + return props, nil + } + + // HTTPS is being enabled + path := customDomainId + "/enableCustomHttps" + + // Get the HTTPS configuration + httpsConfig, ok := props["httpsConfiguration"].(map[string]any) + if !ok { + return nil, errors.New("missing required property 'httpsConfiguration' when httpsEnabled is true") + } + + // Certificate source is required + certificateSource, ok := httpsConfig["certificateSource"].(string) + if !ok { + return nil, errors.New("missing required property 'certificateSource' in httpsConfiguration") + } + + // Protocol type is required + protocolType, ok := httpsConfig["protocolType"].(string) + if !ok { + return nil, errors.New("missing required property 'protocolType' in httpsConfiguration") + } + + // Prepare the request body for enabling HTTPS + body := map[string]any{ + "certificateSource": certificateSource, + "protocolType": protocolType, + } + + // Optional TLS version + if minimumTlsVersion, ok := httpsConfig["minimumTlsVersion"].(string); ok { + body["minimumTlsVersion"] = minimumTlsVersion + } + + // Configure certificate source parameters based on certificate source + certificateSourceParams := map[string]any{} + + if certificateSource == CertificateSourceCdn { + cdnParams, hasCdnParams := httpsConfig["cdnCertificateSourceParameters"].(map[string]any) + if hasCdnParams { + if certificateType, ok := cdnParams["certificateType"].(string); ok { + certificateSourceParams["certificateType"] = certificateType + } else { + // Default to Shared if not specified + certificateSourceParams["certificateType"] = "Shared" + } + } else { + // Default to Shared if not specified + certificateSourceParams["certificateType"] = "Shared" + } + certificateSourceParams["typeName"] = "CdnCertificateSourceParameters" + } else if certificateSource == CertificateSourceKeyVault { + // Get KeyVault parameters + kvParams, hasKvParams := httpsConfig["keyVaultCertificateSourceParameters"].(map[string]any) + if !hasKvParams { + return nil, errors.New("missing required property 'keyVaultCertificateSourceParameters' for AzureKeyVault certificate source") + } + + // Validate required parameters for Key Vault + requiredKvParams := []string{ + "subscriptionId", + "resourceGroupName", + "vaultName", + "secretName", + } + + for _, param := range requiredKvParams { + if _, ok := kvParams[param].(string); !ok { + return nil, errors.New("missing required property '" + param + "' in keyVaultCertificateSourceParameters") + } + } + + // Copy all parameters to the request + for k, v := range kvParams { + certificateSourceParams[k] = v + } + + // Default update and delete rules if not specified + if _, hasUpdateRule := certificateSourceParams["updateRule"]; !hasUpdateRule { + certificateSourceParams["updateRule"] = "NoAction" + } + + if _, hasDeleteRule := certificateSourceParams["deleteRule"]; !hasDeleteRule { + certificateSourceParams["deleteRule"] = "NoAction" + } + + certificateSourceParams["typeName"] = "KeyVaultCertificateSourceParameters" + } + + body["certificateSourceParameters"] = certificateSourceParams + + _, err := azureClient.Post(ctx, path, body, queryParams) + if err != nil { + return nil, err + } + + // Return the updated properties + return map[string]any{ + "customDomainId": customDomainId, + "httpsEnabled": httpsEnabled, + "httpsConfiguration": httpsConfig, + }, nil +} \ No newline at end of file diff --git a/provider/pkg/resources/customresources/customresources.go b/provider/pkg/resources/customresources/customresources.go index 6266f837a833..232d05a87d84 100644 --- a/provider/pkg/resources/customresources/customresources.go +++ b/provider/pkg/resources/customresources/customresources.go @@ -257,6 +257,7 @@ func BuildCustomResources(env *azureEnv.Environment, protectedItem, pimRoleManagementPolicy, pimRoleEligibilitySchedule, + cdnCustomDomainHttps(azureClient), } // For Key Vault, we need to use separate token sources for azidentity and for the legacy auth. The diff --git a/reports/tokenPaths.json b/reports/tokenPaths.json index 58b056965ce1..7c22553f61d6 100644 --- a/reports/tokenPaths.json +++ b/reports/tokenPaths.json @@ -2612,6 +2612,7 @@ "azure-native:cdn:AFDOriginGroup": "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Cdn/profiles/{profileName}/originGroups/{originGroupName}", "azure-native:cdn:AFDTargetGroup": "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Cdn/profiles/{profileName}/targetGroups/{targetGroupName}", "azure-native:cdn:CustomDomain": "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Cdn/profiles/{profileName}/endpoints/{endpointName}/customDomains/{customDomainName}", + "azure-native:cdn:CustomDomainHttps": "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Cdn/profiles/{profileName}/endpoints/{endpointName}/customDomains/{customDomainName}/customHttps", "azure-native:cdn:Endpoint": "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Cdn/profiles/{profileName}/endpoints/{endpointName}", "azure-native:cdn:KeyGroup": "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Cdn/profiles/{profileName}/keyGroups/{keyGroupName}", "azure-native:cdn:Origin": "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Cdn/profiles/{profileName}/endpoints/{endpointName}/origins/{originName}", diff --git a/sdk/dotnet/Cdn/CustomDomainHttps.cs b/sdk/dotnet/Cdn/CustomDomainHttps.cs new file mode 100644 index 000000000000..e27be230cd7f --- /dev/null +++ b/sdk/dotnet/Cdn/CustomDomainHttps.cs @@ -0,0 +1,104 @@ +// *** WARNING: this file was generated by pulumi-language-dotnet. *** +// *** Do not edit by hand unless you're certain you know what you are doing! *** + +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Threading.Tasks; +using Pulumi.Serialization; + +namespace Pulumi.AzureNative.Cdn +{ + /// + /// Enables or disables HTTPS on a CDN custom domain. + /// + [AzureNativeResourceType("azure-native:cdn:CustomDomainHttps")] + public partial class CustomDomainHttps : global::Pulumi.CustomResource + { + /// + /// The resource ID of the CDN Custom Domain. + /// + [Output("customDomainId")] + public Output CustomDomainId { get; private set; } = null!; + + /// + /// HTTPS configuration when HTTPS is enabled. + /// + [Output("httpsConfiguration")] + public Output HttpsConfiguration { get; private set; } = null!; + + /// + /// Whether HTTPS is enabled on the custom domain. + /// + [Output("httpsEnabled")] + public Output HttpsEnabled { get; private set; } = null!; + + + /// + /// Create a CustomDomainHttps resource with the given unique name, arguments, and options. + /// + /// + /// The unique name of the resource + /// The arguments used to populate this resource's properties + /// A bag of options that control this resource's behavior + public CustomDomainHttps(string name, CustomDomainHttpsArgs args, CustomResourceOptions? options = null) + : base("azure-native:cdn:CustomDomainHttps", name, args ?? new CustomDomainHttpsArgs(), MakeResourceOptions(options, "")) + { + } + + private CustomDomainHttps(string name, Input id, CustomResourceOptions? options = null) + : base("azure-native:cdn:CustomDomainHttps", name, null, MakeResourceOptions(options, id)) + { + } + + private static CustomResourceOptions MakeResourceOptions(CustomResourceOptions? options, Input? id) + { + var defaultOptions = new CustomResourceOptions + { + Version = Utilities.Version, + }; + var merged = CustomResourceOptions.Merge(defaultOptions, options); + // Override the ID if one was specified for consistency with other language SDKs. + merged.Id = id ?? merged.Id; + return merged; + } + /// + /// Get an existing CustomDomainHttps resource's state with the given name, ID, and optional extra + /// properties used to qualify the lookup. + /// + /// + /// The unique name of the resulting resource. + /// The unique provider ID of the resource to lookup. + /// A bag of options that control this resource's behavior + public static CustomDomainHttps Get(string name, Input id, CustomResourceOptions? options = null) + { + return new CustomDomainHttps(name, id, options); + } + } + + public sealed class CustomDomainHttpsArgs : global::Pulumi.ResourceArgs + { + /// + /// The resource ID of the CDN Custom Domain. + /// + [Input("customDomainId", required: true)] + public Input CustomDomainId { get; set; } = null!; + + /// + /// HTTPS configuration when HTTPS is enabled. + /// + [Input("httpsConfiguration")] + public Input? HttpsConfiguration { get; set; } + + /// + /// Whether HTTPS is enabled on the custom domain. + /// + [Input("httpsEnabled", required: true)] + public Input HttpsEnabled { get; set; } = null!; + + public CustomDomainHttpsArgs() + { + } + public static new CustomDomainHttpsArgs Empty => new CustomDomainHttpsArgs(); + } +} diff --git a/sdk/dotnet/Cdn/Inputs/CdnCertificateSourceParametersArgs.cs b/sdk/dotnet/Cdn/Inputs/CdnCertificateSourceParametersArgs.cs new file mode 100644 index 000000000000..854d28871efc --- /dev/null +++ b/sdk/dotnet/Cdn/Inputs/CdnCertificateSourceParametersArgs.cs @@ -0,0 +1,29 @@ +// *** WARNING: this file was generated by pulumi-language-dotnet. *** +// *** Do not edit by hand unless you're certain you know what you are doing! *** + +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Threading.Tasks; +using Pulumi.Serialization; + +namespace Pulumi.AzureNative.Cdn.Inputs +{ + + /// + /// CDN certificate parameters for custom domain HTTPS configuration. + /// + public sealed class CdnCertificateSourceParametersArgs : global::Pulumi.ResourceArgs + { + /// + /// Certificate type for CDN managed certificates. One of: 'Shared', 'Dedicated'. + /// + [Input("certificateType")] + public Input? CertificateType { get; set; } + + public CdnCertificateSourceParametersArgs() + { + } + public static new CdnCertificateSourceParametersArgs Empty => new CdnCertificateSourceParametersArgs(); + } +} diff --git a/sdk/dotnet/Cdn/Inputs/HttpsConfigurationArgs.cs b/sdk/dotnet/Cdn/Inputs/HttpsConfigurationArgs.cs new file mode 100644 index 000000000000..da887d930544 --- /dev/null +++ b/sdk/dotnet/Cdn/Inputs/HttpsConfigurationArgs.cs @@ -0,0 +1,53 @@ +// *** WARNING: this file was generated by pulumi-language-dotnet. *** +// *** Do not edit by hand unless you're certain you know what you are doing! *** + +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Threading.Tasks; +using Pulumi.Serialization; + +namespace Pulumi.AzureNative.Cdn.Inputs +{ + + /// + /// HTTPS configuration for CDN custom domain. + /// + public sealed class HttpsConfigurationArgs : global::Pulumi.ResourceArgs + { + /// + /// Parameters required for using CDN managed certificates. + /// + [Input("cdnCertificateSourceParameters")] + public Input? CdnCertificateSourceParameters { get; set; } + + /// + /// Certificate source for the custom domain. One of: 'Cdn', 'AzureKeyVault'. + /// + [Input("certificateSource", required: true)] + public Input CertificateSource { get; set; } = null!; + + /// + /// Parameters required for using certificates stored in Azure KeyVault. + /// + [Input("keyVaultCertificateSourceParameters")] + public Input? KeyVaultCertificateSourceParameters { get; set; } + + /// + /// TLS protocol version that will be used for HTTPS. One of: 'None', 'TLS10', 'TLS12'. + /// + [Input("minimumTlsVersion")] + public Input? MinimumTlsVersion { get; set; } + + /// + /// TLS extension protocol. One of: 'ServerNameIndication', 'IPBased'. + /// + [Input("protocolType", required: true)] + public Input ProtocolType { get; set; } = null!; + + public HttpsConfigurationArgs() + { + } + public static new HttpsConfigurationArgs Empty => new HttpsConfigurationArgs(); + } +} diff --git a/sdk/dotnet/Cdn/Inputs/KeyVaultCertificateSourceParametersArgs.cs b/sdk/dotnet/Cdn/Inputs/KeyVaultCertificateSourceParametersArgs.cs new file mode 100644 index 000000000000..b2458d50a645 --- /dev/null +++ b/sdk/dotnet/Cdn/Inputs/KeyVaultCertificateSourceParametersArgs.cs @@ -0,0 +1,53 @@ +// *** WARNING: this file was generated by pulumi-language-dotnet. *** +// *** Do not edit by hand unless you're certain you know what you are doing! *** + +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Threading.Tasks; +using Pulumi.Serialization; + +namespace Pulumi.AzureNative.Cdn.Inputs +{ + + /// + /// Key Vault certificate parameters for custom domain HTTPS configuration. + /// + public sealed class KeyVaultCertificateSourceParametersArgs : global::Pulumi.ResourceArgs + { + /// + /// Resource group containing the Key Vault. + /// + [Input("resourceGroupName", required: true)] + public Input ResourceGroupName { get; set; } = null!; + + /// + /// Name of the secret in Key Vault. + /// + [Input("secretName", required: true)] + public Input SecretName { get; set; } = null!; + + /// + /// Version of the secret in Key Vault. + /// + [Input("secretVersion")] + public Input? SecretVersion { get; set; } + + /// + /// Azure subscription ID containing the Key Vault. + /// + [Input("subscriptionId", required: true)] + public Input SubscriptionId { get; set; } = null!; + + /// + /// Name of the Key Vault. + /// + [Input("vaultName", required: true)] + public Input VaultName { get; set; } = null!; + + public KeyVaultCertificateSourceParametersArgs() + { + } + public static new KeyVaultCertificateSourceParametersArgs Empty => new KeyVaultCertificateSourceParametersArgs(); + } +} diff --git a/sdk/dotnet/Cdn/Outputs/CdnCertificateSourceParameters.cs b/sdk/dotnet/Cdn/Outputs/CdnCertificateSourceParameters.cs new file mode 100644 index 000000000000..73ab0fe118c9 --- /dev/null +++ b/sdk/dotnet/Cdn/Outputs/CdnCertificateSourceParameters.cs @@ -0,0 +1,30 @@ +// *** WARNING: this file was generated by pulumi-language-dotnet. *** +// *** Do not edit by hand unless you're certain you know what you are doing! *** + +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Threading.Tasks; +using Pulumi.Serialization; + +namespace Pulumi.AzureNative.Cdn.Outputs +{ + + /// + /// CDN certificate parameters for custom domain HTTPS configuration. + /// + [OutputType] + public sealed class CdnCertificateSourceParameters + { + /// + /// Certificate type for CDN managed certificates. One of: 'Shared', 'Dedicated'. + /// + public readonly string? CertificateType; + + [OutputConstructor] + private CdnCertificateSourceParameters(string? certificateType) + { + CertificateType = certificateType; + } + } +} diff --git a/sdk/dotnet/Cdn/Outputs/HttpsConfiguration.cs b/sdk/dotnet/Cdn/Outputs/HttpsConfiguration.cs new file mode 100644 index 000000000000..c0aabe176c40 --- /dev/null +++ b/sdk/dotnet/Cdn/Outputs/HttpsConfiguration.cs @@ -0,0 +1,59 @@ +// *** WARNING: this file was generated by pulumi-language-dotnet. *** +// *** Do not edit by hand unless you're certain you know what you are doing! *** + +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Threading.Tasks; +using Pulumi.Serialization; + +namespace Pulumi.AzureNative.Cdn.Outputs +{ + + /// + /// HTTPS configuration for CDN custom domain. + /// + [OutputType] + public sealed class HttpsConfiguration + { + /// + /// Parameters required for using CDN managed certificates. + /// + public readonly Outputs.CdnCertificateSourceParameters? CdnCertificateSourceParameters; + /// + /// Certificate source for the custom domain. One of: 'Cdn', 'AzureKeyVault'. + /// + public readonly string CertificateSource; + /// + /// Parameters required for using certificates stored in Azure KeyVault. + /// + public readonly Outputs.KeyVaultCertificateSourceParameters? KeyVaultCertificateSourceParameters; + /// + /// TLS protocol version that will be used for HTTPS. One of: 'None', 'TLS10', 'TLS12'. + /// + public readonly string? MinimumTlsVersion; + /// + /// TLS extension protocol. One of: 'ServerNameIndication', 'IPBased'. + /// + public readonly string ProtocolType; + + [OutputConstructor] + private HttpsConfiguration( + Outputs.CdnCertificateSourceParameters? cdnCertificateSourceParameters, + + string certificateSource, + + Outputs.KeyVaultCertificateSourceParameters? keyVaultCertificateSourceParameters, + + string? minimumTlsVersion, + + string protocolType) + { + CdnCertificateSourceParameters = cdnCertificateSourceParameters; + CertificateSource = certificateSource; + KeyVaultCertificateSourceParameters = keyVaultCertificateSourceParameters; + MinimumTlsVersion = minimumTlsVersion; + ProtocolType = protocolType; + } + } +} diff --git a/sdk/dotnet/Cdn/Outputs/KeyVaultCertificateSourceParameters.cs b/sdk/dotnet/Cdn/Outputs/KeyVaultCertificateSourceParameters.cs new file mode 100644 index 000000000000..2c9440ee0205 --- /dev/null +++ b/sdk/dotnet/Cdn/Outputs/KeyVaultCertificateSourceParameters.cs @@ -0,0 +1,59 @@ +// *** WARNING: this file was generated by pulumi-language-dotnet. *** +// *** Do not edit by hand unless you're certain you know what you are doing! *** + +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Threading.Tasks; +using Pulumi.Serialization; + +namespace Pulumi.AzureNative.Cdn.Outputs +{ + + /// + /// Key Vault certificate parameters for custom domain HTTPS configuration. + /// + [OutputType] + public sealed class KeyVaultCertificateSourceParameters + { + /// + /// Resource group containing the Key Vault. + /// + public readonly string ResourceGroupName; + /// + /// Name of the secret in Key Vault. + /// + public readonly string SecretName; + /// + /// Version of the secret in Key Vault. + /// + public readonly string? SecretVersion; + /// + /// Azure subscription ID containing the Key Vault. + /// + public readonly string SubscriptionId; + /// + /// Name of the Key Vault. + /// + public readonly string VaultName; + + [OutputConstructor] + private KeyVaultCertificateSourceParameters( + string resourceGroupName, + + string secretName, + + string? secretVersion, + + string subscriptionId, + + string vaultName) + { + ResourceGroupName = resourceGroupName; + SecretName = secretName; + SecretVersion = secretVersion; + SubscriptionId = subscriptionId; + VaultName = vaultName; + } + } +} diff --git a/sdk/nodejs/cdn/customDomainHttps.ts b/sdk/nodejs/cdn/customDomainHttps.ts new file mode 100644 index 000000000000..5af07ebbb333 --- /dev/null +++ b/sdk/nodejs/cdn/customDomainHttps.ts @@ -0,0 +1,99 @@ +// *** WARNING: this file was generated by pulumi-language-nodejs. *** +// *** Do not edit by hand unless you're certain you know what you are doing! *** + +import * as pulumi from "@pulumi/pulumi"; +import * as inputs from "../types/input"; +import * as outputs from "../types/output"; +import * as enums from "../types/enums"; +import * as utilities from "../utilities"; + +/** + * Enables or disables HTTPS on a CDN custom domain. + */ +export class CustomDomainHttps extends pulumi.CustomResource { + /** + * Get an existing CustomDomainHttps resource's state with the given name, ID, and optional extra + * properties used to qualify the lookup. + * + * @param name The _unique_ name of the resulting resource. + * @param id The _unique_ provider ID of the resource to lookup. + * @param opts Optional settings to control the behavior of the CustomResource. + */ + public static get(name: string, id: pulumi.Input, opts?: pulumi.CustomResourceOptions): CustomDomainHttps { + return new CustomDomainHttps(name, undefined as any, { ...opts, id: id }); + } + + /** @internal */ + public static readonly __pulumiType = 'azure-native:cdn:CustomDomainHttps'; + + /** + * Returns true if the given object is an instance of CustomDomainHttps. This is designed to work even + * when multiple copies of the Pulumi SDK have been loaded into the same process. + */ + public static isInstance(obj: any): obj is CustomDomainHttps { + if (obj === undefined || obj === null) { + return false; + } + return obj['__pulumiType'] === CustomDomainHttps.__pulumiType; + } + + /** + * The resource ID of the CDN Custom Domain. + */ + public readonly customDomainId!: pulumi.Output; + /** + * HTTPS configuration when HTTPS is enabled. + */ + public readonly httpsConfiguration!: pulumi.Output; + /** + * Whether HTTPS is enabled on the custom domain. + */ + public readonly httpsEnabled!: pulumi.Output; + + /** + * Create a CustomDomainHttps resource with the given unique name, arguments, and options. + * + * @param name The _unique_ name of the resource. + * @param args The arguments to use to populate this resource's properties. + * @param opts A bag of options that control this resource's behavior. + */ + constructor(name: string, args: CustomDomainHttpsArgs, opts?: pulumi.CustomResourceOptions) { + let resourceInputs: pulumi.Inputs = {}; + opts = opts || {}; + if (!opts.id) { + if ((!args || args.customDomainId === undefined) && !opts.urn) { + throw new Error("Missing required property 'customDomainId'"); + } + if ((!args || args.httpsEnabled === undefined) && !opts.urn) { + throw new Error("Missing required property 'httpsEnabled'"); + } + resourceInputs["customDomainId"] = args ? args.customDomainId : undefined; + resourceInputs["httpsConfiguration"] = args ? args.httpsConfiguration : undefined; + resourceInputs["httpsEnabled"] = args ? args.httpsEnabled : undefined; + } else { + resourceInputs["customDomainId"] = undefined /*out*/; + resourceInputs["httpsConfiguration"] = undefined /*out*/; + resourceInputs["httpsEnabled"] = undefined /*out*/; + } + opts = pulumi.mergeOptions(utilities.resourceOptsDefaults(), opts); + super(CustomDomainHttps.__pulumiType, name, resourceInputs, opts); + } +} + +/** + * The set of arguments for constructing a CustomDomainHttps resource. + */ +export interface CustomDomainHttpsArgs { + /** + * The resource ID of the CDN Custom Domain. + */ + customDomainId: pulumi.Input; + /** + * HTTPS configuration when HTTPS is enabled. + */ + httpsConfiguration?: pulumi.Input; + /** + * Whether HTTPS is enabled on the custom domain. + */ + httpsEnabled: pulumi.Input; +} diff --git a/sdk/nodejs/cdn/index.ts b/sdk/nodejs/cdn/index.ts index f1fae222d584..30c3c9efd8b4 100644 --- a/sdk/nodejs/cdn/index.ts +++ b/sdk/nodejs/cdn/index.ts @@ -35,6 +35,11 @@ export type CustomDomain = import("./customDomain").CustomDomain; export const CustomDomain: typeof import("./customDomain").CustomDomain = null as any; utilities.lazyLoad(exports, ["CustomDomain"], () => require("./customDomain")); +export { CustomDomainHttpsArgs } from "./customDomainHttps"; +export type CustomDomainHttps = import("./customDomainHttps").CustomDomainHttps; +export const CustomDomainHttps: typeof import("./customDomainHttps").CustomDomainHttps = null as any; +utilities.lazyLoad(exports, ["CustomDomainHttps"], () => require("./customDomainHttps")); + export { EndpointArgs } from "./endpoint"; export type Endpoint = import("./endpoint").Endpoint; export const Endpoint: typeof import("./endpoint").Endpoint = null as any; @@ -210,6 +215,8 @@ const _module = { return new AFDTargetGroup(name, undefined, { urn }) case "azure-native:cdn:CustomDomain": return new CustomDomain(name, undefined, { urn }) + case "azure-native:cdn:CustomDomainHttps": + return new CustomDomainHttps(name, undefined, { urn }) case "azure-native:cdn:Endpoint": return new Endpoint(name, undefined, { urn }) case "azure-native:cdn:KeyGroup": diff --git a/sdk/nodejs/tsconfig.json b/sdk/nodejs/tsconfig.json index 60d9f27aaa6e..7a57dd9c06a3 100644 --- a/sdk/nodejs/tsconfig.json +++ b/sdk/nodejs/tsconfig.json @@ -1058,6 +1058,7 @@ "cdn/afdoriginGroup.ts", "cdn/afdtargetGroup.ts", "cdn/customDomain.ts", + "cdn/customDomainHttps.ts", "cdn/endpoint.ts", "cdn/getAFDCustomDomain.ts", "cdn/getAFDEndpoint.ts", diff --git a/sdk/nodejs/types/input.ts b/sdk/nodejs/types/input.ts index 28f9c801191a..266f4fd5f596 100644 --- a/sdk/nodejs/types/input.ts +++ b/sdk/nodejs/types/input.ts @@ -39533,6 +39533,16 @@ export namespace cdn { typeName: pulumi.Input<"DeliveryRuleCacheKeyQueryStringBehaviorActionParameters">; } + /** + * CDN certificate parameters for custom domain HTTPS configuration. + */ + export interface CdnCertificateSourceParametersArgs { + /** + * Certificate type for CDN managed certificates. One of: 'Shared', 'Dedicated'. + */ + certificateType?: pulumi.Input; + } + /** * Defines the parameters for ClientPort match conditions */ @@ -40492,6 +40502,32 @@ export namespace cdn { }; } + /** + * HTTPS configuration for CDN custom domain. + */ + export interface HttpsConfigurationArgs { + /** + * Parameters required for using CDN managed certificates. + */ + cdnCertificateSourceParameters?: pulumi.Input; + /** + * Certificate source for the custom domain. One of: 'Cdn', 'AzureKeyVault'. + */ + certificateSource: pulumi.Input; + /** + * Parameters required for using certificates stored in Azure KeyVault. + */ + keyVaultCertificateSourceParameters?: pulumi.Input; + /** + * TLS protocol version that will be used for HTTPS. One of: 'None', 'TLS10', 'TLS12'. + */ + minimumTlsVersion?: pulumi.Input; + /** + * TLS extension protocol. One of: 'ServerNameIndication', 'IPBased'. + */ + protocolType: pulumi.Input; + } + /** * Defines the parameters for IsDevice match conditions */ @@ -40528,6 +40564,32 @@ export namespace cdn { }; } + /** + * Key Vault certificate parameters for custom domain HTTPS configuration. + */ + export interface KeyVaultCertificateSourceParametersArgs { + /** + * Resource group containing the Key Vault. + */ + resourceGroupName: pulumi.Input; + /** + * Name of the secret in Key Vault. + */ + secretName: pulumi.Input; + /** + * Version of the secret in Key Vault. + */ + secretVersion?: pulumi.Input; + /** + * Azure subscription ID containing the Key Vault. + */ + subscriptionId: pulumi.Input; + /** + * Name of the Key Vault. + */ + vaultName: pulumi.Input; + } + /** * Describes the parameters for using a user's KeyVault for URL Signing Key. */ diff --git a/sdk/nodejs/types/output.ts b/sdk/nodejs/types/output.ts index b4ac683229f6..2bf1add9ce47 100644 --- a/sdk/nodejs/types/output.ts +++ b/sdk/nodejs/types/output.ts @@ -48067,6 +48067,16 @@ export namespace cdn { typeName: "DeliveryRuleCacheKeyQueryStringBehaviorActionParameters"; } + /** + * CDN certificate parameters for custom domain HTTPS configuration. + */ + export interface CdnCertificateSourceParameters { + /** + * Certificate type for CDN managed certificates. One of: 'Shared', 'Dedicated'. + */ + certificateType?: string; + } + /** * Defines the parameters for using CDN managed certificate for securing custom domain. */ @@ -49126,6 +49136,32 @@ export namespace cdn { }; } + /** + * HTTPS configuration for CDN custom domain. + */ + export interface HttpsConfiguration { + /** + * Parameters required for using CDN managed certificates. + */ + cdnCertificateSourceParameters?: outputs.cdn.CdnCertificateSourceParameters; + /** + * Certificate source for the custom domain. One of: 'Cdn', 'AzureKeyVault'. + */ + certificateSource: string; + /** + * Parameters required for using certificates stored in Azure KeyVault. + */ + keyVaultCertificateSourceParameters?: outputs.cdn.KeyVaultCertificateSourceParameters; + /** + * TLS protocol version that will be used for HTTPS. One of: 'None', 'TLS10', 'TLS12'. + */ + minimumTlsVersion?: string; + /** + * TLS extension protocol. One of: 'ServerNameIndication', 'IPBased'. + */ + protocolType: string; + } + /** * Defines the parameters for IsDevice match conditions */ @@ -49162,6 +49198,32 @@ export namespace cdn { }; } + /** + * Key Vault certificate parameters for custom domain HTTPS configuration. + */ + export interface KeyVaultCertificateSourceParameters { + /** + * Resource group containing the Key Vault. + */ + resourceGroupName: string; + /** + * Name of the secret in Key Vault. + */ + secretName: string; + /** + * Version of the secret in Key Vault. + */ + secretVersion?: string; + /** + * Azure subscription ID containing the Key Vault. + */ + subscriptionId: string; + /** + * Name of the Key Vault. + */ + vaultName: string; + } + /** * Describes the parameters for using a user's KeyVault certificate for securing custom domain. */ diff --git a/sdk/python/pulumi_azure_native/__init__.py b/sdk/python/pulumi_azure_native/__init__.py index ad5f55d63ff1..525e35c6f4c8 100644 --- a/sdk/python/pulumi_azure_native/__init__.py +++ b/sdk/python/pulumi_azure_native/__init__.py @@ -1496,6 +1496,7 @@ "azure-native:cdn:AFDOriginGroup": "AFDOriginGroup", "azure-native:cdn:AFDTargetGroup": "AFDTargetGroup", "azure-native:cdn:CustomDomain": "CustomDomain", + "azure-native:cdn:CustomDomainHttps": "CustomDomainHttps", "azure-native:cdn:Endpoint": "Endpoint", "azure-native:cdn:KeyGroup": "KeyGroup", "azure-native:cdn:Origin": "Origin", diff --git a/sdk/python/pulumi_azure_native/cdn/__init__.py b/sdk/python/pulumi_azure_native/cdn/__init__.py index b02ccf745e7e..483f757dda71 100644 --- a/sdk/python/pulumi_azure_native/cdn/__init__.py +++ b/sdk/python/pulumi_azure_native/cdn/__init__.py @@ -13,6 +13,7 @@ from .afd_origin_group import * from .afd_target_group import * from .custom_domain import * +from .custom_domain_https import * from .endpoint import * from .get_afd_custom_domain import * from .get_afd_endpoint import * diff --git a/sdk/python/pulumi_azure_native/cdn/_inputs.py b/sdk/python/pulumi_azure_native/cdn/_inputs.py index 61317c536ee1..65b814bd77d1 100644 --- a/sdk/python/pulumi_azure_native/cdn/_inputs.py +++ b/sdk/python/pulumi_azure_native/cdn/_inputs.py @@ -31,6 +31,8 @@ 'CacheExpirationActionParametersArgsDict', 'CacheKeyQueryStringActionParametersArgs', 'CacheKeyQueryStringActionParametersArgsDict', + 'CdnCertificateSourceParametersArgs', + 'CdnCertificateSourceParametersArgsDict', 'ClientPortMatchConditionParametersArgs', 'ClientPortMatchConditionParametersArgsDict', 'CompressionSettingsArgs', @@ -113,8 +115,12 @@ 'HttpErrorRangeParametersArgsDict', 'HttpVersionMatchConditionParametersArgs', 'HttpVersionMatchConditionParametersArgsDict', + 'HttpsConfigurationArgs', + 'HttpsConfigurationArgsDict', 'IsDeviceMatchConditionParametersArgs', 'IsDeviceMatchConditionParametersArgsDict', + 'KeyVaultCertificateSourceParametersArgs', + 'KeyVaultCertificateSourceParametersArgsDict', 'KeyVaultSigningKeyParametersArgs', 'KeyVaultSigningKeyParametersArgsDict', 'LoadBalancingSettingsParametersArgs', @@ -749,6 +755,42 @@ def query_parameters(self, value: Optional[pulumi.Input[builtins.str]]): pulumi.set(self, "query_parameters", value) +if not MYPY: + class CdnCertificateSourceParametersArgsDict(TypedDict): + """ + CDN certificate parameters for custom domain HTTPS configuration. + """ + certificate_type: NotRequired[pulumi.Input[builtins.str]] + """ + Certificate type for CDN managed certificates. One of: 'Shared', 'Dedicated'. + """ +elif False: + CdnCertificateSourceParametersArgsDict: TypeAlias = Mapping[str, Any] + +@pulumi.input_type +class CdnCertificateSourceParametersArgs: + def __init__(__self__, *, + certificate_type: Optional[pulumi.Input[builtins.str]] = None): + """ + CDN certificate parameters for custom domain HTTPS configuration. + :param pulumi.Input[builtins.str] certificate_type: Certificate type for CDN managed certificates. One of: 'Shared', 'Dedicated'. + """ + if certificate_type is not None: + pulumi.set(__self__, "certificate_type", certificate_type) + + @property + @pulumi.getter(name="certificateType") + def certificate_type(self) -> Optional[pulumi.Input[builtins.str]]: + """ + Certificate type for CDN managed certificates. One of: 'Shared', 'Dedicated'. + """ + return pulumi.get(self, "certificate_type") + + @certificate_type.setter + def certificate_type(self, value: Optional[pulumi.Input[builtins.str]]): + pulumi.set(self, "certificate_type", value) + + if not MYPY: class ClientPortMatchConditionParametersArgsDict(TypedDict): """ @@ -3808,6 +3850,120 @@ def transforms(self, value: Optional[pulumi.Input[Sequence[pulumi.Input[Union[bu pulumi.set(self, "transforms", value) +if not MYPY: + class HttpsConfigurationArgsDict(TypedDict): + """ + HTTPS configuration for CDN custom domain. + """ + certificate_source: pulumi.Input[builtins.str] + """ + Certificate source for the custom domain. One of: 'Cdn', 'AzureKeyVault'. + """ + protocol_type: pulumi.Input[builtins.str] + """ + TLS extension protocol. One of: 'ServerNameIndication', 'IPBased'. + """ + cdn_certificate_source_parameters: NotRequired[pulumi.Input['CdnCertificateSourceParametersArgsDict']] + """ + Parameters required for using CDN managed certificates. + """ + key_vault_certificate_source_parameters: NotRequired[pulumi.Input['KeyVaultCertificateSourceParametersArgsDict']] + """ + Parameters required for using certificates stored in Azure KeyVault. + """ + minimum_tls_version: NotRequired[pulumi.Input[builtins.str]] + """ + TLS protocol version that will be used for HTTPS. One of: 'None', 'TLS10', 'TLS12'. + """ +elif False: + HttpsConfigurationArgsDict: TypeAlias = Mapping[str, Any] + +@pulumi.input_type +class HttpsConfigurationArgs: + def __init__(__self__, *, + certificate_source: pulumi.Input[builtins.str], + protocol_type: pulumi.Input[builtins.str], + cdn_certificate_source_parameters: Optional[pulumi.Input['CdnCertificateSourceParametersArgs']] = None, + key_vault_certificate_source_parameters: Optional[pulumi.Input['KeyVaultCertificateSourceParametersArgs']] = None, + minimum_tls_version: Optional[pulumi.Input[builtins.str]] = None): + """ + HTTPS configuration for CDN custom domain. + :param pulumi.Input[builtins.str] certificate_source: Certificate source for the custom domain. One of: 'Cdn', 'AzureKeyVault'. + :param pulumi.Input[builtins.str] protocol_type: TLS extension protocol. One of: 'ServerNameIndication', 'IPBased'. + :param pulumi.Input['CdnCertificateSourceParametersArgs'] cdn_certificate_source_parameters: Parameters required for using CDN managed certificates. + :param pulumi.Input['KeyVaultCertificateSourceParametersArgs'] key_vault_certificate_source_parameters: Parameters required for using certificates stored in Azure KeyVault. + :param pulumi.Input[builtins.str] minimum_tls_version: TLS protocol version that will be used for HTTPS. One of: 'None', 'TLS10', 'TLS12'. + """ + pulumi.set(__self__, "certificate_source", certificate_source) + pulumi.set(__self__, "protocol_type", protocol_type) + if cdn_certificate_source_parameters is not None: + pulumi.set(__self__, "cdn_certificate_source_parameters", cdn_certificate_source_parameters) + if key_vault_certificate_source_parameters is not None: + pulumi.set(__self__, "key_vault_certificate_source_parameters", key_vault_certificate_source_parameters) + if minimum_tls_version is not None: + pulumi.set(__self__, "minimum_tls_version", minimum_tls_version) + + @property + @pulumi.getter(name="certificateSource") + def certificate_source(self) -> pulumi.Input[builtins.str]: + """ + Certificate source for the custom domain. One of: 'Cdn', 'AzureKeyVault'. + """ + return pulumi.get(self, "certificate_source") + + @certificate_source.setter + def certificate_source(self, value: pulumi.Input[builtins.str]): + pulumi.set(self, "certificate_source", value) + + @property + @pulumi.getter(name="protocolType") + def protocol_type(self) -> pulumi.Input[builtins.str]: + """ + TLS extension protocol. One of: 'ServerNameIndication', 'IPBased'. + """ + return pulumi.get(self, "protocol_type") + + @protocol_type.setter + def protocol_type(self, value: pulumi.Input[builtins.str]): + pulumi.set(self, "protocol_type", value) + + @property + @pulumi.getter(name="cdnCertificateSourceParameters") + def cdn_certificate_source_parameters(self) -> Optional[pulumi.Input['CdnCertificateSourceParametersArgs']]: + """ + Parameters required for using CDN managed certificates. + """ + return pulumi.get(self, "cdn_certificate_source_parameters") + + @cdn_certificate_source_parameters.setter + def cdn_certificate_source_parameters(self, value: Optional[pulumi.Input['CdnCertificateSourceParametersArgs']]): + pulumi.set(self, "cdn_certificate_source_parameters", value) + + @property + @pulumi.getter(name="keyVaultCertificateSourceParameters") + def key_vault_certificate_source_parameters(self) -> Optional[pulumi.Input['KeyVaultCertificateSourceParametersArgs']]: + """ + Parameters required for using certificates stored in Azure KeyVault. + """ + return pulumi.get(self, "key_vault_certificate_source_parameters") + + @key_vault_certificate_source_parameters.setter + def key_vault_certificate_source_parameters(self, value: Optional[pulumi.Input['KeyVaultCertificateSourceParametersArgs']]): + pulumi.set(self, "key_vault_certificate_source_parameters", value) + + @property + @pulumi.getter(name="minimumTlsVersion") + def minimum_tls_version(self) -> Optional[pulumi.Input[builtins.str]]: + """ + TLS protocol version that will be used for HTTPS. One of: 'None', 'TLS10', 'TLS12'. + """ + return pulumi.get(self, "minimum_tls_version") + + @minimum_tls_version.setter + def minimum_tls_version(self, value: Optional[pulumi.Input[builtins.str]]): + pulumi.set(self, "minimum_tls_version", value) + + if not MYPY: class IsDeviceMatchConditionParametersArgsDict(TypedDict): """ @@ -3927,6 +4083,118 @@ def transforms(self, value: Optional[pulumi.Input[Sequence[pulumi.Input[Union[bu pulumi.set(self, "transforms", value) +if not MYPY: + class KeyVaultCertificateSourceParametersArgsDict(TypedDict): + """ + Key Vault certificate parameters for custom domain HTTPS configuration. + """ + resource_group_name: pulumi.Input[builtins.str] + """ + Resource group containing the Key Vault. + """ + secret_name: pulumi.Input[builtins.str] + """ + Name of the secret in Key Vault. + """ + subscription_id: pulumi.Input[builtins.str] + """ + Azure subscription ID containing the Key Vault. + """ + vault_name: pulumi.Input[builtins.str] + """ + Name of the Key Vault. + """ + secret_version: NotRequired[pulumi.Input[builtins.str]] + """ + Version of the secret in Key Vault. + """ +elif False: + KeyVaultCertificateSourceParametersArgsDict: TypeAlias = Mapping[str, Any] + +@pulumi.input_type +class KeyVaultCertificateSourceParametersArgs: + def __init__(__self__, *, + resource_group_name: pulumi.Input[builtins.str], + secret_name: pulumi.Input[builtins.str], + subscription_id: pulumi.Input[builtins.str], + vault_name: pulumi.Input[builtins.str], + secret_version: Optional[pulumi.Input[builtins.str]] = None): + """ + Key Vault certificate parameters for custom domain HTTPS configuration. + :param pulumi.Input[builtins.str] resource_group_name: Resource group containing the Key Vault. + :param pulumi.Input[builtins.str] secret_name: Name of the secret in Key Vault. + :param pulumi.Input[builtins.str] subscription_id: Azure subscription ID containing the Key Vault. + :param pulumi.Input[builtins.str] vault_name: Name of the Key Vault. + :param pulumi.Input[builtins.str] secret_version: Version of the secret in Key Vault. + """ + pulumi.set(__self__, "resource_group_name", resource_group_name) + pulumi.set(__self__, "secret_name", secret_name) + pulumi.set(__self__, "subscription_id", subscription_id) + pulumi.set(__self__, "vault_name", vault_name) + if secret_version is not None: + pulumi.set(__self__, "secret_version", secret_version) + + @property + @pulumi.getter(name="resourceGroupName") + def resource_group_name(self) -> pulumi.Input[builtins.str]: + """ + Resource group containing the Key Vault. + """ + return pulumi.get(self, "resource_group_name") + + @resource_group_name.setter + def resource_group_name(self, value: pulumi.Input[builtins.str]): + pulumi.set(self, "resource_group_name", value) + + @property + @pulumi.getter(name="secretName") + def secret_name(self) -> pulumi.Input[builtins.str]: + """ + Name of the secret in Key Vault. + """ + return pulumi.get(self, "secret_name") + + @secret_name.setter + def secret_name(self, value: pulumi.Input[builtins.str]): + pulumi.set(self, "secret_name", value) + + @property + @pulumi.getter(name="subscriptionId") + def subscription_id(self) -> pulumi.Input[builtins.str]: + """ + Azure subscription ID containing the Key Vault. + """ + return pulumi.get(self, "subscription_id") + + @subscription_id.setter + def subscription_id(self, value: pulumi.Input[builtins.str]): + pulumi.set(self, "subscription_id", value) + + @property + @pulumi.getter(name="vaultName") + def vault_name(self) -> pulumi.Input[builtins.str]: + """ + Name of the Key Vault. + """ + return pulumi.get(self, "vault_name") + + @vault_name.setter + def vault_name(self, value: pulumi.Input[builtins.str]): + pulumi.set(self, "vault_name", value) + + @property + @pulumi.getter(name="secretVersion") + def secret_version(self) -> Optional[pulumi.Input[builtins.str]]: + """ + Version of the secret in Key Vault. + """ + return pulumi.get(self, "secret_version") + + @secret_version.setter + def secret_version(self, value: Optional[pulumi.Input[builtins.str]]): + pulumi.set(self, "secret_version", value) + + if not MYPY: class KeyVaultSigningKeyParametersArgsDict(TypedDict): """ diff --git a/sdk/python/pulumi_azure_native/cdn/custom_domain_https.py b/sdk/python/pulumi_azure_native/cdn/custom_domain_https.py new file mode 100644 index 000000000000..d170befd461e --- /dev/null +++ b/sdk/python/pulumi_azure_native/cdn/custom_domain_https.py @@ -0,0 +1,188 @@ +# coding=utf-8 +# *** WARNING: this file was generated by pulumi-language-python. *** +# *** Do not edit by hand unless you're certain you know what you are doing! *** + +import builtins +import copy +import warnings +import sys +import pulumi +import pulumi.runtime +from typing import Any, Mapping, Optional, Sequence, Union, overload +if sys.version_info >= (3, 11): + from typing import NotRequired, TypedDict, TypeAlias +else: + from typing_extensions import NotRequired, TypedDict, TypeAlias +from .. import _utilities +from . import outputs +from ._inputs import * + +__all__ = ['CustomDomainHttpsArgs', 'CustomDomainHttps'] + +@pulumi.input_type +class CustomDomainHttpsArgs: + def __init__(__self__, *, + custom_domain_id: pulumi.Input[builtins.str], + https_enabled: pulumi.Input[builtins.bool], + https_configuration: Optional[pulumi.Input['HttpsConfigurationArgs']] = None): + """ + The set of arguments for constructing a CustomDomainHttps resource. + :param pulumi.Input[builtins.str] custom_domain_id: The resource ID of the CDN Custom Domain. + :param pulumi.Input[builtins.bool] https_enabled: Whether HTTPS is enabled on the custom domain. + :param pulumi.Input['HttpsConfigurationArgs'] https_configuration: HTTPS configuration when HTTPS is enabled. + """ + pulumi.set(__self__, "custom_domain_id", custom_domain_id) + pulumi.set(__self__, "https_enabled", https_enabled) + if https_configuration is not None: + pulumi.set(__self__, "https_configuration", https_configuration) + + @property + @pulumi.getter(name="customDomainId") + def custom_domain_id(self) -> pulumi.Input[builtins.str]: + """ + The resource ID of the CDN Custom Domain. + """ + return pulumi.get(self, "custom_domain_id") + + @custom_domain_id.setter + def custom_domain_id(self, value: pulumi.Input[builtins.str]): + pulumi.set(self, "custom_domain_id", value) + + @property + @pulumi.getter(name="httpsEnabled") + def https_enabled(self) -> pulumi.Input[builtins.bool]: + """ + Whether HTTPS is enabled on the custom domain. + """ + return pulumi.get(self, "https_enabled") + + @https_enabled.setter + def https_enabled(self, value: pulumi.Input[builtins.bool]): + pulumi.set(self, "https_enabled", value) + + @property + @pulumi.getter(name="httpsConfiguration") + def https_configuration(self) -> Optional[pulumi.Input['HttpsConfigurationArgs']]: + """ + HTTPS configuration when HTTPS is enabled. + """ + return pulumi.get(self, "https_configuration") + + @https_configuration.setter + def https_configuration(self, value: Optional[pulumi.Input['HttpsConfigurationArgs']]): + pulumi.set(self, "https_configuration", value) + + +@pulumi.type_token("azure-native:cdn:CustomDomainHttps") +class CustomDomainHttps(pulumi.CustomResource): + @overload + def __init__(__self__, + resource_name: str, + opts: Optional[pulumi.ResourceOptions] = None, + custom_domain_id: Optional[pulumi.Input[builtins.str]] = None, + https_configuration: Optional[pulumi.Input[Union['HttpsConfigurationArgs', 'HttpsConfigurationArgsDict']]] = None, + https_enabled: Optional[pulumi.Input[builtins.bool]] = None, + __props__=None): + """ + Enables or disables HTTPS on a CDN custom domain. + + :param str resource_name: The name of the resource. + :param pulumi.ResourceOptions opts: Options for the resource. + :param pulumi.Input[builtins.str] custom_domain_id: The resource ID of the CDN Custom Domain. + :param pulumi.Input[Union['HttpsConfigurationArgs', 'HttpsConfigurationArgsDict']] https_configuration: HTTPS configuration when HTTPS is enabled. + :param pulumi.Input[builtins.bool] https_enabled: Whether HTTPS is enabled on the custom domain. + """ + ... + @overload + def __init__(__self__, + resource_name: str, + args: CustomDomainHttpsArgs, + opts: Optional[pulumi.ResourceOptions] = None): + """ + Enables or disables HTTPS on a CDN custom domain. + + :param str resource_name: The name of the resource. + :param CustomDomainHttpsArgs args: The arguments to use to populate this resource's properties. + :param pulumi.ResourceOptions opts: Options for the resource. + """ + ... + def __init__(__self__, resource_name: str, *args, **kwargs): + resource_args, opts = _utilities.get_resource_args_opts(CustomDomainHttpsArgs, pulumi.ResourceOptions, *args, **kwargs) + if resource_args is not None: + __self__._internal_init(resource_name, opts, **resource_args.__dict__) + else: + __self__._internal_init(resource_name, *args, **kwargs) + + def _internal_init(__self__, + resource_name: str, + opts: Optional[pulumi.ResourceOptions] = None, + custom_domain_id: Optional[pulumi.Input[builtins.str]] = None, + https_configuration: Optional[pulumi.Input[Union['HttpsConfigurationArgs', 'HttpsConfigurationArgsDict']]] = None, + https_enabled: Optional[pulumi.Input[builtins.bool]] = None, + __props__=None): + opts = pulumi.ResourceOptions.merge(_utilities.get_resource_opts_defaults(), opts) + if not isinstance(opts, pulumi.ResourceOptions): + raise TypeError('Expected resource options to be a ResourceOptions instance') + if opts.id is None: + if __props__ is not None: + raise TypeError('__props__ is only valid when passed in combination with a valid opts.id to get an existing resource') + __props__ = CustomDomainHttpsArgs.__new__(CustomDomainHttpsArgs) + + if custom_domain_id is None and not opts.urn: + raise TypeError("Missing required property 'custom_domain_id'") + __props__.__dict__["custom_domain_id"] = custom_domain_id + __props__.__dict__["https_configuration"] = https_configuration + if https_enabled is None and not opts.urn: + raise TypeError("Missing required property 'https_enabled'") + __props__.__dict__["https_enabled"] = https_enabled + super(CustomDomainHttps, __self__).__init__( + 'azure-native:cdn:CustomDomainHttps', + resource_name, + __props__, + opts) + + @staticmethod + def get(resource_name: str, + id: pulumi.Input[str], + opts: Optional[pulumi.ResourceOptions] = None) -> 'CustomDomainHttps': + """ + Get an existing CustomDomainHttps resource's state with the given name, id, and optional extra + properties used to qualify the lookup. + + :param str resource_name: The unique name of the resulting resource. + :param pulumi.Input[str] id: The unique provider ID of the resource to lookup. + :param pulumi.ResourceOptions opts: Options for the resource. + """ + opts = pulumi.ResourceOptions.merge(opts, pulumi.ResourceOptions(id=id)) + + __props__ = CustomDomainHttpsArgs.__new__(CustomDomainHttpsArgs) + + __props__.__dict__["custom_domain_id"] = None + __props__.__dict__["https_configuration"] = None + __props__.__dict__["https_enabled"] = None + return CustomDomainHttps(resource_name, opts=opts, __props__=__props__) + + @property + @pulumi.getter(name="customDomainId") + def custom_domain_id(self) -> pulumi.Output[Optional[builtins.str]]: + """ + The resource ID of the CDN Custom Domain. + """ + return pulumi.get(self, "custom_domain_id") + + @property + @pulumi.getter(name="httpsConfiguration") + def https_configuration(self) -> pulumi.Output[Optional['outputs.HttpsConfiguration']]: + """ + HTTPS configuration when HTTPS is enabled. + """ + return pulumi.get(self, "https_configuration") + + @property + @pulumi.getter(name="httpsEnabled") + def https_enabled(self) -> pulumi.Output[Optional[builtins.bool]]: + """ + Whether HTTPS is enabled on the custom domain. + """ + return pulumi.get(self, "https_enabled") + diff --git a/sdk/python/pulumi_azure_native/cdn/outputs.py b/sdk/python/pulumi_azure_native/cdn/outputs.py index d82e1205abcd..3116994fbcd6 100644 --- a/sdk/python/pulumi_azure_native/cdn/outputs.py +++ b/sdk/python/pulumi_azure_native/cdn/outputs.py @@ -25,6 +25,7 @@ 'CacheConfigurationResponse', 'CacheExpirationActionParametersResponse', 'CacheKeyQueryStringActionParametersResponse', + 'CdnCertificateSourceParameters', 'CdnCertificateSourceParametersResponse', 'CdnEndpointResponse', 'CdnManagedHttpsParametersResponse', @@ -71,7 +72,9 @@ 'HostNameMatchConditionParametersResponse', 'HttpErrorRangeParametersResponse', 'HttpVersionMatchConditionParametersResponse', + 'HttpsConfiguration', 'IsDeviceMatchConditionParametersResponse', + 'KeyVaultCertificateSourceParameters', 'KeyVaultCertificateSourceParametersResponse', 'KeyVaultSigningKeyParametersResponse', 'LoadBalancingSettingsParametersResponse', @@ -669,6 +672,46 @@ def query_parameters(self) -> Optional[builtins.str]: return pulumi.get(self, "query_parameters") +@pulumi.output_type +class CdnCertificateSourceParameters(dict): + """ + CDN certificate parameters for custom domain HTTPS configuration. + """ + @staticmethod + def __key_warning(key: str): + suggest = None + if key == "certificateType": + suggest = "certificate_type" + + if suggest: + pulumi.log.warn(f"Key '{key}' not found in CdnCertificateSourceParameters. Access the value via the '{suggest}' property getter instead.") + + def __getitem__(self, key: str) -> Any: + CdnCertificateSourceParameters.__key_warning(key) + return super().__getitem__(key) + + def get(self, key: str, default = None) -> Any: + CdnCertificateSourceParameters.__key_warning(key) + return super().get(key, default) + + def __init__(__self__, *, + certificate_type: Optional[builtins.str] = None): + """ + CDN certificate parameters for custom domain HTTPS configuration. + :param builtins.str certificate_type: Certificate type for CDN managed certificates. One of: 'Shared', 'Dedicated'. + """ + if certificate_type is not None: + pulumi.set(__self__, "certificate_type", certificate_type) + + @property + @pulumi.getter(name="certificateType") + def certificate_type(self) -> Optional[builtins.str]: + """ + Certificate type for CDN managed certificates. One of: 'Shared', 'Dedicated'. + """ + return pulumi.get(self, "certificate_type") + + @pulumi.output_type class CdnCertificateSourceParametersResponse(dict): """ @@ -3136,6 +3179,100 @@ def transforms(self) -> Optional[Sequence[builtins.str]]: return pulumi.get(self, "transforms") +@pulumi.output_type +class HttpsConfiguration(dict): + """ + HTTPS configuration for CDN custom domain. + """ + @staticmethod + def __key_warning(key: str): + suggest = None + if key == "certificateSource": + suggest = "certificate_source" + elif key == "protocolType": + suggest = "protocol_type" + elif key == "cdnCertificateSourceParameters": + suggest = "cdn_certificate_source_parameters" + elif key == "keyVaultCertificateSourceParameters": + suggest = "key_vault_certificate_source_parameters" + elif key == "minimumTlsVersion": + suggest = "minimum_tls_version" + + if suggest: + pulumi.log.warn(f"Key '{key}' not found in HttpsConfiguration. Access the value via the '{suggest}' property getter instead.") + + def __getitem__(self, key: str) -> Any: + HttpsConfiguration.__key_warning(key) + return super().__getitem__(key) + + def get(self, key: str, default = None) -> Any: + HttpsConfiguration.__key_warning(key) + return super().get(key, default) + + def __init__(__self__, *, + certificate_source: builtins.str, + protocol_type: builtins.str, + cdn_certificate_source_parameters: Optional['outputs.CdnCertificateSourceParameters'] = None, + key_vault_certificate_source_parameters: Optional['outputs.KeyVaultCertificateSourceParameters'] = None, + minimum_tls_version: Optional[builtins.str] = None): + """ + HTTPS configuration for CDN custom domain. + :param builtins.str certificate_source: Certificate source for the custom domain. One of: 'Cdn', 'AzureKeyVault'. + :param builtins.str protocol_type: TLS extension protocol. One of: 'ServerNameIndication', 'IPBased'. + :param 'CdnCertificateSourceParameters' cdn_certificate_source_parameters: Parameters required for using CDN managed certificates. + :param 'KeyVaultCertificateSourceParameters' key_vault_certificate_source_parameters: Parameters required for using certificates stored in Azure KeyVault. + :param builtins.str minimum_tls_version: TLS protocol version that will be used for HTTPS. One of: 'None', 'TLS10', 'TLS12'. + """ + pulumi.set(__self__, "certificate_source", certificate_source) + pulumi.set(__self__, "protocol_type", protocol_type) + if cdn_certificate_source_parameters is not None: + pulumi.set(__self__, "cdn_certificate_source_parameters", cdn_certificate_source_parameters) + if key_vault_certificate_source_parameters is not None: + pulumi.set(__self__, "key_vault_certificate_source_parameters", key_vault_certificate_source_parameters) + if minimum_tls_version is not None: + pulumi.set(__self__, "minimum_tls_version", minimum_tls_version) + + @property + @pulumi.getter(name="certificateSource") + def certificate_source(self) -> builtins.str: + """ + Certificate source for the custom domain. One of: 'Cdn', 'AzureKeyVault'. + """ + return pulumi.get(self, "certificate_source") + + @property + @pulumi.getter(name="protocolType") + def protocol_type(self) -> builtins.str: + """ + TLS extension protocol. One of: 'ServerNameIndication', 'IPBased'. + """ + return pulumi.get(self, "protocol_type") + + @property + @pulumi.getter(name="cdnCertificateSourceParameters") + def cdn_certificate_source_parameters(self) -> Optional['outputs.CdnCertificateSourceParameters']: + """ + Parameters required for using CDN managed certificates. + """ + return pulumi.get(self, "cdn_certificate_source_parameters") + + @property + @pulumi.getter(name="keyVaultCertificateSourceParameters") + def key_vault_certificate_source_parameters(self) -> Optional['outputs.KeyVaultCertificateSourceParameters']: + """ + Parameters required for using certificates stored in Azure KeyVault. + """ + return pulumi.get(self, "key_vault_certificate_source_parameters") + + @property + @pulumi.getter(name="minimumTlsVersion") + def minimum_tls_version(self) -> Optional[builtins.str]: + """ + TLS protocol version that will be used for HTTPS. One of: 'None', 'TLS10', 'TLS12'. + """ + return pulumi.get(self, "minimum_tls_version") + + @pulumi.output_type class IsDeviceMatchConditionParametersResponse(dict): """ @@ -3230,6 +3367,98 @@ def transforms(self) -> Optional[Sequence[builtins.str]]: return pulumi.get(self, "transforms") +@pulumi.output_type +class KeyVaultCertificateSourceParameters(dict): + """ + Key Vault certificate parameters for custom domain HTTPS configuration. + """ + @staticmethod + def __key_warning(key: str): + suggest = None + if key == "resourceGroupName": + suggest = "resource_group_name" + elif key == "secretName": + suggest = "secret_name" + elif key == "subscriptionId": + suggest = "subscription_id" + elif key == "vaultName": + suggest = "vault_name" + elif key == "secretVersion": + suggest = "secret_version" + + if suggest: + pulumi.log.warn(f"Key '{key}' not found in KeyVaultCertificateSourceParameters. Access the value via the '{suggest}' property getter instead.") + + def __getitem__(self, key: str) -> Any: + KeyVaultCertificateSourceParameters.__key_warning(key) + return super().__getitem__(key) + + def get(self, key: str, default = None) -> Any: + KeyVaultCertificateSourceParameters.__key_warning(key) + return super().get(key, default) + + def __init__(__self__, *, + resource_group_name: builtins.str, + secret_name: builtins.str, + subscription_id: builtins.str, + vault_name: builtins.str, + secret_version: Optional[builtins.str] = None): + """ + Key Vault certificate parameters for custom domain HTTPS configuration. + :param builtins.str resource_group_name: Resource group containing the Key Vault. + :param builtins.str secret_name: Name of the secret in Key Vault. + :param builtins.str subscription_id: Azure subscription ID containing the Key Vault. + :param builtins.str vault_name: Name of the Key Vault. + :param builtins.str secret_version: Version of the secret in Key Vault. + """ + pulumi.set(__self__, "resource_group_name", resource_group_name) + pulumi.set(__self__, "secret_name", secret_name) + pulumi.set(__self__, "subscription_id", subscription_id) + pulumi.set(__self__, "vault_name", vault_name) + if secret_version is not None: + pulumi.set(__self__, "secret_version", secret_version) + + @property + @pulumi.getter(name="resourceGroupName") + def resource_group_name(self) -> builtins.str: + """ + Resource group containing the Key Vault. + """ + return pulumi.get(self, "resource_group_name") + + @property + @pulumi.getter(name="secretName") + def secret_name(self) -> builtins.str: + """ + Name of the secret in Key Vault. + """ + return pulumi.get(self, "secret_name") + + @property + @pulumi.getter(name="subscriptionId") + def subscription_id(self) -> builtins.str: + """ + Azure subscription ID containing the Key Vault. + """ + return pulumi.get(self, "subscription_id") + + @property + @pulumi.getter(name="vaultName") + def vault_name(self) -> builtins.str: + """ + Name of the Key Vault. + """ + return pulumi.get(self, "vault_name") + + @property + @pulumi.getter(name="secretVersion") + def secret_version(self) -> Optional[builtins.str]: + """ + Version of the secret in Key Vault. + """ + return pulumi.get(self, "secret_version") + + @pulumi.output_type class KeyVaultCertificateSourceParametersResponse(dict): """