diff --git a/.github/.copilot-instructions.md b/.github/.copilot-instructions.md index c8970da..7f994c4 100644 --- a/.github/.copilot-instructions.md +++ b/.github/.copilot-instructions.md @@ -131,6 +131,19 @@ This pattern ensures: - Implement proper authentication token refresh - Follow meshStack API conventions for CRUD operations +### Data Structure Guidelines +**Pointer and `omitempty` Usage:** +- Only use pointers (`*type`) and `omitempty` JSON tags for fields that are **actually nullable** in the backend API +- Non-nullable fields should use value types (e.g., `string`, `int64`, `bool`) without `omitempty` +- This ensures proper validation and prevents sending incorrect null values to the API +- Example: + ```go + type Resource struct { + RequiredField string `json:"requiredField" tfsdk:"required_field"` // Non-nullable + OptionalField *string `json:"optionalField,omitempty" tfsdk:"optional_field"` // Nullable in backend + } + ``` + ## Key Dependencies - **Terraform Plugin Framework**: Latest stable version for provider development diff --git a/CHANGELOG.md b/CHANGELOG.md index 9c0413e..27dbf50 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,51 @@ +## v0.13.0 + +FEATURES: +- Add metering config support to `meshstack_mesh_platform` resource and data source. + +FIXES: +- Correctly model nullable platform config fields. + +## v0.12.4 + +FEATURES: +- Add quota definitions to meshPlatforms. + +## v0.12.3 + +FIXES: +- Bump terraform-plugin-docs and fix docs. + +## v0.12.2 + +FIXES: +- Fix possible nil-pointer issue when handling obfuscated secrets. + +## v0.12.1 + +FIXES: +- Handle obfuscated secrets in meshPlatform Azure Type. + +## v0.12.0 + +FEATURES: +- Added `meshstack_mesh_platform` resource. +- Added `meshstack_mesh_platform` data source. + +FIXES: +- Fix landing zone data source. + +## v0.11.0 + +FEATURES: +- Added `meshstack_mesh_landing_zone` resource. +- Added `meshstack_mesh_landing_zone` data source. +- Automatically set `type` inside platform_properties for landing zones. + +FIXES: +- Fix landing zone status handling. +- Make `type` a read-only property for landing zones. + ## v0.10.1 FIXES: diff --git a/client/platform.go b/client/platform.go index 5afdd3d..01500b0 100644 --- a/client/platform.go +++ b/client/platform.go @@ -71,306 +71,6 @@ type PlatformConfig struct { OpenShift *OpenShiftPlatformConfig `json:"openshift,omitempty" tfsdk:"openshift"` } -type AwsPlatformConfig struct { - Region *string `json:"region,omitempty" tfsdk:"region"` - Replication *AwsReplicationConfig `json:"replication,omitempty" tfsdk:"replication"` -} - -type AksPlatformConfig struct { - BaseUrl string `json:"baseUrl" tfsdk:"base_url"` - DisableSslValidation bool `json:"disableSslValidation" tfsdk:"disable_ssl_validation"` - Replication *AksReplicationConfig `json:"replication" tfsdk:"replication"` -} - -type AzurePlatformConfig struct { - EntraTenant *string `json:"entraTenant,omitempty" tfsdk:"entra_tenant"` - Replication *AzureReplicationConfig `json:"replication,omitempty" tfsdk:"replication"` -} - -type AzureRgPlatformConfig struct { - EntraTenant *string `json:"entraTenant,omitempty" tfsdk:"entra_tenant"` - Replication *AzureRgReplicationConfig `json:"replication,omitempty" tfsdk:"replication"` -} - -type GcpPlatformConfig struct { - Replication *GcpReplicationConfig `json:"replication" tfsdk:"replication"` -} - -type KubernetesPlatformConfig struct { - BaseUrl string `json:"baseUrl" tfsdk:"base_url"` - DisableSslValidation bool `json:"disableSslValidation" tfsdk:"disable_ssl_validation"` - Replication *KubernetesReplicationConfig `json:"replication" tfsdk:"replication"` -} - -type OpenShiftPlatformConfig struct { - BaseUrl string `json:"baseUrl" tfsdk:"base_url"` - DisableSslValidation bool `json:"disableSslValidation" tfsdk:"disable_ssl_validation"` - Replication *OpenShiftReplicationConfig `json:"replication" tfsdk:"replication"` -} - -type AzureRgReplicationConfig struct { - ServicePrincipal *AzureServicePrincipalConfig `json:"servicePrincipal,omitempty" tfsdk:"service_principal"` - Subscription *string `json:"subscription,omitempty" tfsdk:"subscription"` - ResourceGroupNamePattern *string `json:"resourceGroupNamePattern,omitempty" tfsdk:"resource_group_name_pattern"` - UserGroupNamePattern *string `json:"userGroupNamePattern,omitempty" tfsdk:"user_group_name_pattern"` - B2bUserInvitation *AzureB2bUserInvitation `json:"b2bUserInvitation,omitempty" tfsdk:"b2b_user_invitation"` - UserLookUpStrategy *string `json:"userLookUpStrategy,omitempty" tfsdk:"user_look_up_strategy"` - TenantTags *AzureTenantTags `json:"tenantTags,omitempty" tfsdk:"tenant_tags"` - SkipUserGroupPermissionCleanup *bool `json:"skipUserGroupPermissionCleanup,omitempty" tfsdk:"skip_user_group_permission_cleanup"` - AdministrativeUnitId *string `json:"administrativeUnitId,omitempty" tfsdk:"administrative_unit_id"` - AllowHierarchicalManagementGroupAssignment *bool `json:"allowHierarchicalManagementGroupAssignment,omitempty" tfsdk:"allow_hierarchical_management_group_assignment"` -} - -type GcpReplicationConfig struct { - ServiceAccountConfig *GcpServiceAccountConfig `json:"serviceAccountConfig,omitempty" tfsdk:"service_account_config"` - Domain *string `json:"domain,omitempty" tfsdk:"domain"` - CustomerId *string `json:"customerId,omitempty" tfsdk:"customer_id"` - GroupNamePattern *string `json:"groupNamePattern,omitempty" tfsdk:"group_name_pattern"` - ProjectNamePattern *string `json:"projectNamePattern,omitempty" tfsdk:"project_name_pattern"` - ProjectIdPattern *string `json:"projectIdPattern,omitempty" tfsdk:"project_id_pattern"` - BillingAccountId *string `json:"billingAccountId,omitempty" tfsdk:"billing_account_id"` - UserLookupStrategy *string `json:"userLookupStrategy,omitempty" tfsdk:"user_lookup_strategy"` - GcpRoleMappings []GcpPlatformRoleMapping `json:"gcpRoleMappings,omitempty" tfsdk:"gcp_role_mappings"` - AllowHierarchicalFolderAssignment *bool `json:"allowHierarchicalFolderAssignment,omitempty" tfsdk:"allow_hierarchical_folder_assignment"` - TenantTags *GcpTenantTags `json:"tenantTags,omitempty" tfsdk:"tenant_tags"` - SkipUserGroupPermissionCleanup *bool `json:"skipUserGroupPermissionCleanup,omitempty" tfsdk:"skip_user_group_permission_cleanup"` -} - -type GcpServiceAccountConfig struct { - ServiceAccountCredentialsConfig *GcpServiceAccountCredentialsConfig `json:"serviceAccountCredentialsConfig,omitempty" tfsdk:"service_account_credentials_config"` - ServiceAccountWorkloadIdentityConfig *GcpServiceAccountWorkloadIdentityConfig `json:"serviceAccountWorkloadIdentityConfig,omitempty" tfsdk:"service_account_workload_identity_config"` -} - -type GcpServiceAccountCredentialsConfig struct { - ServiceAccountCredentialsB64 *string `json:"serviceAccountCredentialsB64,omitempty" tfsdk:"service_account_credentials_b64"` -} - -type GcpServiceAccountWorkloadIdentityConfig struct { - Audience *string `json:"audience,omitempty" tfsdk:"audience"` - ServiceAccountEmail *string `json:"serviceAccountEmail,omitempty" tfsdk:"service_account_email"` -} - -type GcpTenantTags struct { - NamespacePrefix string `json:"namespacePrefix" tfsdk:"namespace_prefix"` - TagMappers []GcpTagMapper `json:"tagMappers" tfsdk:"tag_mappers"` -} - -type GcpTagMapper struct { - Key string `json:"key" tfsdk:"key"` - ValuePattern string `json:"valuePattern" tfsdk:"value_pattern"` -} - -type KubernetesReplicationConfig struct { - ClientConfig *KubernetesClientConfig `json:"clientConfig,omitempty" tfsdk:"client_config"` - NamespaceNamePattern *string `json:"namespaceNamePattern,omitempty" tfsdk:"namespace_name_pattern"` -} - -type KubernetesClientConfig struct { - AccessToken *string `json:"accessToken,omitempty" tfsdk:"access_token"` -} - -type OpenShiftReplicationConfig struct { - ClientConfig *OpenShiftClientConfig `json:"clientConfig,omitempty" tfsdk:"client_config"` - WebConsoleUrl *string `json:"webConsoleUrl,omitempty" tfsdk:"web_console_url"` - ProjectNamePattern *string `json:"projectNamePattern,omitempty" tfsdk:"project_name_pattern"` - EnableTemplateInstantiation *bool `json:"enableTemplateInstantiation,omitempty" tfsdk:"enable_template_instantiation"` - OpenShiftRoleMappings []OpenShiftPlatformRoleMapping `json:"openshiftRoleMappings,omitempty" tfsdk:"openshift_role_mappings"` - IdentityProviderName *string `json:"identityProviderName,omitempty" tfsdk:"identity_provider_name"` - TenantTags *OpenShiftTenantTags `json:"tenantTags,omitempty" tfsdk:"tenant_tags"` -} - -type OpenShiftClientConfig struct { - AccessToken *string `json:"accessToken,omitempty" tfsdk:"access_token"` -} - -type OpenShiftTenantTags struct { - NamespacePrefix string `json:"namespacePrefix" tfsdk:"namespace_prefix"` - TagMappers []OpenShiftTagMapper `json:"tagMappers" tfsdk:"tag_mappers"` -} - -type OpenShiftTagMapper struct { - Key string `json:"key" tfsdk:"key"` - ValuePattern string `json:"valuePattern" tfsdk:"value_pattern"` -} - -type AksReplicationConfig struct { - AccessToken *string `json:"accessToken,omitempty" tfsdk:"access_token"` - NamespaceNamePattern *string `json:"namespaceNamePattern,omitempty" tfsdk:"namespace_name_pattern"` - GroupNamePattern *string `json:"groupNamePattern,omitempty" tfsdk:"group_name_pattern"` - ServicePrincipal *ServicePrincipalConfig `json:"servicePrincipal,omitempty" tfsdk:"service_principal"` - AksSubscriptionId *string `json:"aksSubscriptionId,omitempty" tfsdk:"aks_subscription_id"` - AksClusterName *string `json:"aksClusterName,omitempty" tfsdk:"aks_cluster_name"` - AksResourceGroup *string `json:"aksResourceGroup,omitempty" tfsdk:"aks_resource_group"` - RedirectUrl *string `json:"redirectUrl,omitempty" tfsdk:"redirect_url"` - SendAzureInvitationMail *bool `json:"sendAzureInvitationMail,omitempty" tfsdk:"send_azure_invitation_mail"` - UserLookUpStrategy *string `json:"userLookUpStrategy,omitempty" tfsdk:"user_look_up_strategy"` - AdministrativeUnitId *string `json:"administrativeUnitId,omitempty" tfsdk:"administrative_unit_id"` -} - -type ServicePrincipalConfig struct { - ClientId string `json:"clientId" tfsdk:"client_id"` - AuthType string `json:"authType" tfsdk:"auth_type"` - CredentialsAuthClientSecret *string `json:"credentialsAuthClientSecret,omitempty" tfsdk:"credentials_auth_client_secret"` - EntraTenant string `json:"entraTenant" tfsdk:"entra_tenant"` - ObjectId string `json:"objectId" tfsdk:"object_id"` -} - -// Azure-specific service principal configurations -type AzureServicePrincipalConfig struct { - ClientId string `json:"clientId" tfsdk:"client_id"` - AuthType string `json:"authType" tfsdk:"auth_type"` - CredentialsAuthClientSecret *string `json:"credentialsAuthClientSecret,omitempty" tfsdk:"credentials_auth_client_secret"` - ObjectId string `json:"objectId" tfsdk:"object_id"` -} - -type AzureSourceServicePrincipalConfig struct { - ClientId string `json:"clientId" tfsdk:"client_id"` - AuthType string `json:"authType" tfsdk:"auth_type"` - CredentialsAuthClientSecret *string `json:"credentialsAuthClientSecret,omitempty" tfsdk:"credentials_auth_client_secret"` -} - -// AWS-specific replication configuration structures -type AwsReplicationConfig struct { - AccessConfig *AwsAccessConfig `json:"accessConfig,omitempty" tfsdk:"access_config"` - WaitForExternalAvm *bool `json:"waitForExternalAvm,omitempty" tfsdk:"wait_for_external_avm"` - AutomationAccountRole *string `json:"automationAccountRole,omitempty" tfsdk:"automation_account_role"` - AutomationAccountExternalId *string `json:"automationAccountExternalId,omitempty" tfsdk:"automation_account_external_id"` - AccountAccessRole *string `json:"accountAccessRole,omitempty" tfsdk:"account_access_role"` - AccountAliasPattern *string `json:"accountAliasPattern,omitempty" tfsdk:"account_alias_pattern"` - EnforceAccountAlias *bool `json:"enforceAccountAlias,omitempty" tfsdk:"enforce_account_alias"` - AccountEmailPattern *string `json:"accountEmailPattern,omitempty" tfsdk:"account_email_pattern"` - TenantTags *AwsTenantTags `json:"tenantTags,omitempty" tfsdk:"tenant_tags"` - AwsSso *AwsSsoConfig `json:"awsSso,omitempty" tfsdk:"aws_sso"` - EnrollmentConfiguration *AwsEnrollmentConfiguration `json:"enrollmentConfiguration,omitempty" tfsdk:"enrollment_configuration"` - SelfDowngradeAccessRole *bool `json:"selfDowngradeAccessRole,omitempty" tfsdk:"self_downgrade_access_role"` - SkipUserGroupPermissionCleanup *bool `json:"skipUserGroupPermissionCleanup,omitempty" tfsdk:"skip_user_group_permission_cleanup"` - AllowHierarchicalOrganizationalUnitAssignment *bool `json:"allowHierarchicalOrganizationalUnitAssignment,omitempty" tfsdk:"allow_hierarchical_organizational_unit_assignment"` -} - -type AwsAccessConfig struct { - OrganizationRootAccountRole string `json:"organizationRootAccountRole" tfsdk:"organization_root_account_role"` - OrganizationRootAccountExternalId *string `json:"organizationRootAccountExternalId,omitempty" tfsdk:"organization_root_account_external_id"` - ServiceUserConfig *AwsServiceUserConfig `json:"serviceUserConfig,omitempty" tfsdk:"service_user_config"` - WorkloadIdentityConfig *AwsWorkloadIdentityConfig `json:"workloadIdentityConfig,omitempty" tfsdk:"workload_identity_config"` -} - -type AwsServiceUserConfig struct { - AccessKey string `json:"accessKey" tfsdk:"access_key"` - SecretKey *string `json:"secretKey,omitempty" tfsdk:"secret_key"` -} - -type AwsWorkloadIdentityConfig struct { - RoleArn string `json:"roleArn" tfsdk:"role_arn"` -} - -type AwsTenantTags struct { - NamespacePrefix string `json:"namespacePrefix" tfsdk:"namespace_prefix"` - TagMappers []AwsTagMapper `json:"tagMappers" tfsdk:"tag_mappers"` -} - -type AwsTagMapper struct { - Key string `json:"key" tfsdk:"key"` - ValuePattern string `json:"valuePattern" tfsdk:"value_pattern"` -} - -type AwsSsoConfig struct { - ScimEndpoint string `json:"scimEndpoint" tfsdk:"scim_endpoint"` - Arn string `json:"arn" tfsdk:"arn"` - GroupNamePattern string `json:"groupNamePattern" tfsdk:"group_name_pattern"` - SsoAccessToken *string `json:"ssoAccessToken,omitempty" tfsdk:"sso_access_token"` - AwsRoleMappings []AwsSsoRoleMapping `json:"awsRoleMappings" tfsdk:"aws_role_mappings"` - SignInUrl *string `json:"signInUrl,omitempty" tfsdk:"sign_in_url"` -} - -type AwsSsoRoleMapping struct { - MeshProjectRoleRef MeshProjectRoleRefV2 `json:"projectRoleRef" tfsdk:"project_role_ref"` - AwsRole string `json:"awsRole" tfsdk:"aws_role"` - PermissionSetArns []string `json:"permissionSetArns" tfsdk:"permission_set_arns"` -} - -type GcpPlatformRoleMapping struct { - MeshProjectRoleRef MeshProjectRoleRefV2 `json:"projectRoleRef" tfsdk:"project_role_ref"` - GcpRole string `json:"gcpRole" tfsdk:"gcp_role"` -} - -type OpenShiftPlatformRoleMapping struct { - MeshProjectRoleRef MeshProjectRoleRefV2 `json:"projectRoleRef" tfsdk:"project_role_ref"` - OpenShiftRole string `json:"openshiftRole" tfsdk:"openshift_role"` -} - -type AwsEnrollmentConfiguration struct { - ManagementAccountId string `json:"managementAccountId" tfsdk:"management_account_id"` - AccountFactoryProductId string `json:"accountFactoryProductId" tfsdk:"account_factory_product_id"` -} - -// Azure-specific replication configuration structures -type AzureReplicationConfig struct { - ServicePrincipal *AzureServicePrincipalConfig `json:"servicePrincipal,omitempty" tfsdk:"service_principal"` - Provisioning *AzureProvisioning `json:"provisioning,omitempty" tfsdk:"provisioning"` - B2bUserInvitation *AzureB2bUserInvitation `json:"b2bUserInvitation,omitempty" tfsdk:"b2b_user_invitation"` - SubscriptionNamePattern *string `json:"subscriptionNamePattern,omitempty" tfsdk:"subscription_name_pattern"` - GroupNamePattern *string `json:"groupNamePattern,omitempty" tfsdk:"group_name_pattern"` - BlueprintServicePrincipal *string `json:"blueprintServicePrincipal,omitempty" tfsdk:"blueprint_service_principal"` - BlueprintLocation *string `json:"blueprintLocation,omitempty" tfsdk:"blueprint_location"` - AzureRoleMappings []AzurePlatformRoleMapping `json:"azureRoleMappings,omitempty" tfsdk:"azure_role_mappings"` - TenantTags *AzureTenantTags `json:"tenantTags,omitempty" tfsdk:"tenant_tags"` - UserLookUpStrategy *string `json:"userLookUpStrategy,omitempty" tfsdk:"user_look_up_strategy"` - SkipUserGroupPermissionCleanup *bool `json:"skipUserGroupPermissionCleanup,omitempty" tfsdk:"skip_user_group_permission_cleanup"` - AdministrativeUnitId *string `json:"administrativeUnitId,omitempty" tfsdk:"administrative_unit_id"` - AllowHierarchicalManagementGroupAssignment *bool `json:"allowHierarchicalManagementGroupAssignment,omitempty" tfsdk:"allow_hierarchical_management_group_assignment"` -} - -type AzureProvisioning struct { - SubscriptionOwnerObjectIds []string `json:"subscriptionOwnerObjectIds,omitempty" tfsdk:"subscription_owner_object_ids"` - EnterpriseEnrollment *AzureEnterpriseEnrollment `json:"enterpriseEnrollment,omitempty" tfsdk:"enterprise_enrollment"` - CustomerAgreement *AzureCustomerAgreement `json:"customerAgreement,omitempty" tfsdk:"customer_agreement"` - PreProvisioned *AzurePreProvisioned `json:"preProvisioned,omitempty" tfsdk:"pre_provisioned"` -} - -type AzureEnterpriseEnrollment struct { - EnrollmentAccountId string `json:"enrollmentAccountId" tfsdk:"enrollment_account_id"` - SubscriptionOfferType string `json:"subscriptionOfferType" tfsdk:"subscription_offer_type"` - UseLegacySubscriptionEnrollment *bool `json:"useLegacySubscriptionEnrollment,omitempty" tfsdk:"use_legacy_subscription_enrollment"` - SubscriptionCreationErrorCooldownSec *int `json:"subscriptionCreationErrorCooldownSec,omitempty" tfsdk:"subscription_creation_error_cooldown_sec"` -} - -type AzureCustomerAgreement struct { - SourceServicePrincipal *AzureSourceServicePrincipalConfig `json:"sourceServicePrincipal,omitempty" tfsdk:"source_service_principal"` - DestinationEntraId string `json:"destinationEntraId" tfsdk:"destination_entra_id"` - SourceEntraTenant string `json:"sourceEntraTenant" tfsdk:"source_entra_tenant"` - BillingScope string `json:"billingScope" tfsdk:"billing_scope"` - SubscriptionCreationErrorCooldownSec *int `json:"subscriptionCreationErrorCooldownSec,omitempty" tfsdk:"subscription_creation_error_cooldown_sec"` -} - -type AzurePreProvisioned struct { - UnusedSubscriptionNamePrefix string `json:"unusedSubscriptionNamePrefix" tfsdk:"unused_subscription_name_prefix"` -} - -type AzureB2bUserInvitation struct { - RedirectUrl *string `json:"redirectUrl,omitempty" tfsdk:"redirect_url"` - SendAzureInvitationMail *bool `json:"sendAzureInvitationMail,omitempty" tfsdk:"send_azure_invitation_mail"` -} - -type AzurePlatformRoleMapping struct { - MeshProjectRoleRef MeshProjectRoleRefV2 `json:"projectRoleRef" tfsdk:"project_role_ref"` - AzureRole AzurePlatformRoleDefinition `json:"azureRole" tfsdk:"azure_role"` -} - -type AzurePlatformRoleDefinition struct { - Alias string `json:"alias" tfsdk:"alias"` - Id string `json:"id" tfsdk:"id"` -} - -type AzureTenantTags struct { - NamespacePrefix string `json:"namespacePrefix" tfsdk:"namespace_prefix"` - TagMappers []AzureTagMapper `json:"tagMappers" tfsdk:"tag_mappers"` -} - -type AzureTagMapper struct { - Key string `json:"key" tfsdk:"key"` - ValuePattern string `json:"valuePattern" tfsdk:"value_pattern"` -} - type MeshPlatformCreate struct { ApiVersion string `json:"apiVersion" tfsdk:"api_version"` Metadata MeshPlatformCreateMetadata `json:"metadata" tfsdk:"metadata"` @@ -394,6 +94,21 @@ type MeshPlatformUpdateMetadata struct { Uuid string `json:"uuid" tfsdk:"uuid"` } +type MeshPlatformMeteringProcessingConfig struct { + CompactTimelinesAfterDays int64 `json:"compactTimelinesAfterDays" tfsdk:"compact_timelines_after_days"` + DeleteRawDataAfterDays int64 `json:"deleteRawDataAfterDays" tfsdk:"delete_raw_data_after_days"` +} + +type MeshTenantTags struct { + NamespacePrefix string `json:"namespacePrefix" tfsdk:"namespace_prefix"` + TagMappers []TagMapper `json:"tagMappers" tfsdk:"tag_mappers"` +} + +type TagMapper struct { + Key string `json:"key" tfsdk:"key"` + ValuePattern string `json:"valuePattern" tfsdk:"value_pattern"` +} + func (c *MeshStackProviderClient) urlForPlatform(uuid string) *url.URL { return c.endpoints.Platforms.JoinPath(uuid) } diff --git a/client/platform_config_aks.go b/client/platform_config_aks.go new file mode 100644 index 0000000..927d119 --- /dev/null +++ b/client/platform_config_aks.go @@ -0,0 +1,35 @@ +package client + +type AksPlatformConfig struct { + BaseUrl string `json:"baseUrl" tfsdk:"base_url"` + DisableSslValidation bool `json:"disableSslValidation" tfsdk:"disable_ssl_validation"` + Replication *AksReplicationConfig `json:"replication" tfsdk:"replication"` + Metering *AksMeteringConfig `json:"metering,omitempty" tfsdk:"metering"` +} + +type AksReplicationConfig struct { + AccessToken string `json:"accessToken" tfsdk:"access_token"` + NamespaceNamePattern string `json:"namespaceNamePattern" tfsdk:"namespace_name_pattern"` + GroupNamePattern string `json:"groupNamePattern" tfsdk:"group_name_pattern"` + ServicePrincipal AksServicePrincipalConfig `json:"servicePrincipal" tfsdk:"service_principal"` + AksSubscriptionId string `json:"aksSubscriptionId" tfsdk:"aks_subscription_id"` + AksClusterName string `json:"aksClusterName" tfsdk:"aks_cluster_name"` + AksResourceGroup string `json:"aksResourceGroup" tfsdk:"aks_resource_group"` + RedirectUrl *string `json:"redirectUrl,omitempty" tfsdk:"redirect_url"` + SendAzureInvitationMail bool `json:"sendAzureInvitationMail" tfsdk:"send_azure_invitation_mail"` + UserLookUpStrategy string `json:"userLookUpStrategy" tfsdk:"user_look_up_strategy"` + AdministrativeUnitId *string `json:"administrativeUnitId,omitempty" tfsdk:"administrative_unit_id"` +} + +type AksServicePrincipalConfig struct { + ClientId string `json:"clientId" tfsdk:"client_id"` + AuthType string `json:"authType" tfsdk:"auth_type"` + CredentialsAuthClientSecret *string `json:"credentialsAuthClientSecret,omitempty" tfsdk:"credentials_auth_client_secret"` + EntraTenant string `json:"entraTenant" tfsdk:"entra_tenant"` + ObjectId string `json:"objectId" tfsdk:"object_id"` +} + +type AksMeteringConfig struct { + ClientConfig KubernetesClientConfig `json:"clientConfig" tfsdk:"client_config"` + Processing MeshPlatformMeteringProcessingConfig `json:"processing" tfsdk:"processing"` +} diff --git a/client/platform_config_aws.go b/client/platform_config_aws.go new file mode 100644 index 0000000..a193b09 --- /dev/null +++ b/client/platform_config_aws.go @@ -0,0 +1,68 @@ +package client + +type AwsPlatformConfig struct { + Region string `json:"region,omitempty" tfsdk:"region"` + Replication *AwsReplicationConfig `json:"replication,omitempty" tfsdk:"replication"` + Metering *AwsMeteringConfig `json:"metering,omitempty" tfsdk:"metering"` +} + +type AwsReplicationConfig struct { + AccessConfig AwsAccessConfig `json:"accessConfig" tfsdk:"access_config"` + WaitForExternalAvm bool `json:"waitForExternalAvm" tfsdk:"wait_for_external_avm"` + AutomationAccountRole string `json:"automationAccountRole" tfsdk:"automation_account_role"` + AutomationAccountExternalId *string `json:"automationAccountExternalId,omitempty" tfsdk:"automation_account_external_id"` + AccountAccessRole string `json:"accountAccessRole" tfsdk:"account_access_role"` + AccountAliasPattern string `json:"accountAliasPattern" tfsdk:"account_alias_pattern"` + EnforceAccountAlias bool `json:"enforceAccountAlias" tfsdk:"enforce_account_alias"` + AccountEmailPattern string `json:"accountEmailPattern" tfsdk:"account_email_pattern"` + TenantTags *MeshTenantTags `json:"tenantTags,omitempty" tfsdk:"tenant_tags"` + AwsSso *AwsSsoConfig `json:"awsSso,omitempty" tfsdk:"aws_sso"` + EnrollmentConfiguration *AwsEnrollmentConfiguration `json:"enrollmentConfiguration,omitempty" tfsdk:"enrollment_configuration"` + SelfDowngradeAccessRole bool `json:"selfDowngradeAccessRole" tfsdk:"self_downgrade_access_role"` + SkipUserGroupPermissionCleanup bool `json:"skipUserGroupPermissionCleanup" tfsdk:"skip_user_group_permission_cleanup"` + AllowHierarchicalOrganizationalUnitAssignment bool `json:"allowHierarchicalOrganizationalUnitAssignment" tfsdk:"allow_hierarchical_organizational_unit_assignment"` +} + +type AwsAccessConfig struct { + OrganizationRootAccountRole string `json:"organizationRootAccountRole" tfsdk:"organization_root_account_role"` + OrganizationRootAccountExternalId *string `json:"organizationRootAccountExternalId,omitempty" tfsdk:"organization_root_account_external_id"` + ServiceUserConfig *AwsServiceUserConfig `json:"serviceUserConfig,omitempty" tfsdk:"service_user_config"` + WorkloadIdentityConfig *AwsWorkloadIdentityConfig `json:"workloadIdentityConfig,omitempty" tfsdk:"workload_identity_config"` +} + +type AwsServiceUserConfig struct { + AccessKey string `json:"accessKey" tfsdk:"access_key"` + SecretKey string `json:"secretKey" tfsdk:"secret_key"` +} + +type AwsWorkloadIdentityConfig struct { + RoleArn string `json:"roleArn" tfsdk:"role_arn"` +} + +type AwsSsoConfig struct { + ScimEndpoint string `json:"scimEndpoint" tfsdk:"scim_endpoint"` + Arn string `json:"arn" tfsdk:"arn"` + GroupNamePattern string `json:"groupNamePattern" tfsdk:"group_name_pattern"` + SsoAccessToken string `json:"ssoAccessToken" tfsdk:"sso_access_token"` + AwsRoleMappings []AwsSsoRoleMapping `json:"awsRoleMappings" tfsdk:"aws_role_mappings"` + SignInUrl string `json:"signInUrl" tfsdk:"sign_in_url"` +} + +type AwsSsoRoleMapping struct { + MeshProjectRoleRef MeshProjectRoleRefV2 `json:"projectRoleRef" tfsdk:"project_role_ref"` + AwsRole string `json:"awsRole" tfsdk:"aws_role"` + PermissionSetArns []string `json:"permissionSetArns" tfsdk:"permission_set_arns"` +} + +type AwsEnrollmentConfiguration struct { + ManagementAccountId string `json:"managementAccountId" tfsdk:"management_account_id"` + AccountFactoryProductId string `json:"accountFactoryProductId" tfsdk:"account_factory_product_id"` +} + +type AwsMeteringConfig struct { + AccessConfig AwsAccessConfig `json:"accessConfig" tfsdk:"access_config"` + Filter string `json:"filter" tfsdk:"filter"` + ReservedInstanceFairChargeback bool `json:"reservedInstanceFairChargeback" tfsdk:"reserved_instance_fair_chargeback"` + SavingsPlanFairChargeback bool `json:"savingsPlanFairChargeback" tfsdk:"savings_plan_fair_chargeback"` + Processing MeshPlatformMeteringProcessingConfig `json:"processing" tfsdk:"processing"` +} diff --git a/client/platform_config_azure.go b/client/platform_config_azure.go new file mode 100644 index 0000000..6541a42 --- /dev/null +++ b/client/platform_config_azure.go @@ -0,0 +1,82 @@ +package client + +type AzurePlatformConfig struct { + EntraTenant string `json:"entraTenant" tfsdk:"entra_tenant"` + Replication *AzureReplicationConfig `json:"replication,omitempty" tfsdk:"replication"` + Metering *AzureMeteringConfig `json:"metering,omitempty" tfsdk:"metering"` +} + +type AzureReplicationConfig struct { + ServicePrincipal AzureServicePrincipalConfig `json:"servicePrincipal" tfsdk:"service_principal"` + Provisioning *AzureSubscriptionProvisioningConfig `json:"provisioning,omitempty" tfsdk:"provisioning"` + B2bUserInvitation *AzureInviteB2BUserConfig `json:"b2bUserInvitation,omitempty" tfsdk:"b2b_user_invitation"` + SubscriptionNamePattern string `json:"subscriptionNamePattern" tfsdk:"subscription_name_pattern"` + GroupNamePattern string `json:"groupNamePattern" tfsdk:"group_name_pattern"` + BlueprintServicePrincipal string `json:"blueprintServicePrincipal" tfsdk:"blueprint_service_principal"` + BlueprintLocation string `json:"blueprintLocation" tfsdk:"blueprint_location"` + AzureRoleMappings []AzureRoleMapping `json:"azureRoleMappings" tfsdk:"azure_role_mappings"` + TenantTags *MeshTenantTags `json:"tenantTags,omitempty" tfsdk:"tenant_tags"` + UserLookUpStrategy string `json:"userLookUpStrategy" tfsdk:"user_look_up_strategy"` + SkipUserGroupPermissionCleanup bool `json:"skipUserGroupPermissionCleanup" tfsdk:"skip_user_group_permission_cleanup"` + AdministrativeUnitId *string `json:"administrativeUnitId,omitempty" tfsdk:"administrative_unit_id"` + AllowHierarchicalManagementGroupAssignment bool `json:"allowHierarchicalManagementGroupAssignment" tfsdk:"allow_hierarchical_management_group_assignment"` +} + +type AzureServicePrincipalConfig struct { + ClientId string `json:"clientId" tfsdk:"client_id"` + AuthType string `json:"authType" tfsdk:"auth_type"` + CredentialsAuthClientSecret *string `json:"credentialsAuthClientSecret,omitempty" tfsdk:"credentials_auth_client_secret"` + ObjectId string `json:"objectId" tfsdk:"object_id"` +} + +type AzureGraphApiCredentials struct { + ClientId string `json:"clientId" tfsdk:"client_id"` + AuthType string `json:"authType" tfsdk:"auth_type"` + CredentialsAuthClientSecret *string `json:"credentialsAuthClientSecret,omitempty" tfsdk:"credentials_auth_client_secret"` +} + +type AzureSubscriptionProvisioningConfig struct { + SubscriptionOwnerObjectIds []string `json:"subscriptionOwnerObjectIds" tfsdk:"subscription_owner_object_ids"` + EnterpriseEnrollment *AzureEnterpriseEnrollmentConfig `json:"enterpriseEnrollment,omitempty" tfsdk:"enterprise_enrollment"` + CustomerAgreement *AzureCustomerAgreementConfig `json:"customerAgreement,omitempty" tfsdk:"customer_agreement"` + PreProvisioned *AzurePreProvisionedSubscriptionConfig `json:"preProvisioned,omitempty" tfsdk:"pre_provisioned"` +} + +type AzureEnterpriseEnrollmentConfig struct { + EnrollmentAccountId string `json:"enrollmentAccountId" tfsdk:"enrollment_account_id"` + SubscriptionOfferType string `json:"subscriptionOfferType" tfsdk:"subscription_offer_type"` + UseLegacySubscriptionEnrollment bool `json:"useLegacySubscriptionEnrollment" tfsdk:"use_legacy_subscription_enrollment"` + SubscriptionCreationErrorCooldownSec int64 `json:"subscriptionCreationErrorCooldownSec" tfsdk:"subscription_creation_error_cooldown_sec"` +} + +type AzureCustomerAgreementConfig struct { + SourceServicePrincipal AzureGraphApiCredentials `json:"sourceServicePrincipal" tfsdk:"source_service_principal"` + DestinationEntraId string `json:"destinationEntraId" tfsdk:"destination_entra_id"` + SourceEntraTenant string `json:"sourceEntraTenant" tfsdk:"source_entra_tenant"` + BillingScope string `json:"billingScope" tfsdk:"billing_scope"` + SubscriptionCreationErrorCooldownSec int64 `json:"subscriptionCreationErrorCooldownSec" tfsdk:"subscription_creation_error_cooldown_sec"` +} + +type AzurePreProvisionedSubscriptionConfig struct { + UnusedSubscriptionNamePrefix string `json:"unusedSubscriptionNamePrefix" tfsdk:"unused_subscription_name_prefix"` +} + +type AzureInviteB2BUserConfig struct { + RedirectUrl string `json:"redirectUrl" tfsdk:"redirect_url"` + SendAzureInvitationMail bool `json:"sendAzureInvitationMail" tfsdk:"send_azure_invitation_mail"` +} + +type AzureRoleMapping struct { + MeshProjectRoleRef MeshProjectRoleRefV2 `json:"projectRoleRef" tfsdk:"project_role_ref"` + AzureRole AzureRole `json:"azureRole" tfsdk:"azure_role"` +} + +type AzureRole struct { + Alias string `json:"alias" tfsdk:"alias"` + Id string `json:"id" tfsdk:"id"` +} + +type AzureMeteringConfig struct { + ServicePrincipal AzureServicePrincipalConfig `json:"servicePrincipal" tfsdk:"service_principal"` + Processing MeshPlatformMeteringProcessingConfig `json:"processing" tfsdk:"processing"` +} diff --git a/client/platform_config_azurerg.go b/client/platform_config_azurerg.go new file mode 100644 index 0000000..d553f56 --- /dev/null +++ b/client/platform_config_azurerg.go @@ -0,0 +1,19 @@ +package client + +type AzureRgPlatformConfig struct { + EntraTenant string `json:"entraTenant" tfsdk:"entra_tenant"` + Replication *AzureRgReplicationConfig `json:"replication,omitempty" tfsdk:"replication"` +} + +type AzureRgReplicationConfig struct { + ServicePrincipal AzureServicePrincipalConfig `json:"servicePrincipal" tfsdk:"service_principal"` + Subscription string `json:"subscription" tfsdk:"subscription"` + ResourceGroupNamePattern string `json:"resourceGroupNamePattern" tfsdk:"resource_group_name_pattern"` + UserGroupNamePattern string `json:"userGroupNamePattern" tfsdk:"user_group_name_pattern"` + B2bUserInvitation *AzureInviteB2BUserConfig `json:"b2bUserInvitation,omitempty" tfsdk:"b2b_user_invitation"` + UserLookUpStrategy string `json:"userLookUpStrategy" tfsdk:"user_look_up_strategy"` + TenantTags *MeshTenantTags `json:"tenantTags,omitempty" tfsdk:"tenant_tags"` + SkipUserGroupPermissionCleanup bool `json:"skipUserGroupPermissionCleanup" tfsdk:"skip_user_group_permission_cleanup"` + AdministrativeUnitId *string `json:"administrativeUnitId,omitempty" tfsdk:"administrative_unit_id"` + AllowHierarchicalManagementGroupAssignment bool `json:"allowHierarchicalManagementGroupAssignment" tfsdk:"allow_hierarchical_management_group_assignment"` +} diff --git a/client/platform_config_gcp.go b/client/platform_config_gcp.go new file mode 100644 index 0000000..4812173 --- /dev/null +++ b/client/platform_config_gcp.go @@ -0,0 +1,51 @@ +package client + +type GcpPlatformConfig struct { + Replication *GcpReplicationConfig `json:"replication,omitempty" tfsdk:"replication"` + Metering *GcpMeteringConfig `json:"metering,omitempty" tfsdk:"metering"` +} + +type GcpReplicationConfig struct { + ServiceAccountConfig GcpServiceAccountConfig `json:"serviceAccountConfig" tfsdk:"service_account_config"` + Domain string `json:"domain" tfsdk:"domain"` + CustomerId string `json:"customerId" tfsdk:"customer_id"` + GroupNamePattern string `json:"groupNamePattern" tfsdk:"group_name_pattern"` + ProjectNamePattern string `json:"projectNamePattern" tfsdk:"project_name_pattern"` + ProjectIdPattern string `json:"projectIdPattern" tfsdk:"project_id_pattern"` + BillingAccountId string `json:"billingAccountId" tfsdk:"billing_account_id"` + UserLookupStrategy string `json:"userLookupStrategy" tfsdk:"user_lookup_strategy"` + UsedExternalIdType *string `json:"usedExternalIdType,omitempty" tfsdk:"used_external_id_type"` + GcpRoleMappings []GcpPlatformRoleMapping `json:"gcpRoleMappings" tfsdk:"gcp_role_mappings"` + AllowHierarchicalFolderAssignment bool `json:"allowHierarchicalFolderAssignment" tfsdk:"allow_hierarchical_folder_assignment"` + TenantTags *MeshTenantTags `json:"tenantTags,omitempty" tfsdk:"tenant_tags"` + SkipUserGroupPermissionCleanup bool `json:"skipUserGroupPermissionCleanup" tfsdk:"skip_user_group_permission_cleanup"` +} + +type GcpServiceAccountConfig struct { + ServiceAccountCredentialsConfig *GcpServiceAccountCredentialsConfig `json:"serviceAccountCredentialsConfig,omitempty" tfsdk:"service_account_credentials_config"` + ServiceAccountWorkloadIdentityConfig *GcpServiceAccountWorkloadIdentityConfig `json:"serviceAccountWorkloadIdentityConfig,omitempty" tfsdk:"service_account_workload_identity_config"` +} + +type GcpServiceAccountCredentialsConfig struct { + ServiceAccountCredentialsB64 string `json:"serviceAccountCredentialsB64" tfsdk:"service_account_credentials_b64"` +} + +type GcpServiceAccountWorkloadIdentityConfig struct { + Audience string `json:"audience" tfsdk:"audience"` + ServiceAccountEmail string `json:"serviceAccountEmail" tfsdk:"service_account_email"` +} + +type GcpPlatformRoleMapping struct { + MeshProjectRoleRef MeshProjectRoleRefV2 `json:"projectRoleRef" tfsdk:"project_role_ref"` + GcpRole string `json:"gcpRole" tfsdk:"gcp_role"` +} + +type GcpMeteringConfig struct { + ServiceAccountConfig GcpServiceAccountConfig `json:"serviceAccountConfig" tfsdk:"service_account_config"` + BigqueryTable string `json:"bigqueryTable" tfsdk:"bigquery_table"` + BigqueryTableForCarbonFootprint *string `json:"bigqueryTableForCarbonFootprint,omitempty" tfsdk:"bigquery_table_for_carbon_footprint"` + CarbonFootprintDataCollectionStartMonth *string `json:"carbonFootprintDataCollectionStartMonth,omitempty" tfsdk:"carbon_footprint_data_collection_start_month"` + PartitionTimeColumn string `json:"partitionTimeColumn" tfsdk:"partition_time_column"` + AdditionalFilter *string `json:"additionalFilter,omitempty" tfsdk:"additional_filter"` + Processing MeshPlatformMeteringProcessingConfig `json:"processing" tfsdk:"processing"` +} diff --git a/client/platform_config_kubernetes.go b/client/platform_config_kubernetes.go new file mode 100644 index 0000000..72b0d96 --- /dev/null +++ b/client/platform_config_kubernetes.go @@ -0,0 +1,22 @@ +package client + +type KubernetesPlatformConfig struct { + BaseUrl string `json:"baseUrl" tfsdk:"base_url"` + DisableSslValidation bool `json:"disableSslValidation" tfsdk:"disable_ssl_validation"` + Replication *KubernetesReplicationConfig `json:"replication" tfsdk:"replication"` + Metering *KubernetesMeteringConfig `json:"metering,omitempty" tfsdk:"metering"` +} + +type KubernetesReplicationConfig struct { + ClientConfig KubernetesClientConfig `json:"clientConfig" tfsdk:"client_config"` + NamespaceNamePattern string `json:"namespaceNamePattern" tfsdk:"namespace_name_pattern"` +} + +type KubernetesClientConfig struct { + AccessToken string `json:"accessToken" tfsdk:"access_token"` +} + +type KubernetesMeteringConfig struct { + ClientConfig KubernetesClientConfig `json:"clientConfig" tfsdk:"client_config"` + Processing MeshPlatformMeteringProcessingConfig `json:"processing" tfsdk:"processing"` +} diff --git a/client/platform_config_openshift.go b/client/platform_config_openshift.go new file mode 100644 index 0000000..2dc05c7 --- /dev/null +++ b/client/platform_config_openshift.go @@ -0,0 +1,28 @@ +package client + +type OpenShiftPlatformConfig struct { + BaseUrl string `json:"baseUrl" tfsdk:"base_url"` + DisableSslValidation bool `json:"disableSslValidation" tfsdk:"disable_ssl_validation"` + Replication *OpenShiftReplicationConfig `json:"replication" tfsdk:"replication"` + Metering *OpenShiftMeteringConfig `json:"metering,omitempty" tfsdk:"metering"` +} + +type OpenShiftReplicationConfig struct { + ClientConfig KubernetesClientConfig `json:"clientConfig" tfsdk:"client_config"` + WebConsoleUrl *string `json:"webConsoleUrl,omitempty" tfsdk:"web_console_url"` + ProjectNamePattern string `json:"projectNamePattern" tfsdk:"project_name_pattern"` + EnableTemplateInstantiation bool `json:"enableTemplateInstantiation" tfsdk:"enable_template_instantiation"` + OpenShiftRoleMappings []OpenShiftPlatformRoleMapping `json:"openshiftRoleMappings" tfsdk:"openshift_role_mappings"` + IdentityProviderName string `json:"identityProviderName" tfsdk:"identity_provider_name"` + TenantTags *MeshTenantTags `json:"tenantTags,omitempty" tfsdk:"tenant_tags"` +} + +type OpenShiftMeteringConfig struct { + ClientConfig KubernetesClientConfig `json:"clientConfig" tfsdk:"client_config"` + Processing MeshPlatformMeteringProcessingConfig `json:"processing" tfsdk:"processing"` +} + +type OpenShiftPlatformRoleMapping struct { + MeshProjectRoleRef MeshProjectRoleRefV2 `json:"projectRoleRef" tfsdk:"project_role_ref"` + OpenShiftRole string `json:"openshiftRole" tfsdk:"openshift_role"` +} diff --git a/client/platform_properties_azure.go b/client/platform_properties_azure.go index a06c010..6979403 100644 --- a/client/platform_properties_azure.go +++ b/client/platform_properties_azure.go @@ -1,11 +1,11 @@ package client type AzurePlatformProperties struct { - AzureRoleMappings []AzureRoleMapping `json:"azureRoleMappings" tfsdk:"azure_role_mappings"` - AzureManagementGroupId string `json:"azureManagementGroupId" tfsdk:"azure_management_group_id"` + AzureRoleMappings []AzureRoleMappingProperty `json:"azureRoleMappings" tfsdk:"azure_role_mappings"` + AzureManagementGroupId string `json:"azureManagementGroupId" tfsdk:"azure_management_group_id"` } -type AzureRoleMapping struct { +type AzureRoleMappingProperty struct { MeshProjectRoleRef MeshProjectRoleRefV2 `json:"projectRoleRef" tfsdk:"project_role_ref"` AzureGroupSuffix string `json:"azureGroupSuffix" tfsdk:"azure_group_suffix"` AzureRoleDefinitions []AzureRoleDefinition `json:"azureRoleDefinitions" tfsdk:"azure_role_definitions"` diff --git a/docs/data-sources/platform.md b/docs/data-sources/platform.md index bad0476..a245079 100644 --- a/docs/data-sources/platform.md +++ b/docs/data-sources/platform.md @@ -51,10 +51,6 @@ Read-Only: ### Nested Schema for `spec` -Required: - -- `quota_definitions` (List of Object) List of quota definitions for the platform. (see [below for nested schema](#nestedatt--spec--quota_definitions)) - Read-Only: - `availability` (Attributes) Availability configuration for the meshPlatform. (see [below for nested schema](#nestedatt--spec--availability)) @@ -65,22 +61,9 @@ Read-Only: - `documentation_url` (String) URL for platform documentation. - `endpoint` (String) The web console URL endpoint of the platform. - `location_ref` (Attributes) Reference to the location where this platform is situated. (see [below for nested schema](#nestedatt--spec--location_ref)) +- `quota_definitions` (List of Object) List of quota definitions for the platform. (see [below for nested schema](#nestedatt--spec--quota_definitions)) - `support_url` (String) URL for platform support documentation. - -### Nested Schema for `spec.quota_definitions` - -Read-Only: - -- `auto_approval_threshold` (Number) -- `description` (String) -- `label` (String) -- `max_value` (Number) -- `min_value` (Number) -- `quota_key` (String) -- `unit` (String) - - ### Nested Schema for `spec.availability` @@ -112,8 +95,35 @@ Read-Only: - `base_url` (String) Base URL of the AKS cluster - `disable_ssl_validation` (Boolean) Flag to disable SSL validation for the AKS cluster. (SSL Validation should at best never be disabled, but for integration of some private cloud platforms in an early state, they might not yet be using valid SSL certificates. In that case it can make sense to disable SSL validation here to already test integration of these platforms.) +- `metering` (Attributes) Metering configuration for AKS (optional, but required for metering) (see [below for nested schema](#nestedatt--spec--config--aks--metering)) - `replication` (Attributes) Replication configuration for AKS (optional, but required for replication) (see [below for nested schema](#nestedatt--spec--config--aks--replication)) + +### Nested Schema for `spec.config.aks.metering` + +Read-Only: + +- `client_config` (Attributes) Client configuration for AKS metering (see [below for nested schema](#nestedatt--spec--config--aks--metering--client_config)) +- `processing` (Attributes) Processing configuration for metering (see [below for nested schema](#nestedatt--spec--config--aks--metering--processing)) + + +### Nested Schema for `spec.config.aks.metering.client_config` + +Read-Only: + +- `access_token` (String, Sensitive) The Access Token of the service account for replicator access. + + + +### Nested Schema for `spec.config.aks.metering.processing` + +Read-Only: + +- `compact_timelines_after_days` (Number) Number of days after which timelines should be compacted. +- `delete_raw_data_after_days` (Number) Number of days after which raw data should be deleted. + + + ### Nested Schema for `spec.config.aks.replication` @@ -150,9 +160,59 @@ Read-Only: Read-Only: +- `metering` (Attributes) Metering configuration for AWS (optional, but required for metering) (see [below for nested schema](#nestedatt--spec--config--aws--metering)) - `region` (String) AWS region - `replication` (Attributes) Replication configuration for AWS (optional, but required for replication) (see [below for nested schema](#nestedatt--spec--config--aws--replication)) + +### Nested Schema for `spec.config.aws.metering` + +Read-Only: + +- `access_config` (Attributes) Access configuration for AWS metering (see [below for nested schema](#nestedatt--spec--config--aws--metering--access_config)) +- `filter` (String) Cost Explorer filter type (NONE or EXCLUDE_TAX) +- `processing` (Attributes) Processing configuration for metering (see [below for nested schema](#nestedatt--spec--config--aws--metering--processing)) +- `reserved_instance_fair_chargeback` (Boolean) Enable fair chargeback for reserved instances +- `savings_plan_fair_chargeback` (Boolean) Enable fair chargeback for savings plans + + +### Nested Schema for `spec.config.aws.metering.access_config` + +Read-Only: + +- `organization_root_account_external_id` (String) ExternalId for the organization root account role +- `organization_root_account_role` (String) ARN of the Management Account Role +- `service_user_config` (Attributes) Service user configuration (see [below for nested schema](#nestedatt--spec--config--aws--metering--access_config--service_user_config)) +- `workload_identity_config` (Attributes) Workload identity configuration (see [below for nested schema](#nestedatt--spec--config--aws--metering--access_config--workload_identity_config)) + + +### Nested Schema for `spec.config.aws.metering.access_config.service_user_config` + +Read-Only: + +- `access_key` (String) AWS access key +- `secret_key` (String, Sensitive) AWS secret key + + + +### Nested Schema for `spec.config.aws.metering.access_config.workload_identity_config` + +Read-Only: + +- `role_arn` (String) ARN of the role for workload identity + + + + +### Nested Schema for `spec.config.aws.metering.processing` + +Read-Only: + +- `compact_timelines_after_days` (Number) Number of days after which timelines should be compacted. +- `delete_raw_data_after_days` (Number) Number of days after which raw data should be deleted. + + + ### Nested Schema for `spec.config.aws.replication` @@ -220,24 +280,18 @@ Required: - `project_role_ref` (Attributes) the meshProject role (see [below for nested schema](#nestedatt--spec--config--aws--replication--aws_sso--aws_role_mappings--project_role_ref)) -Optional: - -- `permission_set_arns` (List of String) List of permission set ARNs associated with this role mapping - Read-Only: - `aws_role` (String) The AWS role name +- `permission_set_arns` (List of String) List of permission set ARNs associated with this role mapping ### Nested Schema for `spec.config.aws.replication.aws_sso.aws_role_mappings.project_role_ref` -Required: - -- `name` (String) The identifier of the meshProjectRole - Read-Only: - `kind` (String) meshObject type, always `meshProjectRole`. +- `name` (String) The identifier of the meshProjectRole @@ -277,8 +331,38 @@ Read-Only: Read-Only: - `entra_tenant` (String) Azure Active Directory (Entra ID) tenant +- `metering` (Attributes) Metering configuration for Azure (optional, but required for metering) (see [below for nested schema](#nestedatt--spec--config--azure--metering)) - `replication` (Attributes) Azure-specific replication configuration for the platform. (see [below for nested schema](#nestedatt--spec--config--azure--replication)) + +### Nested Schema for `spec.config.azure.metering` + +Read-Only: + +- `processing` (Attributes) Processing configuration for metering (see [below for nested schema](#nestedatt--spec--config--azure--metering--processing)) +- `service_principal` (Attributes) Service principal configuration for Azure metering (see [below for nested schema](#nestedatt--spec--config--azure--metering--service_principal)) + + +### Nested Schema for `spec.config.azure.metering.processing` + +Read-Only: + +- `compact_timelines_after_days` (Number) Number of days after which timelines should be compacted. +- `delete_raw_data_after_days` (Number) Number of days after which raw data should be deleted. + + + +### Nested Schema for `spec.config.azure.metering.service_principal` + +Read-Only: + +- `auth_type` (String) Authentication type (CREDENTIALS or WORKLOAD_IDENTITY) +- `client_id` (String) The Application (Client) ID +- `credentials_auth_client_secret` (String, Sensitive) Client secret (if authType is CREDENTIALS) +- `object_id` (String) The Object ID of the Enterprise Application + + + ### Nested Schema for `spec.config.azure.replication` @@ -312,13 +396,10 @@ Read-Only: ### Nested Schema for `spec.config.azure.replication.azure_role_mappings.project_role_ref` -Required: - -- `name` (String) The identifier of the meshProjectRole - Read-Only: - `kind` (String) meshObject type, always `meshProjectRole`. +- `name` (String) The identifier of the meshProjectRole @@ -336,7 +417,7 @@ Read-Only: Read-Only: -- `redirect_url` (String) This is the URL that Azure's consent experience redirects users to after they accept their invitation. +- `redirect_url` (String) - `send_azure_invitation_mail` (Boolean) When true, meshStack instructs Azure to send out Invitation mails to invited users. These mails allow users to redeem their invitation to the AAD tenant only using email and Azure Portal. @@ -492,8 +573,58 @@ Read-Only: Read-Only: +- `metering` (Attributes) Metering configuration for GCP (optional, but required for metering) (see [below for nested schema](#nestedatt--spec--config--gcp--metering)) - `replication` (Attributes) GCP-specific replication configuration for the platform. (see [below for nested schema](#nestedatt--spec--config--gcp--replication)) + +### Nested Schema for `spec.config.gcp.metering` + +Read-Only: + +- `additional_filter` (String) Additional filter for metering queries +- `bigquery_table` (String) BigQuery table for metering data +- `bigquery_table_for_carbon_footprint` (String) BigQuery table for carbon footprint data +- `carbon_footprint_data_collection_start_month` (String) Start month for carbon footprint data collection +- `partition_time_column` (String) Partition time column name +- `processing` (Attributes) Processing configuration for metering (see [below for nested schema](#nestedatt--spec--config--gcp--metering--processing)) +- `service_account_config` (Attributes) Service account configuration for GCP metering (see [below for nested schema](#nestedatt--spec--config--gcp--metering--service_account_config)) + + +### Nested Schema for `spec.config.gcp.metering.processing` + +Read-Only: + +- `compact_timelines_after_days` (Number) Number of days after which timelines should be compacted. +- `delete_raw_data_after_days` (Number) Number of days after which raw data should be deleted. + + + +### Nested Schema for `spec.config.gcp.metering.service_account_config` + +Read-Only: + +- `service_account_credentials_config` (Attributes) Service account credentials configuration (see [below for nested schema](#nestedatt--spec--config--gcp--metering--service_account_config--service_account_credentials_config)) +- `service_account_workload_identity_config` (Attributes) Service account workload identity configuration (see [below for nested schema](#nestedatt--spec--config--gcp--metering--service_account_config--service_account_workload_identity_config)) + + +### Nested Schema for `spec.config.gcp.metering.service_account_config.service_account_credentials_config` + +Read-Only: + +- `service_account_credentials_b64` (String, Sensitive) Base64 encoded service account credentials + + + +### Nested Schema for `spec.config.gcp.metering.service_account_config.service_account_workload_identity_config` + +Read-Only: + +- `audience` (String) The audience for workload identity +- `service_account_email` (String) Service account email address + + + + ### Nested Schema for `spec.config.gcp.replication` @@ -510,6 +641,7 @@ Read-Only: - `service_account_config` (Attributes) Service account configuration. Either `serviceAccountCredentialsConfig` or `serviceAccountWorkloadIdentityConfig` must be provided. (see [below for nested schema](#nestedatt--spec--config--gcp--replication--service_account_config)) - `skip_user_group_permission_cleanup` (Boolean) For certain use cases you might want to preserve user groups and replicated permission after a tenant was deleted on the GCP platform. Checking this option preserves those permissions. Please keep in mind that the platform operator is then responsible for cleaning them up later. - `tenant_tags` (Attributes) Tenant tags configuration (see [below for nested schema](#nestedatt--spec--config--gcp--replication--tenant_tags)) +- `used_external_id_type` (String) The type of external ID used for user lookup. - `user_lookup_strategy` (String) Users can either be looked up by E-Mail or externalAccountId. This must also be the property that is placed in the external user id (EUID) of your meshUser entity to match. E-Mail is usually a good choice as this is often set up as the EUID throughout all cloud platforms and meshStack. ('email' or 'externalId') @@ -526,13 +658,10 @@ Read-Only: ### Nested Schema for `spec.config.gcp.replication.gcp_role_mappings.project_role_ref` -Required: - -- `name` (String) The identifier of the meshProjectRole - Read-Only: - `kind` (String) meshObject type, always `meshProjectRole`. +- `name` (String) The identifier of the meshProjectRole @@ -589,8 +718,25 @@ Read-Only: - `base_url` (String) This URL is the base URL to your Kubernetes Cluster, which is used to call the APIs to create new Kubernetes projects, get raw data for metering the Kubernetes projects, etc. An example base URL is: https://k8s.dev.eu-de-central.msh.host:6443 - `disable_ssl_validation` (Boolean) Flag to disable SSL validation for the Kubernetes cluster. SSL Validation should at best never be disabled, but for integration of some private cloud platforms in an early state, they might not yet be using valid SSL certificates. In that case it can make sense to disable SSL validation here to already test integration of these platforms. +- `metering` (Attributes) Metering configuration for Kubernetes (optional, but required for metering) (see [below for nested schema](#nestedatt--spec--config--kubernetes--metering)) - `replication` (Attributes) Replication configuration for Kubernetes (optional, but required for replication) (see [below for nested schema](#nestedatt--spec--config--kubernetes--replication)) + +### Nested Schema for `spec.config.kubernetes.metering` + +Read-Only: + +- `client_config` (Attributes) Client configuration for Kubernetes metering (see [below for nested schema](#nestedatt--spec--config--kubernetes--metering--client_config)) + + +### Nested Schema for `spec.config.kubernetes.metering.client_config` + +Read-Only: + +- `access_token` (String, Sensitive) The Access Token of the service account for replicator access. + + + ### Nested Schema for `spec.config.kubernetes.replication` @@ -616,8 +762,35 @@ Read-Only: - `base_url` (String) This URL is the base URL to your OpenShift Cluster, which is used to call the APIs to create new OpenShift projects, get raw data for metering the OpenShift projects, etc. An example base URL is: https://api.okd4.dev.eu-de-central.msh.host:6443 - `disable_ssl_validation` (Boolean) Flag to disable SSL validation for the OpenShift cluster. SSL Validation should at best never be disabled, but for integration of some private cloud platforms in an early state, they might not yet be using valid SSL certificates. In that case it can make sense to disable SSL validation here to already test integration of these platforms. +- `metering` (Attributes) Metering configuration for OpenShift (optional, but required for metering) (see [below for nested schema](#nestedatt--spec--config--openshift--metering)) - `replication` (Attributes) Replication configuration for OpenShift (optional, but required for replication) (see [below for nested schema](#nestedatt--spec--config--openshift--replication)) + +### Nested Schema for `spec.config.openshift.metering` + +Read-Only: + +- `client_config` (Attributes) Client configuration for OpenShift metering (see [below for nested schema](#nestedatt--spec--config--openshift--metering--client_config)) +- `processing` (Attributes) Processing configuration for metering (see [below for nested schema](#nestedatt--spec--config--openshift--metering--processing)) + + +### Nested Schema for `spec.config.openshift.metering.client_config` + +Read-Only: + +- `access_token` (String, Sensitive) The Access Token of the service account for replicator access. + + + +### Nested Schema for `spec.config.openshift.metering.processing` + +Read-Only: + +- `compact_timelines_after_days` (Number) Number of days after which timelines should be compacted. +- `delete_raw_data_after_days` (Number) Number of days after which raw data should be deleted. + + + ### Nested Schema for `spec.config.openshift.replication` @@ -653,13 +826,10 @@ Read-Only: ### Nested Schema for `spec.config.openshift.replication.openshift_role_mappings.project_role_ref` -Required: - -- `name` (String) The identifier of the meshProjectRole - Read-Only: - `kind` (String) meshObject type, always `meshProjectRole`. +- `name` (String) The identifier of the meshProjectRole @@ -691,3 +861,17 @@ Read-Only: - `kind` (String) Must always be set to meshLocation - `name` (String) Identifier of the Location. + + + +### Nested Schema for `spec.quota_definitions` + +Read-Only: + +- `auto_approval_threshold` (Number) +- `description` (String) +- `label` (String) +- `max_value` (Number) +- `min_value` (Number) +- `quota_key` (String) +- `unit` (String) diff --git a/docs/resources/platform.md b/docs/resources/platform.md index 2ce53bd..f6f0be9 100644 --- a/docs/resources/platform.md +++ b/docs/resources/platform.md @@ -191,12 +191,12 @@ Required: - `display_name` (String) The human-readable display name of the meshPlatform. - `endpoint` (String) The web console URL endpoint of the platform. - `location_ref` (Attributes) Reference to the location where this platform is situated. (see [below for nested schema](#nestedatt--spec--location_ref)) -- `quota_definitions` (List of Object) List of quota definitions for the platform. (see [below for nested schema](#nestedatt--spec--quota_definitions)) Optional: - `contributing_workspaces` (List of String) A list of workspace identifiers that may contribute to this meshPlatform. - `documentation_url` (String) URL for platform documentation. +- `quota_definitions` (List of Object) List of quota definitions for the platform. (see [below for nested schema](#nestedatt--spec--quota_definitions)) - `support_url` (String) URL for platform support documentation. @@ -239,25 +239,55 @@ Required: Optional: - `disable_ssl_validation` (Boolean) Flag to disable SSL validation for the AKS cluster. (SSL Validation should at best never be disabled, but for integration of some private cloud platforms in an early state, they might not yet be using valid SSL certificates. In that case it can make sense to disable SSL validation here to already test integration of these platforms.) +- `metering` (Attributes) Metering configuration for AKS (optional, but required for metering) (see [below for nested schema](#nestedatt--spec--config--aks--metering)) - `replication` (Attributes) Replication configuration for AKS (optional, but required for replication) (see [below for nested schema](#nestedatt--spec--config--aks--replication)) + +### Nested Schema for `spec.config.aks.metering` + +Required: + +- `client_config` (Attributes) Client configuration for AKS metering (see [below for nested schema](#nestedatt--spec--config--aks--metering--client_config)) +- `processing` (Attributes) Processing configuration for metering (see [below for nested schema](#nestedatt--spec--config--aks--metering--processing)) + + +### Nested Schema for `spec.config.aks.metering.client_config` + +Required: + +- `access_token` (String, Sensitive) The Access Token of the service account for replicator access. + + + +### Nested Schema for `spec.config.aks.metering.processing` + +Optional: + +- `compact_timelines_after_days` (Number) Number of days after which timelines should be compacted. +- `delete_raw_data_after_days` (Number) Number of days after which raw data should be deleted. + + + ### Nested Schema for `spec.config.aks.replication` -Optional: +Required: - `access_token` (String, Sensitive) The Access Token of the service account for replicator access. -- `administrative_unit_id` (String) If you enter an administrative unit ID the replicated (and potentially existing) groups will be put into this AU. This can be used to limit the permission scopes which are required for the replicator principal. If you remove the AU ID again or change it, the groups will not be removed from the old AU. - `aks_cluster_name` (String) Name of the AKS cluster. - `aks_resource_group` (String) Resource group for the AKS cluster - `aks_subscription_id` (String) Subscription ID for the AKS cluster - `group_name_pattern` (String) Pattern for naming groups in AKS - `namespace_name_pattern` (String) Pattern for naming namespaces in AKS -- `redirect_url` (String) This is the URL that Azure’s consent experience redirects users to after they accept their invitation. - `send_azure_invitation_mail` (Boolean) Flag to send Azure invitation emails. When true, meshStack instructs Azure to send out Invitation mails to invited users. - `service_principal` (Attributes) Service principal configuration for AKS (see [below for nested schema](#nestedatt--spec--config--aks--replication--service_principal)) - `user_look_up_strategy` (String) Strategy for user lookup in Azure (`userPrincipalName` or `email`) +Optional: + +- `administrative_unit_id` (String) If you enter an administrative unit ID the replicated (and potentially existing) groups will be put into this AU. This can be used to limit the permission scopes which are required for the replicator principal. If you remove the AU ID again or change it, the groups will not be removed from the old AU. +- `redirect_url` (String) This is the URL that Azure's consent experience redirects users to after they accept their invitation. + ### Nested Schema for `spec.config.aks.replication.service_principal` @@ -280,29 +310,85 @@ Optional: Optional: +- `metering` (Attributes) Metering configuration for AWS (optional, but required for metering) (see [below for nested schema](#nestedatt--spec--config--aws--metering)) - `region` (String) AWS region - `replication` (Attributes) Replication configuration for AWS (optional, but required for replication) (see [below for nested schema](#nestedatt--spec--config--aws--replication)) + +### Nested Schema for `spec.config.aws.metering` + +Required: + +- `access_config` (Attributes) meshStack currently supports 2 types of authentication. Workload Identity Federation (using OIDC) is the one that we recommend as it enables secure access to your AWS account without using long lived credentials. Alternatively, you can use credential based authentication by providing access and secret keys. Either the `service_user_config` or `workload_identity_config` must be provided. (see [below for nested schema](#nestedatt--spec--config--aws--metering--access_config)) +- `filter` (String) Filter for AWS metering data. +- `processing` (Attributes) Processing configuration for metering (see [below for nested schema](#nestedatt--spec--config--aws--metering--processing)) +- `reserved_instance_fair_chargeback` (Boolean) Flag to enable fair chargeback for reserved instances. +- `savings_plan_fair_chargeback` (Boolean) Flag to enable fair chargeback for savings plans. + + +### Nested Schema for `spec.config.aws.metering.access_config` + +Required: + +- `organization_root_account_role` (String) ARN of the Management Account Role. The Management Account contains your AWS organization. E.g. `arn:aws:iam::123456789:role/MeshfedServiceRole`. + +Optional: + +- `organization_root_account_external_id` (String) ExternalId to enhance security in a multi account setup when assuming the organization root account role. +- `service_user_config` (Attributes) Service user configuration (alternative to `workload_identity_config`) (see [below for nested schema](#nestedatt--spec--config--aws--metering--access_config--service_user_config)) +- `workload_identity_config` (Attributes) Workload identity configuration (alternative to `service_user_config`) (see [below for nested schema](#nestedatt--spec--config--aws--metering--access_config--workload_identity_config)) + + +### Nested Schema for `spec.config.aws.metering.access_config.service_user_config` + +Required: + +- `access_key` (String) AWS access key for service user +- `secret_key` (String, Sensitive) AWS secret key for service user + + + +### Nested Schema for `spec.config.aws.metering.access_config.workload_identity_config` + +Required: + +- `role_arn` (String) ARN of the role that should be used as the entry point for meshStack by assuming it via web identity. + + + + +### Nested Schema for `spec.config.aws.metering.processing` + +Optional: + +- `compact_timelines_after_days` (Number) Number of days after which timelines should be compacted. +- `delete_raw_data_after_days` (Number) Number of days after which raw data should be deleted. + + + ### Nested Schema for `spec.config.aws.replication` -Optional: +Required: - `access_config` (Attributes) meshStack currently supports 2 types of authentication. Workload Identity Federation (using OIDC) is the one that we recommend as it enables secure access to your AWS account without using long lived credentials. Alternatively, you can use credential based authentication by providing access and secret keys. Either the `service_user_config` or `workload_identity_config` must be provided. (see [below for nested schema](#nestedatt--spec--config--aws--replication--access_config)) - `account_access_role` (String) The name for the Account Access Role that will be rolled out to all managed accounts. Only a name, not an ARN must be set here, as the ARN must be built dynamically for every managed AWS Account. The replicator service user needs to assume this role in all accounts to manage them. - `account_alias_pattern` (String) With a String Pattern you can define how the account alias of the created AWS account will be named. E.g. `#{workspaceIdentifier}-#{projectIdentifier}`. Attention: Account Alias must be globally unique in AWS. So consider defining a unique prefix. - `account_email_pattern` (String) With a String Pattern you can define how the account email address of the created AWS account will be set. E.g. `aws+#{workspaceIdentifier}.#{projectIdentifier}@yourcompany.com`. Please consider that this email address is limited to 64 characters! Also have a look at our docs for more information. - `allow_hierarchical_organizational_unit_assignment` (Boolean) Configuration flag to enable or disable hierarchical organizational unit assignment in AWS. If set to true: Accounts can be moved to child organizational units of the organizational unit defined in the Landing Zone. This is useful if you want to manage the account location with a deeper and more granular hierarchy. If set to false: Accounts will always be moved directly to the organizational unit defined in the Landing Zone. -- `automation_account_external_id` (String) ExternalId to enhance security in a multi account setup when assuming the automation account role. - `automation_account_role` (String) ARN of the Automation Account Role. The Automation Account contains all AWS StackSets and Lambda Functions that shall be executed via meshLandingZones. E.g. `arn:aws:iam::123456789:role/MeshfedAutomationRole`. -- `aws_sso` (Attributes) AWS SSO configuration (see [below for nested schema](#nestedatt--spec--config--aws--replication--aws_sso)) - `enforce_account_alias` (Boolean) Flag to enforce account alias. If set, meshStack will guarantee on every replication that the configured Account Alias is applied. Otherwise it will only set the Account Alias once during tenant creation. -- `enrollment_configuration` (Attributes) AWS account enrollment configuration. (see [below for nested schema](#nestedatt--spec--config--aws--replication--enrollment_configuration)) - `self_downgrade_access_role` (Boolean) Flag for self downgrade access role. If set, meshStack will revoke its rights on the managed account that were only needed for initial account creation. - `skip_user_group_permission_cleanup` (Boolean) Flag to skip user group permission cleanup. For certain use cases you might want to preserve user groups and replicated permission after a tenant was deleted on the AWS platform. Checking this option preserves those permissions. Please keep in mind that the platform operator is then responsible for cleaning them up later. -- `tenant_tags` (Attributes) Tenant tags configuration (see [below for nested schema](#nestedatt--spec--config--aws--replication--tenant_tags)) - `wait_for_external_avm` (Boolean) Flag to wait for external AVM. Please use this setting with care! It is currently very specific to certain tags being present on the account! In general, we recommend not to activate this functionality! In a meshLandingZone an AVM can be triggered via an AWS StackSet or via a Lambda Function. If meshStack shall wait for the AVM to complete when creating a new platform tenant, this flag must be checked. meshStack will identify completion of the AVM by checking the presence of the following tags on the AWS account: 'ProductName' is set to workspace identifier and 'Stage' is set to project identifier. +Optional: + +- `automation_account_external_id` (String) ExternalId to enhance security in a multi account setup when assuming the automation account role. +- `aws_sso` (Attributes) AWS SSO configuration (see [below for nested schema](#nestedatt--spec--config--aws--replication--aws_sso)) +- `enrollment_configuration` (Attributes) AWS account enrollment configuration. (see [below for nested schema](#nestedatt--spec--config--aws--replication--enrollment_configuration)) +- `tenant_tags` (Attributes) Tenant tags configuration (see [below for nested schema](#nestedatt--spec--config--aws--replication--tenant_tags)) + ### Nested Schema for `spec.config.aws.replication.access_config` @@ -322,9 +408,6 @@ Optional: Required: - `access_key` (String) AWS access key for service user - -Optional: - - `secret_key` (String, Sensitive) AWS secret key for service user @@ -413,30 +496,69 @@ Required: ### Nested Schema for `spec.config.azure` -Optional: +Required: - `entra_tenant` (String) Azure Active Directory (Entra ID) tenant + +Optional: + +- `metering` (Attributes) Metering configuration for Azure (optional, but required for metering) (see [below for nested schema](#nestedatt--spec--config--azure--metering)) - `replication` (Attributes) Azure-specific replication configuration for the platform. (see [below for nested schema](#nestedatt--spec--config--azure--replication)) + +### Nested Schema for `spec.config.azure.metering` + +Required: + +- `processing` (Attributes) Processing configuration for metering (see [below for nested schema](#nestedatt--spec--config--azure--metering--processing)) +- `service_principal` (Attributes) Service principal configuration for Azure metering (see [below for nested schema](#nestedatt--spec--config--azure--metering--service_principal)) + + +### Nested Schema for `spec.config.azure.metering.processing` + +Optional: + +- `compact_timelines_after_days` (Number) Number of days after which timelines should be compacted. +- `delete_raw_data_after_days` (Number) Number of days after which raw data should be deleted. + + + +### Nested Schema for `spec.config.azure.metering.service_principal` + +Required: + +- `auth_type` (String) Authentication type (`CREDENTIALS` or `WORKLOAD_IDENTITY`) +- `client_id` (String) The Application (Client) ID. In Azure Portal, this is the Application ID of the 'Enterprise Application' but can also be retrieved via the 'App Registration' object as 'Application (Client) ID +- `object_id` (String) The Object ID of the Enterprise Application. You can get this Object ID via the API (e.g. when using our Terraform provider) or from Enterprise applications pane in Microsoft Entra admin center. + +Optional: + +- `credentials_auth_client_secret` (String, Sensitive) Client secret (if authType is `CREDENTIALS`) + + + ### Nested Schema for `spec.config.azure.replication` -Optional: +Required: -- `administrative_unit_id` (String) If you enter an administrative unit ID the replicated (and potentially existing) groups will be put into this AU. This can be used to limit the permission scopes which are required for the replicator principal. If you remove the AU ID again or change it, the groups will not be removed from the old AU. - `allow_hierarchical_management_group_assignment` (Boolean) Configuration flag to enable or disable hierarchical management group assignment in Azure. If set to true: Subscriptions can be moved to sub management groups of the management group defined in the Landing Zone. This is useful if you want to manage the subscription location with a deeper and more granular hierarchy. If set to false: Subscriptions will always be moved directly to the management group defined in the Landing Zone. - `azure_role_mappings` (Attributes List) Azure role mappings for Azure role definitions. (see [below for nested schema](#nestedatt--spec--config--azure--replication--azure_role_mappings)) -- `b2b_user_invitation` (Attributes) Optional B2B user invitation configuration. When configured, instructs the replicator to create AAD B2B guest invitations for users missing in the AAD tenant managed by this meshPlatform. (see [below for nested schema](#nestedatt--spec--config--azure--replication--b2b_user_invitation)) -- `blueprint_location` (String) The Azure location where replication creates and updates Blueprint Assignments. Note that it’s still possible that the Blueprint creates resources in other locations, this is merely the location where the Blueprint Assignment is managed. - `blueprint_service_principal` (String) Object ID of the Enterprise Application belonging to the Microsoft Application 'Azure Blueprints'. meshStack will grant the necessary permissions on managed Subscriptions to this SPN so that it can create System Assigned Managed Identities (SAMI) for Blueprint execution. - `group_name_pattern` (String) Configures the pattern that defines the desired name of AAD groups managed by meshStack. It follows the usual replicator string pattern features and provides the additional replacement 'platformGroupAlias', which contains the role name suffix, which is configurable via Role Mappings in this platform config or via a meshLandingZone. Operators must ensure the group names are unique in the managed AAD Tenant. -- `provisioning` (Attributes) To provide Azure Subscription for your organization’s meshProjects, meshcloud supports using Enterprise Enrollment or allocating from a pool of pre-provisioned subscriptions. One of the subFields enterpriseEnrollment, customerAgreement or preProvisioned must be provided! (see [below for nested schema](#nestedatt--spec--config--azure--replication--provisioning)) - `service_principal` (Attributes) Service principal configuration for Azure (see [below for nested schema](#nestedatt--spec--config--azure--replication--service_principal)) - `skip_user_group_permission_cleanup` (Boolean) Flag to skip user group permission cleanup. For certain use cases you might want to preserve user groups and replicated permission after a tenant was deleted on the Azure platform. Checking this option preserves those permissions. Please keep in mind that the platform operator is then responsible for cleaning them up later. - `subscription_name_pattern` (String) Configures the pattern that defines the desired name of Azure Subscriptions managed by meshStack. -- `tenant_tags` (Attributes) Tenant tagging configuration. (see [below for nested schema](#nestedatt--spec--config--azure--replication--tenant_tags)) - `user_look_up_strategy` (String) User lookup strategy (`userPrincipalName` or `email`). Users can either be looked up in cloud platforms by email or UPN (User Principal Name). In most cases email is the matching way as it is the only identifier that is consistently used throughout all cloud platforms and meshStack. +Optional: + +- `administrative_unit_id` (String) If you enter an administrative unit ID the replicated (and potentially existing) groups will be put into this AU. This can be used to limit the permission scopes which are required for the replicator principal. If you remove the AU ID again or change it, the groups will not be removed from the old AU. +- `b2b_user_invitation` (Attributes) Optional B2B user invitation configuration. When configured, instructs the replicator to create AAD B2B guest invitations for users missing in the AAD tenant managed by this meshPlatform. (see [below for nested schema](#nestedatt--spec--config--azure--replication--b2b_user_invitation)) +- `blueprint_location` (String) The Azure location where replication creates and updates Blueprint Assignments. Note that it's still possible that the Blueprint creates resources in other locations, this is merely the location where the Blueprint Assignment is managed. +- `provisioning` (Attributes) To provide Azure Subscription for your organization's meshProjects, meshcloud supports using Enterprise Enrollment or allocating from a pool of pre-provisioned subscriptions. One of the subFields enterpriseEnrollment, customerAgreement or preProvisioned must be provided! (see [below for nested schema](#nestedatt--spec--config--azure--replication--provisioning)) +- `tenant_tags` (Attributes) Tenant tagging configuration. (see [below for nested schema](#nestedatt--spec--config--azure--replication--tenant_tags)) + ### Nested Schema for `spec.config.azure.replication.azure_role_mappings` @@ -467,12 +589,26 @@ Read-Only: + +### Nested Schema for `spec.config.azure.replication.service_principal` + +Required: + +- `auth_type` (String) Authentication type (`CREDENTIALS` or `WORKLOAD_IDENTITY`) +- `client_id` (String) The Application (Client) ID. In Azure Portal, this is the Application ID of the 'Enterprise Application' but can also be retrieved via the 'App Registration' object as 'Application (Client) ID +- `object_id` (String) The Object ID of the Enterprise Application. You can get this Object ID via the API (e.g. when using our Terraform provider) or from Enterprise applications pane in Microsoft Entra admin center. + +Optional: + +- `credentials_auth_client_secret` (String, Sensitive) Client secret (if authType is `CREDENTIALS`) + + ### Nested Schema for `spec.config.azure.replication.b2b_user_invitation` -Optional: +Required: -- `redirect_url` (String) This is the URL that Azure’s consent experience redirects users to after they accept their invitation. +- `redirect_url` (String) This is the URL that Azure's consent experience redirects users to after they accept their invitation. - `send_azure_invitation_mail` (Boolean) When true, meshStack instructs Azure to send out Invitation mails to invited users. These mails allow users to redeem their invitation to the AAD tenant only using email and Azure Portal. @@ -483,8 +619,8 @@ Optional: - `customer_agreement` (Attributes) meshcloud can automatically provision new subscriptions from a Customer Agreement Account owned by your organization. This is suitable for larger organizations that have such a Customer Agreement with Microsoft, and want to provide a large number of subscriptions in a fully automated fashion. (see [below for nested schema](#nestedatt--spec--config--azure--replication--provisioning--customer_agreement)) - `enterprise_enrollment` (Attributes) meshcloud can automatically provision new subscriptions from an Enterprise Enrollment Account owned by your organization. This is suitable for large organizations that have a Microsoft Enterprise Agreement, Microsoft Customer Agreement or a Microsoft Partner Agreement and want to provide a large number of subscriptions in a fully automated fashion. (see [below for nested schema](#nestedatt--spec--config--azure--replication--provisioning--enterprise_enrollment)) -- `pre_provisioned` (Attributes) If your organization does not have access to an Enterprise Enrollment, you can alternatively configure meshcloud to consume subscriptions from a pool of externally-provisioned subscriptions. This is useful for smaller organizations that wish to use 'Pay-as-you-go' subscriptions or if you’re organization partners with an Azure Cloud Solution Provider to provide your subscriptions. The meshcloud Azure replication detects externally-provisioned subscriptions based on a configurable prefix in the subscription name. Upon assignment to a meshProject, the subscription is inflated with the right Landing Zone configuration and removed from the subscription pool. (see [below for nested schema](#nestedatt--spec--config--azure--replication--provisioning--pre_provisioned)) -- `subscription_owner_object_ids` (List of String) One or more principals Object IDs (e.g. user groups, SPNs) that meshStack will ensure have an 'Owner' role assignment on the managed subscriptions. This can be useful to satisfy Azure’s constraint of at least one direct 'Owner' role assignment per Subscription. If you want to use a Service Principal please use the Enterprise Application Object ID. You can not use the replicator object ID here, because meshStack always removes its high privilege access after a Subscription creation. +- `pre_provisioned` (Attributes) If your organization does not have access to an Enterprise Enrollment, you can alternatively configure meshcloud to consume subscriptions from a pool of externally-provisioned subscriptions. This is useful for smaller organizations that wish to use 'Pay-as-you-go' subscriptions or if you're organization partners with an Azure Cloud Solution Provider to provide your subscriptions. The meshcloud Azure replication detects externally-provisioned subscriptions based on a configurable prefix in the subscription name. Upon assignment to a meshProject, the subscription is inflated with the right Landing Zone configuration and removed from the subscription pool. (see [below for nested schema](#nestedatt--spec--config--azure--replication--provisioning--pre_provisioned)) +- `subscription_owner_object_ids` (List of String) One or more principals Object IDs (e.g. user groups, SPNs) that meshStack will ensure have an 'Owner' role assignment on the managed subscriptions. This can be useful to satisfy Azure's constraint of at least one direct 'Owner' role assignment per Subscription. If you want to use a Service Principal please use the Enterprise Application Object ID. You can not use the replicator object ID here, because meshStack always removes its high privilege access after a Subscription creation. ### Nested Schema for `spec.config.azure.replication.provisioning.customer_agreement` @@ -498,7 +634,7 @@ Required: Optional: - `source_service_principal` (Attributes) Configure the SPN used by meshStack to create a new Subscription in your MCA billing scope. For more information on the required permissions, see the [Azure docs](https://learn.microsoft.com/en-us/azure/cost-management-billing/manage/programmatically-create-subscription-microsoft-customer-agreement-across-tenants). (see [below for nested schema](#nestedatt--spec--config--azure--replication--provisioning--customer_agreement--source_service_principal)) -- `subscription_creation_error_cooldown_sec` (Number) This value must be defined in seconds. It is a safety mechanism to avoid duplicate Subscription creation in case of an error on Azure’s MCA API. This delay should be a bit higher than it usually takes to create subscriptions. For big installations this is somewhere between 5-15 minutes. The default of 900s should be fine for most installations. +- `subscription_creation_error_cooldown_sec` (Number) This value must be defined in seconds. It is a safety mechanism to avoid duplicate Subscription creation in case of an error on Azure's MCA API. This delay should be a bit higher than it usually takes to create subscriptions. For big installations this is somewhere between 5-15 minutes. The default of 900s should be fine for most installations. ### Nested Schema for `spec.config.azure.replication.provisioning.customer_agreement.source_service_principal` @@ -524,7 +660,7 @@ Required: Optional: -- `subscription_creation_error_cooldown_sec` (Number) This value must be defined in seconds. It is a safety mechanism to avoid duplicate Subscription creation in case of an error on Azure’s MCA API. This delay should be a bit higher than it usually takes to create subscriptions. For big installations this is somewhere between 5-15 minutes. The default of 900s should be fine for most installations. +- `subscription_creation_error_cooldown_sec` (Number) This value must be defined in seconds. It is a safety mechanism to avoid duplicate Subscription creation in case of an error on Azure's MCA API. This delay should be a bit higher than it usually takes to create subscriptions. For big installations this is somewhere between 5-15 minutes. The default of 900s should be fine for most installations. - `use_legacy_subscription_enrollment` (Boolean) Deprecated: Uses the old Subscription enrollment API in its preview version. This enrollment is less reliable and should not be used for new Azure Platform Integrations. @@ -533,23 +669,9 @@ Optional: Required: -- `unused_subscription_name_prefix` (String) The prefix that identifies unused subscriptions. Subscriptions will be renamed during meshStack’s project replication, at which point they should no longer carry this prefix. - +- `unused_subscription_name_prefix` (String) The prefix that identifies unused subscriptions. Subscriptions will be renamed during meshStack's project replication, at which point they should no longer carry this prefix. - -### Nested Schema for `spec.config.azure.replication.service_principal` - -Required: - -- `auth_type` (String) Authentication type (`CREDENTIALS` or `WORKLOAD_IDENTITY`) -- `client_id` (String) The Application (Client) ID. In Azure Portal, this is the Application ID of the 'Enterprise Application' but can also be retrieved via the 'App Registration' object as 'Application (Client) ID -- `object_id` (String) The Object ID of the Enterprise Application. You can get this Object ID via the API (e.g. when using our Terraform provider) or from Enterprise applications pane in Microsoft Entra admin center. - -Optional: - -- `credentials_auth_client_secret` (String, Sensitive) Client secret (if authType is `CREDENTIALS`) - ### Nested Schema for `spec.config.azure.replication.tenant_tags` @@ -577,35 +699,32 @@ Required: ### Nested Schema for `spec.config.azurerg` -Optional: +Required: - `entra_tenant` (String) Azure Active Directory (Entra ID) tenant + +Optional: + - `replication` (Attributes) Azure Resource Group-specific replication configuration for the platform. (see [below for nested schema](#nestedatt--spec--config--azurerg--replication)) ### Nested Schema for `spec.config.azurerg.replication` -Optional: +Required: -- `administrative_unit_id` (String) If you enter an administrative unit ID the replicated (and potentially existing) groups will be put into this AU. This can be used to limit the permission scopes which are required for the replicator principal. If you remove the AU ID again or change it, the groups will not be removed from the old AU. - `allow_hierarchical_management_group_assignment` (Boolean) Configuration flag to enable or disable hierarchical management group assignment in Azure. If set to true: Subscriptions can be moved to child management groups of the management group defined in the Landing Zone. This is useful if you want to manage the subscription location with a deeper and more granular hierarchy. If set to false: Subscriptions will always be moved directly to the management group defined in the Landing Zone. -- `b2b_user_invitation` (Attributes) Optional B2B user invitation configuration. When configured, instructs the replicator to create AAD B2B guest invitations for users missing in the AAD tenant managed by this meshPlatform. (see [below for nested schema](#nestedatt--spec--config--azurerg--replication--b2b_user_invitation)) - `resource_group_name_pattern` (String) Configures the pattern that defines the desired name Resource Group managed by meshStack. It follows the usual replicator string pattern features. Operators must ensure the group names are unique within the Subscription. - `service_principal` (Attributes) Service principal configuration for Azure Resource Group access. (see [below for nested schema](#nestedatt--spec--config--azurerg--replication--service_principal)) - `skip_user_group_permission_cleanup` (Boolean) For certain use cases you might want to preserve user groups and replicated permission after a tenant was deleted on the Azure platform. Checking this option preserves those permissions. Please keep in mind that the platform operator is then responsible for cleaning them up later. - `subscription` (String) The Subscription that will contain all the created Resource Groups. Once you set the Subscription, you must not change it. -- `tenant_tags` (Attributes) Tenant tags configuration (see [below for nested schema](#nestedatt--spec--config--azurerg--replication--tenant_tags)) - `user_group_name_pattern` (String) Configures the pattern that defines the desired name of AAD groups managed by meshStack. It follows the usual replicator string pattern features and provides the additional replacement 'platformGroupAlias', which contains the role name suffix. This suffix is configurable via Role Mappings in this platform config. - `user_look_up_strategy` (String) User lookup strategy (`userPrincipalName` or `email`). Users can either be looked up in cloud platforms by email or UPN (User Principal Name). In most cases email is the matching way as it is the only identifier that is consistently used throughout all cloud platforms and meshStack. - -### Nested Schema for `spec.config.azurerg.replication.b2b_user_invitation` - Optional: -- `redirect_url` (String) This is the URL that Azure’s consent experience redirects users to after they accept their invitation. -- `send_azure_invitation_mail` (Boolean) When true, meshStack instructs Azure to send out Invitation mails to invited users. These mails allow users to redeem their invitation to the AAD tenant only using email and Azure Portal. - +- `administrative_unit_id` (String) If you enter an administrative unit ID the replicated (and potentially existing) groups will be put into this AU. This can be used to limit the permission scopes which are required for the replicator principal. If you remove the AU ID again or change it, the groups will not be removed from the old AU. +- `b2b_user_invitation` (Attributes) Optional B2B user invitation configuration. When configured, instructs the replicator to create AAD B2B guest invitations for users missing in the AAD tenant managed by this meshPlatform. (see [below for nested schema](#nestedatt--spec--config--azurerg--replication--b2b_user_invitation)) +- `tenant_tags` (Attributes) Tenant tags configuration (see [below for nested schema](#nestedatt--spec--config--azurerg--replication--tenant_tags)) ### Nested Schema for `spec.config.azurerg.replication.service_principal` @@ -621,6 +740,15 @@ Optional: - `credentials_auth_client_secret` (String, Sensitive) Client secret (if authType is `CREDENTIALS`) + +### Nested Schema for `spec.config.azurerg.replication.b2b_user_invitation` + +Required: + +- `redirect_url` (String) This is the URL that Azure's consent experience redirects users to after they accept their invitation. +- `send_azure_invitation_mail` (Boolean) When true, meshStack instructs Azure to send out Invitation mails to invited users. These mails allow users to redeem their invitation to the AAD tenant only using email and Azure Portal. + + ### Nested Schema for `spec.config.azurerg.replication.tenant_tags` @@ -649,12 +777,65 @@ Required: Optional: +- `metering` (Attributes) Metering configuration for GCP (optional, but required for metering) (see [below for nested schema](#nestedatt--spec--config--gcp--metering)) - `replication` (Attributes) GCP-specific replication configuration for the platform. (see [below for nested schema](#nestedatt--spec--config--gcp--replication)) + +### Nested Schema for `spec.config.gcp.metering` + +Required: + +- `bigquery_table` (String) BigQuery table for metering data. +- `partition_time_column` (String) Partition time column for BigQuery table. +- `processing` (Attributes) Processing configuration for metering (see [below for nested schema](#nestedatt--spec--config--gcp--metering--processing)) +- `service_account_config` (Attributes) Service account configuration. Either `serviceAccountCredentialsConfig` or `serviceAccountWorkloadIdentityConfig` must be provided. (see [below for nested schema](#nestedatt--spec--config--gcp--metering--service_account_config)) + +Optional: + +- `additional_filter` (String) Additional filter for metering data. +- `bigquery_table_for_carbon_footprint` (String) BigQuery table for carbon footprint data. +- `carbon_footprint_data_collection_start_month` (String) Start month for carbon footprint data collection. + + +### Nested Schema for `spec.config.gcp.metering.processing` + +Optional: + +- `compact_timelines_after_days` (Number) Number of days after which timelines should be compacted. +- `delete_raw_data_after_days` (Number) Number of days after which raw data should be deleted. + + + +### Nested Schema for `spec.config.gcp.metering.service_account_config` + +Optional: + +- `service_account_credentials_config` (Attributes) Service account credentials configuration (alternative to serviceAccountWorkloadIdentityConfig) (see [below for nested schema](#nestedatt--spec--config--gcp--metering--service_account_config--service_account_credentials_config)) +- `service_account_workload_identity_config` (Attributes) Service account workload identity configuration (alternative to serviceAccountCredentialsConfig) (see [below for nested schema](#nestedatt--spec--config--gcp--metering--service_account_config--service_account_workload_identity_config)) + + +### Nested Schema for `spec.config.gcp.metering.service_account_config.service_account_credentials_config` + +Required: + +- `service_account_credentials_b64` (String, Sensitive) Base64 encoded credentials.json file for a GCP ServiceAccount. The replicator uses this Service Account to automate GCP API operations (IAM, ResourceManager etc.). + + + +### Nested Schema for `spec.config.gcp.metering.service_account_config.service_account_workload_identity_config` + +Required: + +- `audience` (String) The audience associated with your workload identity pool provider. +- `service_account_email` (String) The email address of the Service Account, that gets impersonated for calling Google APIs via Workload Identity Federation. + + + + ### Nested Schema for `spec.config.gcp.replication` -Optional: +Required: - `allow_hierarchical_folder_assignment` (Boolean) Configuration flag to enable or disable hierarchical folder assignment in GCP. If set to true: Projects can be moved to sub folders of the folder defined in the Landing Zone. This is useful if you want to manage the project location with a deeper and more granular hierarchy. If set to false: Projects will always be moved directly to the folder defined in the Landing Zone. - `billing_account_id` (String) The ID of the billing account to associate with all GCP projects managed by meshStack @@ -666,9 +847,13 @@ Optional: - `project_name_pattern` (String) All the commonly available replicator string template properties are available. The result must be 4 to 30 characters. Allowed characters are: lowercase and uppercase letters, numbers, hyphen, single-quote, double-quote, space, and exclamation point. When length restrictions are applied, the abbreviation will be in the middle and marked by a single-quote. - `service_account_config` (Attributes) Service account configuration. Either `serviceAccountCredentialsConfig` or `serviceAccountWorkloadIdentityConfig` must be provided. (see [below for nested schema](#nestedatt--spec--config--gcp--replication--service_account_config)) - `skip_user_group_permission_cleanup` (Boolean) For certain use cases you might want to preserve user groups and replicated permission after a tenant was deleted on the GCP platform. Checking this option preserves those permissions. Please keep in mind that the platform operator is then responsible for cleaning them up later. -- `tenant_tags` (Attributes) Tenant tags configuration (see [below for nested schema](#nestedatt--spec--config--gcp--replication--tenant_tags)) - `user_lookup_strategy` (String) Users can either be looked up by E-Mail or externalAccountId. This must also be the property that is placed in the external user id (EUID) of your meshUser entity to match. E-Mail is usually a good choice as this is often set up as the EUID throughout all cloud platforms and meshStack. ('email' or 'externalId') +Optional: + +- `tenant_tags` (Attributes) Tenant tags configuration (see [below for nested schema](#nestedatt--spec--config--gcp--replication--tenant_tags)) +- `used_external_id_type` (String) Used external ID type for user lookup + ### Nested Schema for `spec.config.gcp.replication.gcp_role_mappings` @@ -701,7 +886,7 @@ Optional: ### Nested Schema for `spec.config.gcp.replication.service_account_config.service_account_credentials_config` -Optional: +Required: - `service_account_credentials_b64` (String, Sensitive) Base64 encoded credentials.json file for a GCP ServiceAccount. The replicator uses this Service Account to automate GCP API operations (IAM, ResourceManager etc.). @@ -709,7 +894,7 @@ Optional: ### Nested Schema for `spec.config.gcp.replication.service_account_config.service_account_workload_identity_config` -Optional: +Required: - `audience` (String) The audience associated with your workload identity pool provider. - `service_account_email` (String) The email address of the Service Account, that gets impersonated for calling Google APIs via Workload Identity Federation. @@ -719,9 +904,12 @@ Optional: ### Nested Schema for `spec.config.gcp.replication.tenant_tags` -Optional: +Required: - `namespace_prefix` (String) Namespace prefix for tenant tags + +Optional: + - `tag_mappers` (Attributes List) List of tag mappers for tenant tags (see [below for nested schema](#nestedatt--spec--config--gcp--replication--tenant_tags--tag_mappers)) @@ -746,12 +934,39 @@ Required: Optional: - `disable_ssl_validation` (Boolean) Flag to disable SSL validation for the Kubernetes cluster. SSL Validation should at best never be disabled, but for integration of some private cloud platforms in an early state, they might not yet be using valid SSL certificates. In that case it can make sense to disable SSL validation here to already test integration of these platforms. +- `metering` (Attributes) Metering configuration for Kubernetes (optional, but required for metering) (see [below for nested schema](#nestedatt--spec--config--kubernetes--metering)) - `replication` (Attributes) Replication configuration for Kubernetes (optional, but required for replication) (see [below for nested schema](#nestedatt--spec--config--kubernetes--replication)) + +### Nested Schema for `spec.config.kubernetes.metering` + +Required: + +- `client_config` (Attributes) Client configuration for Kubernetes metering (see [below for nested schema](#nestedatt--spec--config--kubernetes--metering--client_config)) +- `processing` (Attributes) Processing configuration for metering (see [below for nested schema](#nestedatt--spec--config--kubernetes--metering--processing)) + + +### Nested Schema for `spec.config.kubernetes.metering.client_config` + +Required: + +- `access_token` (String, Sensitive) The Access Token of the service account for replicator access. + + + +### Nested Schema for `spec.config.kubernetes.metering.processing` + +Optional: + +- `compact_timelines_after_days` (Number) Number of days after which timelines should be compacted. +- `delete_raw_data_after_days` (Number) Number of days after which raw data should be deleted. + + + ### Nested Schema for `spec.config.kubernetes.replication` -Optional: +Required: - `client_config` (Attributes) Client configuration for Kubernetes (see [below for nested schema](#nestedatt--spec--config--kubernetes--replication--client_config)) - `namespace_name_pattern` (String) All the commonly available replicator string template properties are available. Kubernetes Namespace Names must be no longer than 63 characters, must start and end with a lowercase letter or number, and may contain lowercase letters, numbers, and hyphens. @@ -759,7 +974,7 @@ Optional: ### Nested Schema for `spec.config.kubernetes.replication.client_config` -Optional: +Required: - `access_token` (String, Sensitive) The Access Token of the service account for replicator access. @@ -776,25 +991,55 @@ Required: Optional: - `disable_ssl_validation` (Boolean) Flag to disable SSL validation for the OpenShift cluster. SSL Validation should at best never be disabled, but for integration of some private cloud platforms in an early state, they might not yet be using valid SSL certificates. In that case it can make sense to disable SSL validation here to already test integration of these platforms. +- `metering` (Attributes) Metering configuration for OpenShift (optional, but required for metering) (see [below for nested schema](#nestedatt--spec--config--openshift--metering)) - `replication` (Attributes) Replication configuration for OpenShift (optional, but required for replication) (see [below for nested schema](#nestedatt--spec--config--openshift--replication)) + +### Nested Schema for `spec.config.openshift.metering` + +Required: + +- `client_config` (Attributes) Client configuration for OpenShift metering (see [below for nested schema](#nestedatt--spec--config--openshift--metering--client_config)) +- `processing` (Attributes) Processing configuration for metering (see [below for nested schema](#nestedatt--spec--config--openshift--metering--processing)) + + +### Nested Schema for `spec.config.openshift.metering.client_config` + +Required: + +- `access_token` (String, Sensitive) The Access Token of the service account for replicator access. + + + +### Nested Schema for `spec.config.openshift.metering.processing` + +Optional: + +- `compact_timelines_after_days` (Number) Number of days after which timelines should be compacted. +- `delete_raw_data_after_days` (Number) Number of days after which raw data should be deleted. + + + ### Nested Schema for `spec.config.openshift.replication` -Optional: +Required: - `client_config` (Attributes) Client configuration for OpenShift (see [below for nested schema](#nestedatt--spec--config--openshift--replication--client_config)) - `enable_template_instantiation` (Boolean) Here you can enable templates not only being rolled out to OpenShift but also instantiated during replication. Templates can be configured in meshLandingZones. Please keep in mind that the replication service account needs all the rights that are required to apply the templates that are configured in meshLandingZones. - `identity_provider_name` (String) Identity provider name -- `openshift_role_mappings` (Attributes List) OpenShift role mappings for OpenShift roles. (see [below for nested schema](#nestedatt--spec--config--openshift--replication--openshift_role_mappings)) - `project_name_pattern` (String) All the commonly available replicator string template properties are available. OpenShift Project Names must be no longer than 63 characters, must start and end with a lowercase letter or number, and may contain lowercase letters, numbers, and hyphens. + +Optional: + +- `openshift_role_mappings` (Attributes List) OpenShift role mappings for OpenShift roles. (see [below for nested schema](#nestedatt--spec--config--openshift--replication--openshift_role_mappings)) - `tenant_tags` (Attributes) Tenant tags configuration (see [below for nested schema](#nestedatt--spec--config--openshift--replication--tenant_tags)) - `web_console_url` (String) The Web Console URL that is used to redirect the user to the cloud platform. An example Web Console URL is https://console-openshift-console.apps.okd4.dev.eu-de-central.msh.host ### Nested Schema for `spec.config.openshift.replication.client_config` -Optional: +Required: - `access_token` (String, Sensitive) The Access Token of the service account for replicator access. @@ -823,9 +1068,12 @@ Read-Only: ### Nested Schema for `spec.config.openshift.replication.tenant_tags` -Optional: +Required: - `namespace_prefix` (String) This is the prefix for all labels created by meshStack. It helps to keep track of which labels are managed by meshStack. It is recommended to let this prefix end with a delimiter like an underscore. + +Optional: + - `tag_mappers` (Attributes List) List of tag mappers for tenant tags (see [below for nested schema](#nestedatt--spec--config--openshift--replication--tenant_tags--tag_mappers)) diff --git a/internal/modifiers/platformtypemodifier/validate_single_platform.go b/internal/modifiers/platformtypemodifier/validate_single_platform.go index 6ae08bb..fb25ec4 100644 --- a/internal/modifiers/platformtypemodifier/validate_single_platform.go +++ b/internal/modifiers/platformtypemodifier/validate_single_platform.go @@ -44,8 +44,8 @@ func (v singlePlatformValidator) PlanModifyObject(ctx context.Context, req planm if len(configuredPlatforms) > 1 { resp.Diagnostics.AddError( "Multiple Platform Configurations", - fmt.Sprintf("Only one platform configuration can be specified within "+ - "platform_properties, but found: %v. Please specify only one platform "+ + fmt.Sprintf("Only one platform configuration can be specified,"+ + "but found: %v. Please specify only one platform "+ "configuration.", configuredPlatforms), ) } @@ -53,7 +53,7 @@ func (v singlePlatformValidator) PlanModifyObject(ctx context.Context, req planm if len(configuredPlatforms) == 0 { resp.Diagnostics.AddError( "No Platform Configuration", - "At least one platform configuration must be specified within platform_properties. "+ + "At least one platform configuration must be specified. "+ "Please specify one of: aws, aks, azure, azurerg, gcp, kubernetes, openshift.", ) } diff --git a/internal/provider/landingzone_resource.go b/internal/provider/landingzone_resource.go index 8b12ed4..9d8b9ee 100644 --- a/internal/provider/landingzone_resource.go +++ b/internal/provider/landingzone_resource.go @@ -225,7 +225,7 @@ func awsPlatformConfigSchema() schema.Attribute { Required: true, NestedObject: schema.NestedAttributeObject{ Attributes: map[string]schema.Attribute{ - "project_role_ref": meshProjectRoleAttribute(), + "project_role_ref": meshProjectRoleAttribute(false), "platform_role": schema.StringAttribute{ MarkdownDescription: "The AWS platform role", Required: true, @@ -254,7 +254,7 @@ func aksPlatformConfigSchema() schema.Attribute { Required: true, NestedObject: schema.NestedAttributeObject{ Attributes: map[string]schema.Attribute{ - "project_role_ref": meshProjectRoleAttribute(), + "project_role_ref": meshProjectRoleAttribute(false), "platform_roles": schema.ListAttribute{ MarkdownDescription: "List of AKS platform roles to assign to the meshProject role.", ElementType: types.StringType, @@ -284,7 +284,7 @@ func azurePlatformConfigSchema() schema.Attribute { Required: true, NestedObject: schema.NestedAttributeObject{ Attributes: map[string]schema.Attribute{ - "project_role_ref": meshProjectRoleAttribute(), + "project_role_ref": meshProjectRoleAttribute(false), "azure_group_suffix": schema.StringAttribute{ MarkdownDescription: "The given role name will be injected into the" + " group name via the group naming pattern configured on the" + @@ -336,7 +336,7 @@ func gcpPlatformConfigSchema() schema.Attribute { Required: true, NestedObject: schema.NestedAttributeObject{ Attributes: map[string]schema.Attribute{ - "project_role_ref": meshProjectRoleAttribute(), + "project_role_ref": meshProjectRoleAttribute(false), "platform_roles": schema.ListAttribute{ MarkdownDescription: "Can be empty. List of GCP IAM roles to assign to the meshProject role.", ElementType: types.StringType, @@ -367,7 +367,7 @@ func azureRgPlatformConfigSchema() schema.Attribute { Required: true, NestedObject: schema.NestedAttributeObject{ Attributes: map[string]schema.Attribute{ - "project_role_ref": meshProjectRoleAttribute(), + "project_role_ref": meshProjectRoleAttribute(false), "azure_group_suffix": schema.StringAttribute{ MarkdownDescription: "The given role name will be injected into the" + " group name via the group naming pattern configured on the" + @@ -410,7 +410,7 @@ func kubernetesPlatformConfigSchema() schema.Attribute { Required: true, NestedObject: schema.NestedAttributeObject{ Attributes: map[string]schema.Attribute{ - "project_role_ref": meshProjectRoleAttribute(), + "project_role_ref": meshProjectRoleAttribute(false), "platform_roles": schema.ListAttribute{ MarkdownDescription: "Roles need to be mapped from the meshRole to" + " the Cluster Role. You can use both built in roles like 'editor' or custom roles that you setup in the Kubernetes Cluster" + diff --git a/internal/provider/platform_data_source.go b/internal/provider/platform_data_source.go index 12df4cd..c28f865 100644 --- a/internal/provider/platform_data_source.go +++ b/internal/provider/platform_data_source.go @@ -167,7 +167,7 @@ func (d *platformDataSource) Schema(_ context.Context, _ datasource.SchemaReques }, "quota_definitions": schema.ListAttribute{ MarkdownDescription: "List of quota definitions for the platform.", - Required: true, + Computed: true, Sensitive: false, ElementType: types.ObjectType{ AttrTypes: map[string]attr.Type{ @@ -214,6 +214,7 @@ func awsPlatformDataSourceSchema() schema.Attribute { Computed: true, }, "replication": awsReplicationConfigDataSourceSchema(), + "metering": awsMeteringConfigDataSourceSchema(), }, } } @@ -232,6 +233,7 @@ func aksPlatformDataSourceSchema() schema.Attribute { Computed: true, }, "replication": aksReplicationConfigDataSourceSchema(), + "metering": aksMeteringConfigDataSourceSchema(), }, } } @@ -246,6 +248,7 @@ func azurePlatformDataSourceSchema() schema.Attribute { Computed: true, }, "replication": azureReplicationConfigDataSourceSchema(), + "metering": azureMeteringConfigDataSourceSchema(), }, } } @@ -270,6 +273,7 @@ func gcpPlatformDataSourceSchema() schema.Attribute { Computed: true, Attributes: map[string]schema.Attribute{ "replication": gcpReplicationConfigDataSourceSchema(), + "metering": gcpMeteringConfigDataSourceSchema(), }, } } @@ -288,6 +292,7 @@ func kubernetesPlatformDataSourceSchema() schema.Attribute { Computed: true, }, "replication": kubernetesReplicationConfigDataSourceSchema(), + "metering": kubernetesMeteringConfigDataSourceSchema(), }, } } @@ -306,11 +311,176 @@ func openShiftPlatformDataSourceSchema() schema.Attribute { Computed: true, }, "replication": openShiftReplicationConfigDataSourceSchema(), + "metering": openShiftMeteringConfigDataSourceSchema(), }, } } -// TODO review done until here +func aksMeteringConfigDataSourceSchema() schema.Attribute { + return schema.SingleNestedAttribute{ + MarkdownDescription: "Metering configuration for AKS (optional, but required for metering)", + Computed: true, + Attributes: map[string]schema.Attribute{ + "client_config": kubernetesClientConfigDataSourceSchema("Client configuration for AKS metering"), + "processing": meteringProcessingConfigDataSourceSchema(), + }, + } +} + +func awsMeteringConfigDataSourceSchema() schema.Attribute { + return schema.SingleNestedAttribute{ + MarkdownDescription: "Metering configuration for AWS (optional, but required for metering)", + Computed: true, + Attributes: map[string]schema.Attribute{ + "access_config": schema.SingleNestedAttribute{ + MarkdownDescription: "Access configuration for AWS metering", + Computed: true, + Attributes: map[string]schema.Attribute{ + "organization_root_account_role": schema.StringAttribute{ + MarkdownDescription: "ARN of the Management Account Role", + Computed: true, + }, + "organization_root_account_external_id": schema.StringAttribute{ + MarkdownDescription: "ExternalId for the organization root account role", + Computed: true, + }, + "service_user_config": schema.SingleNestedAttribute{ + MarkdownDescription: "Service user configuration", + Computed: true, + Attributes: map[string]schema.Attribute{ + "access_key": schema.StringAttribute{ + MarkdownDescription: "AWS access key", + Computed: true, + }, + "secret_key": schema.StringAttribute{ + MarkdownDescription: "AWS secret key", + Computed: true, + Sensitive: true, + }, + }, + }, + "workload_identity_config": schema.SingleNestedAttribute{ + MarkdownDescription: "Workload identity configuration", + Computed: true, + Attributes: map[string]schema.Attribute{ + "role_arn": schema.StringAttribute{ + MarkdownDescription: "ARN of the role for workload identity", + Computed: true, + }, + }, + }, + }, + }, + "filter": schema.StringAttribute{ + MarkdownDescription: "Cost Explorer filter type (NONE or EXCLUDE_TAX)", + Computed: true, + }, + "reserved_instance_fair_chargeback": schema.BoolAttribute{ + MarkdownDescription: "Enable fair chargeback for reserved instances", + Computed: true, + }, + "savings_plan_fair_chargeback": schema.BoolAttribute{ + MarkdownDescription: "Enable fair chargeback for savings plans", + Computed: true, + }, + "processing": meteringProcessingConfigDataSourceSchema(), + }, + } +} + +func azureMeteringConfigDataSourceSchema() schema.Attribute { + return schema.SingleNestedAttribute{ + MarkdownDescription: "Metering configuration for Azure (optional, but required for metering)", + Computed: true, + Attributes: map[string]schema.Attribute{ + "service_principal": schema.SingleNestedAttribute{ + MarkdownDescription: "Service principal configuration for Azure metering", + Computed: true, + Attributes: map[string]schema.Attribute{ + "client_id": schema.StringAttribute{ + MarkdownDescription: "The Application (Client) ID", + Computed: true, + }, + "auth_type": schema.StringAttribute{ + MarkdownDescription: "Authentication type (CREDENTIALS or WORKLOAD_IDENTITY)", + Computed: true, + }, + "credentials_auth_client_secret": schema.StringAttribute{ + MarkdownDescription: "Client secret (if authType is CREDENTIALS)", + Computed: true, + Sensitive: true, + }, + "object_id": schema.StringAttribute{ + MarkdownDescription: "The Object ID of the Enterprise Application", + Computed: true, + }, + }, + }, + "processing": meteringProcessingConfigDataSourceSchema(), + }, + } +} + +func gcpMeteringConfigDataSourceSchema() schema.Attribute { + return schema.SingleNestedAttribute{ + MarkdownDescription: "Metering configuration for GCP (optional, but required for metering)", + Computed: true, + Attributes: map[string]schema.Attribute{ + "service_account_config": schema.SingleNestedAttribute{ + MarkdownDescription: "Service account configuration for GCP metering", + Computed: true, + Attributes: map[string]schema.Attribute{ + "service_account_credentials_config": schema.SingleNestedAttribute{ + MarkdownDescription: "Service account credentials configuration", + Computed: true, + Attributes: map[string]schema.Attribute{ + "service_account_credentials_b64": schema.StringAttribute{ + MarkdownDescription: "Base64 encoded service account credentials", + Computed: true, + Sensitive: true, + }, + }, + }, + "service_account_workload_identity_config": schema.SingleNestedAttribute{ + MarkdownDescription: "Service account workload identity configuration", + Computed: true, + Attributes: map[string]schema.Attribute{ + "audience": schema.StringAttribute{ + MarkdownDescription: "The audience for workload identity", + Computed: true, + }, + "service_account_email": schema.StringAttribute{ + MarkdownDescription: "Service account email address", + Computed: true, + }, + }, + }, + }, + }, + "bigquery_table": schema.StringAttribute{ + MarkdownDescription: "BigQuery table for metering data", + Computed: true, + }, + "bigquery_table_for_carbon_footprint": schema.StringAttribute{ + MarkdownDescription: "BigQuery table for carbon footprint data", + Computed: true, + }, + "carbon_footprint_data_collection_start_month": schema.StringAttribute{ + MarkdownDescription: "Start month for carbon footprint data collection", + Computed: true, + }, + "partition_time_column": schema.StringAttribute{ + MarkdownDescription: "Partition time column name", + Computed: true, + }, + "additional_filter": schema.StringAttribute{ + MarkdownDescription: "Additional filter for metering queries", + Computed: true, + }, + "processing": meteringProcessingConfigDataSourceSchema(), + }, + } +} func aksReplicationConfigDataSourceSchema() schema.Attribute { return schema.SingleNestedAttribute{ @@ -509,7 +679,7 @@ func awsReplicationConfigDataSourceSchema() schema.Attribute { Computed: true, NestedObject: schema.NestedAttributeObject{ Attributes: map[string]schema.Attribute{ - "project_role_ref": meshProjectRoleAttribute(), + "project_role_ref": meshProjectRoleAttribute(true), "aws_role": schema.StringAttribute{ MarkdownDescription: "The AWS role name", Computed: true, @@ -517,7 +687,7 @@ func awsReplicationConfigDataSourceSchema() schema.Attribute { "permission_set_arns": schema.ListAttribute{ MarkdownDescription: "List of permission set ARNs associated with this role mapping", ElementType: types.StringType, - Optional: true, + Computed: true, }, }, }, @@ -673,8 +843,7 @@ func azureReplicationConfigDataSourceSchema() schema.Attribute { Computed: true, Attributes: map[string]schema.Attribute{ "redirect_url": schema.StringAttribute{ - MarkdownDescription: "This is the URL that Azure's consent experience redirects users to after they accept their invitation.", - Computed: true, + Computed: true, }, "send_azure_invitation_mail": schema.BoolAttribute{ MarkdownDescription: "When true, meshStack instructs Azure to send out Invitation mails to invited users. These mails allow users to redeem their invitation to the AAD tenant only using email and Azure Portal.", @@ -703,7 +872,7 @@ func azureReplicationConfigDataSourceSchema() schema.Attribute { Computed: true, NestedObject: schema.NestedAttributeObject{ Attributes: map[string]schema.Attribute{ - "project_role_ref": meshProjectRoleAttribute(), + "project_role_ref": meshProjectRoleAttribute(true), "azure_role": schema.SingleNestedAttribute{ MarkdownDescription: "The Azure role definition.", Computed: true, @@ -767,8 +936,6 @@ func azureReplicationConfigDataSourceSchema() schema.Attribute { } } -// TODO continue here. - func azureRgReplicationConfigDataSourceSchema() schema.Attribute { return schema.SingleNestedAttribute{ MarkdownDescription: "Azure Resource Group-specific replication configuration for the platform.", @@ -932,12 +1099,16 @@ func gcpReplicationConfigDataSourceSchema() schema.Attribute { MarkdownDescription: "Users can either be looked up by E-Mail or externalAccountId. This must also be the property that is placed in the external user id (EUID) of your meshUser entity to match. E-Mail is usually a good choice as this is often set up as the EUID throughout all cloud platforms and meshStack. ('email' or 'externalId')", Computed: true, }, + "used_external_id_type": schema.StringAttribute{ + MarkdownDescription: "The type of external ID used for user lookup.", + Computed: true, + }, "gcp_role_mappings": schema.ListNestedAttribute{ MarkdownDescription: "Mapping of platform roles to GCP IAM roles.", Computed: true, NestedObject: schema.NestedAttributeObject{ Attributes: map[string]schema.Attribute{ - "project_role_ref": meshProjectRoleAttribute(), + "project_role_ref": meshProjectRoleAttribute(true), "gcp_role": schema.StringAttribute{ MarkdownDescription: "The GCP IAM role", Computed: true, @@ -983,22 +1154,43 @@ func gcpReplicationConfigDataSourceSchema() schema.Attribute { } } -func kubernetesReplicationConfigDataSourceSchema() schema.Attribute { +func kubernetesClientConfigDataSourceSchema(description string) schema.Attribute { return schema.SingleNestedAttribute{ - MarkdownDescription: "Replication configuration for Kubernetes (optional, but required for replication)", + MarkdownDescription: description, Computed: true, Attributes: map[string]schema.Attribute{ - "client_config": schema.SingleNestedAttribute{ - MarkdownDescription: "Client configuration for Kubernetes", + "access_token": schema.StringAttribute{ + MarkdownDescription: "The Access Token of the service account for replicator access.", + Computed: true, + Sensitive: true, + }, + }, + } +} + +func meteringProcessingConfigDataSourceSchema() schema.Attribute { + return schema.SingleNestedAttribute{ + MarkdownDescription: "Processing configuration for metering", + Computed: true, + Attributes: map[string]schema.Attribute{ + "compact_timelines_after_days": schema.Int64Attribute{ + MarkdownDescription: "Number of days after which timelines should be compacted.", + Computed: true, + }, + "delete_raw_data_after_days": schema.Int64Attribute{ + MarkdownDescription: "Number of days after which raw data should be deleted.", Computed: true, - Attributes: map[string]schema.Attribute{ - "access_token": schema.StringAttribute{ - MarkdownDescription: "The Access Token of the service account for replicator access.", - Computed: true, - Sensitive: true, - }, - }, }, + }, + } +} + +func kubernetesReplicationConfigDataSourceSchema() schema.Attribute { + return schema.SingleNestedAttribute{ + MarkdownDescription: "Replication configuration for Kubernetes (optional, but required for replication)", + Computed: true, + Attributes: map[string]schema.Attribute{ + "client_config": kubernetesClientConfigDataSourceSchema("Client configuration for Kubernetes"), "namespace_name_pattern": schema.StringAttribute{ MarkdownDescription: "All the commonly available replicator string template properties are available. Kubernetes Namespace Names must be no longer than 63 characters, must start and end with a lowercase letter or number, and may contain lowercase letters, numbers, and hyphens.", Computed: true, @@ -1007,24 +1199,22 @@ func kubernetesReplicationConfigDataSourceSchema() schema.Attribute { } } -// TODO continue here. +func kubernetesMeteringConfigDataSourceSchema() schema.Attribute { + return schema.SingleNestedAttribute{ + MarkdownDescription: "Metering configuration for Kubernetes (optional, but required for metering)", + Computed: true, + Attributes: map[string]schema.Attribute{ + "client_config": kubernetesClientConfigDataSourceSchema("Client configuration for Kubernetes metering"), + }, + } +} func openShiftReplicationConfigDataSourceSchema() schema.Attribute { return schema.SingleNestedAttribute{ MarkdownDescription: "Replication configuration for OpenShift (optional, but required for replication)", Computed: true, Attributes: map[string]schema.Attribute{ - "client_config": schema.SingleNestedAttribute{ - MarkdownDescription: "Client configuration for OpenShift", - Computed: true, - Attributes: map[string]schema.Attribute{ - "access_token": schema.StringAttribute{ - MarkdownDescription: "The Access Token of the service account for replicator access.", - Computed: true, - Sensitive: true, - }, - }, - }, + "client_config": kubernetesClientConfigDataSourceSchema("Client configuration for OpenShift"), "web_console_url": schema.StringAttribute{ MarkdownDescription: "The Web Console URL that is used to redirect the user to the cloud platform. An example Web Console URL is https://console-openshift-console.apps.okd4.dev.eu-de-central.msh.host", Computed: true, @@ -1042,7 +1232,7 @@ func openShiftReplicationConfigDataSourceSchema() schema.Attribute { Computed: true, NestedObject: schema.NestedAttributeObject{ Attributes: map[string]schema.Attribute{ - "project_role_ref": meshProjectRoleAttribute(), + "project_role_ref": meshProjectRoleAttribute(true), "openshift_role": schema.StringAttribute{ MarkdownDescription: "The OpenShift role name", Computed: true, @@ -1084,6 +1274,17 @@ func openShiftReplicationConfigDataSourceSchema() schema.Attribute { } } +func openShiftMeteringConfigDataSourceSchema() schema.Attribute { + return schema.SingleNestedAttribute{ + MarkdownDescription: "Metering configuration for OpenShift (optional, but required for metering)", + Computed: true, + Attributes: map[string]schema.Attribute{ + "client_config": kubernetesClientConfigDataSourceSchema("Client configuration for OpenShift metering"), + "processing": meteringProcessingConfigDataSourceSchema(), + }, + } +} + func (d *platformDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) { var uuid string diff --git a/internal/provider/platform_resource.go b/internal/provider/platform_resource.go index 089e905..872e00d 100644 --- a/internal/provider/platform_resource.go +++ b/internal/provider/platform_resource.go @@ -13,7 +13,7 @@ import ( "github.com/hashicorp/terraform-plugin-framework/path" "github.com/hashicorp/terraform-plugin-framework/resource" "github.com/hashicorp/terraform-plugin-framework/resource/schema" - "github.com/hashicorp/terraform-plugin-framework/resource/schema/booldefault" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/int64default" "github.com/hashicorp/terraform-plugin-framework/resource/schema/listdefault" "github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier" "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringdefault" @@ -70,6 +70,16 @@ func (r *platformResource) Schema(_ context.Context, _ resource.SchemaRequest, r "* Deleting and re-creating a platform with the same identifier is not possible. Once you have used a platform identifier, you cannot use it again, even if the platform has been deleted. You may run into this issue when you attempt to modify an immutable attribute and terraform therefore attempts to replace (i.e., delete and recreate) the entire platform, which will result in an error with a status code of `409` due to the identifier already being used by a deleted platform.\n" + "* Changing the owning workspace of a platform (`metadata.owned_by_workspace`) is not possible. To transfer the ownership of a platform, you must use meshPanel." + quotaDefinitionAttrTypes := map[string]attr.Type{ + "quota_key": types.StringType, + "label": types.StringType, + "description": types.StringType, + "unit": types.StringType, + "min_value": types.Int64Type, + "max_value": types.Int64Type, + "auto_approval_threshold": types.Int64Type, + } + resp.Schema = schema.Schema{ MarkdownDescription: markdownDescription, Attributes: map[string]schema.Attribute{ @@ -214,19 +224,15 @@ func (r *platformResource) Schema(_ context.Context, _ resource.SchemaRequest, r }, "quota_definitions": schema.ListAttribute{ MarkdownDescription: "List of quota definitions for the platform.", - Required: true, + Optional: true, + Computed: true, Sensitive: false, ElementType: types.ObjectType{ - AttrTypes: map[string]attr.Type{ - "quota_key": types.StringType, - "label": types.StringType, - "description": types.StringType, - "unit": types.StringType, - "min_value": types.Int64Type, - "max_value": types.Int64Type, - "auto_approval_threshold": types.Int64Type, - }, + AttrTypes: quotaDefinitionAttrTypes, }, + Default: listdefault.StaticValue(types.ListValueMust(types.ObjectType{ + AttrTypes: quotaDefinitionAttrTypes, + }, []attr.Value{})), }, "config": schema.SingleNestedAttribute{ MarkdownDescription: "Platform-specific configuration settings.", @@ -259,888 +265,22 @@ func (r *platformResource) Schema(_ context.Context, _ resource.SchemaRequest, r } } -func awsPlatformSchema() schema.Attribute { +func meteringProcessingConfigSchema() schema.Attribute { return schema.SingleNestedAttribute{ - MarkdownDescription: "Configuration for AWS", - Optional: true, + MarkdownDescription: "Processing configuration for metering", + Required: true, Attributes: map[string]schema.Attribute{ - "region": schema.StringAttribute{ - MarkdownDescription: "AWS region", - Optional: true, - }, - "replication": awsReplicationConfigSchema(), - }, - } -} - -func aksPlatformSchema() schema.Attribute { - return schema.SingleNestedAttribute{ - MarkdownDescription: "Azure Kubernetes Service configuration", - Optional: true, - Attributes: map[string]schema.Attribute{ - "base_url": schema.StringAttribute{ - MarkdownDescription: "Base URL of the AKS cluster", - Required: true, - }, - "disable_ssl_validation": schema.BoolAttribute{ - MarkdownDescription: "Flag to disable SSL validation for the AKS cluster. (SSL Validation should at best never be disabled, but for integration of some private cloud platforms in an early state, they might not yet be using valid SSL certificates. In that case it can make sense to disable SSL validation here to already test integration of these platforms.)", - Optional: true, + "compact_timelines_after_days": schema.Int64Attribute{ + MarkdownDescription: "Number of days after which timelines should be compacted.", Computed: true, - Default: booldefault.StaticBool(false), - }, - "replication": aksReplicationConfigSchema(), - }, - } -} - -func azurePlatformSchema() schema.Attribute { - return schema.SingleNestedAttribute{ - MarkdownDescription: "Azure platform configuration.", - Optional: true, - Attributes: map[string]schema.Attribute{ - "entra_tenant": schema.StringAttribute{ - MarkdownDescription: "Azure Active Directory (Entra ID) tenant", Optional: true, + Default: int64default.StaticInt64(30), }, - "replication": azureReplicationConfigSchema(), - }, - } -} - -func azureRgPlatformSchema() schema.Attribute { - return schema.SingleNestedAttribute{ - MarkdownDescription: "Azure Resource Group platform configuration.", - Optional: true, - Attributes: map[string]schema.Attribute{ - "entra_tenant": schema.StringAttribute{ - MarkdownDescription: "Azure Active Directory (Entra ID) tenant", - Optional: true, - }, - "replication": azureRgReplicationConfigSchema(), - }, - } -} - -func gcpPlatformSchema() schema.Attribute { - return schema.SingleNestedAttribute{ - MarkdownDescription: "Google Cloud Platform (GCP) platform configuration.", - Optional: true, - Attributes: map[string]schema.Attribute{ - "replication": gcpReplicationConfigSchema(), - }, - } -} - -func kubernetesPlatformSchema() schema.Attribute { - return schema.SingleNestedAttribute{ - MarkdownDescription: "Kubernetes platform configuration.", - Optional: true, - Attributes: map[string]schema.Attribute{ - "base_url": schema.StringAttribute{ - MarkdownDescription: "This URL is the base URL to your Kubernetes Cluster, which is used to call the APIs to create new Kubernetes projects, get raw data for metering the Kubernetes projects, etc. An example base URL is: https://k8s.dev.eu-de-central.msh.host:6443", - Required: true, - }, - "disable_ssl_validation": schema.BoolAttribute{ - MarkdownDescription: "Flag to disable SSL validation for the Kubernetes cluster. SSL Validation should at best never be disabled, but for integration of some private cloud platforms in an early state, they might not yet be using valid SSL certificates. In that case it can make sense to disable SSL validation here to already test integration of these platforms.", - Optional: true, - Computed: true, - Default: booldefault.StaticBool(false), - }, - "replication": kubernetesReplicationConfigSchema(), - }, - } -} - -func openShiftPlatformSchema() schema.Attribute { - return schema.SingleNestedAttribute{ - MarkdownDescription: "OpenShift platform configuration.", - Optional: true, - Attributes: map[string]schema.Attribute{ - "base_url": schema.StringAttribute{ - MarkdownDescription: "This URL is the base URL to your OpenShift Cluster, which is used to call the APIs to create new OpenShift projects, get raw data for metering the OpenShift projects, etc. An example base URL is: https://api.okd4.dev.eu-de-central.msh.host:6443", - Required: true, - }, - "disable_ssl_validation": schema.BoolAttribute{ - MarkdownDescription: "Flag to disable SSL validation for the OpenShift cluster. SSL Validation should at best never be disabled, but for integration of some private cloud platforms in an early state, they might not yet be using valid SSL certificates. In that case it can make sense to disable SSL validation here to already test integration of these platforms.", - Optional: true, + "delete_raw_data_after_days": schema.Int64Attribute{ + MarkdownDescription: "Number of days after which raw data should be deleted.", Computed: true, - Default: booldefault.StaticBool(false), - }, - "replication": openShiftReplicationConfigSchema(), - }, - } -} - -func aksReplicationConfigSchema() schema.Attribute { - return schema.SingleNestedAttribute{ - MarkdownDescription: "Replication configuration for AKS (optional, but required for replication)", - Optional: true, - Attributes: map[string]schema.Attribute{ - "access_token": schema.StringAttribute{ - MarkdownDescription: "The Access Token of the service account for replicator access.", - Optional: true, - Sensitive: true, - }, - "namespace_name_pattern": schema.StringAttribute{ - MarkdownDescription: "Pattern for naming namespaces in AKS", - Optional: true, - }, - "group_name_pattern": schema.StringAttribute{ - MarkdownDescription: "Pattern for naming groups in AKS", - Optional: true, - }, - "service_principal": schema.SingleNestedAttribute{ - MarkdownDescription: "Service principal configuration for AKS", - Optional: true, - Attributes: map[string]schema.Attribute{ - "client_id": schema.StringAttribute{ - MarkdownDescription: "The Application (Client) ID. In Azure Portal, this is the Application ID of the 'Enterprise Application' but can also be retrieved via the 'App Registration' object as 'Application (Client) ID'.", - Required: true, - }, - "auth_type": schema.StringAttribute{ - MarkdownDescription: "Authentication type for the service principal (`CREDENTIALS` or `WORKLOAD_IDENTITY`)", - Required: true, - }, - "credentials_auth_client_secret": schema.StringAttribute{ - MarkdownDescription: "Client secret for the service principal (if `authType` is `CREDENTIALS`)", - Optional: true, - Sensitive: true, - }, - "entra_tenant": schema.StringAttribute{ - MarkdownDescription: "Domain name or ID of the Entra Tenant that holds the Service Principal.", - Required: true, - }, - "object_id": schema.StringAttribute{ - MarkdownDescription: "The Object ID of the Enterprise Application. You can get this Object ID via the API (e.g. when using our Terraform provider) or from Enterprise applications pane in Microsoft Entra admin center.", - Required: true, - }, - }, - }, - "aks_subscription_id": schema.StringAttribute{ - MarkdownDescription: "Subscription ID for the AKS cluster", - Optional: true, - }, - "aks_cluster_name": schema.StringAttribute{ - MarkdownDescription: "Name of the AKS cluster.", - Optional: true, - }, - "aks_resource_group": schema.StringAttribute{ - MarkdownDescription: "Resource group for the AKS cluster", - Optional: true, - }, - "redirect_url": schema.StringAttribute{ - MarkdownDescription: "This is the URL that Azure’s consent experience redirects users to after they accept their invitation.", - Optional: true, - }, - "send_azure_invitation_mail": schema.BoolAttribute{ - MarkdownDescription: "Flag to send Azure invitation emails. When true, meshStack instructs Azure to send out Invitation mails to invited users.", - Optional: true, - }, - "user_look_up_strategy": schema.StringAttribute{ - MarkdownDescription: "Strategy for user lookup in Azure (`userPrincipalName` or `email`)", - Optional: true, - }, - "administrative_unit_id": schema.StringAttribute{ - MarkdownDescription: "If you enter an administrative unit ID the replicated (and potentially existing) groups will be put into this AU. This can be used to limit the permission scopes which are required for the replicator principal. If you remove the AU ID again or change it, the groups will not be removed from the old AU.", - Optional: true, - }, - }, - } -} - -func awsReplicationConfigSchema() schema.Attribute { - return schema.SingleNestedAttribute{ - MarkdownDescription: "Replication configuration for AWS (optional, but required for replication)", - Optional: true, - Attributes: map[string]schema.Attribute{ - "access_config": schema.SingleNestedAttribute{ - MarkdownDescription: "meshStack currently supports 2 types of authentication. Workload Identity Federation (using OIDC) is the one that we recommend as it enables secure access to your AWS account without using long lived credentials. Alternatively, you can use credential based authentication by providing access and secret keys. Either the `service_user_config` or `workload_identity_config` must be provided.", - Optional: true, - Attributes: map[string]schema.Attribute{ - "organization_root_account_role": schema.StringAttribute{ - MarkdownDescription: "ARN of the Management Account Role. The Management Account contains your AWS organization. E.g. `arn:aws:iam::123456789:role/MeshfedServiceRole`.", - Required: true, - }, - "organization_root_account_external_id": schema.StringAttribute{ - MarkdownDescription: "ExternalId to enhance security in a multi account setup when assuming the organization root account role.", - Optional: true, - }, - "service_user_config": schema.SingleNestedAttribute{ - MarkdownDescription: "Service user configuration (alternative to `workload_identity_config`)", - Optional: true, - Attributes: map[string]schema.Attribute{ - "access_key": schema.StringAttribute{ - MarkdownDescription: "AWS access key for service user", - Required: true, - }, - "secret_key": schema.StringAttribute{ - MarkdownDescription: "AWS secret key for service user", - Optional: true, - Sensitive: true, - }, - }, - }, - "workload_identity_config": schema.SingleNestedAttribute{ - MarkdownDescription: "Workload identity configuration (alternative to `service_user_config`)", - Optional: true, - Attributes: map[string]schema.Attribute{ - "role_arn": schema.StringAttribute{ - MarkdownDescription: "ARN of the role that should be used as the entry point for meshStack by assuming it via web identity.", - Required: true, - }, - }, - }, - }, - }, - "wait_for_external_avm": schema.BoolAttribute{ - MarkdownDescription: "Flag to wait for external AVM. Please use this setting with care! It is currently very specific to certain tags being present on the account! In general, we recommend not to activate this functionality! In a meshLandingZone an AVM can be triggered via an AWS StackSet or via a Lambda Function. If meshStack shall wait for the AVM to complete when creating a new platform tenant, this flag must be checked. meshStack will identify completion of the AVM by checking the presence of the following tags on the AWS account: 'ProductName' is set to workspace identifier and 'Stage' is set to project identifier.", - Optional: true, - }, - "automation_account_role": schema.StringAttribute{ - MarkdownDescription: "ARN of the Automation Account Role. The Automation Account contains all AWS StackSets and Lambda Functions that shall be executed via meshLandingZones. E.g. `arn:aws:iam::123456789:role/MeshfedAutomationRole`.", - Optional: true, - }, - "automation_account_external_id": schema.StringAttribute{ - MarkdownDescription: "ExternalId to enhance security in a multi account setup when assuming the automation account role.", - Optional: true, - }, - "account_access_role": schema.StringAttribute{ - MarkdownDescription: "The name for the Account Access Role that will be rolled out to all managed accounts. Only a name, not an ARN must be set here, as the ARN must be built dynamically for every managed AWS Account. The replicator service user needs to assume this role in all accounts to manage them.", - Optional: true, - }, - "account_alias_pattern": schema.StringAttribute{ - MarkdownDescription: "With a String Pattern you can define how the account alias of the created AWS account will be named. E.g. `#{workspaceIdentifier}-#{projectIdentifier}`. Attention: Account Alias must be globally unique in AWS. So consider defining a unique prefix.", - Optional: true, - }, - "enforce_account_alias": schema.BoolAttribute{ - MarkdownDescription: "Flag to enforce account alias. If set, meshStack will guarantee on every replication that the configured Account Alias is applied. Otherwise it will only set the Account Alias once during tenant creation.", - Optional: true, - }, - "account_email_pattern": schema.StringAttribute{ - MarkdownDescription: "With a String Pattern you can define how the account email address of the created AWS account will be set. E.g. `aws+#{workspaceIdentifier}.#{projectIdentifier}@yourcompany.com`. Please consider that this email address is limited to 64 characters! Also have a look at our docs for more information.", - Optional: true, - }, - "tenant_tags": schema.SingleNestedAttribute{ - MarkdownDescription: "Tenant tags configuration", - Optional: true, - Attributes: map[string]schema.Attribute{ - "namespace_prefix": schema.StringAttribute{ - MarkdownDescription: "Namespace prefix for tenant tags", - Required: true, - }, - "tag_mappers": schema.ListNestedAttribute{ - MarkdownDescription: "List of tag mappers for tenant tags", - Optional: true, - NestedObject: schema.NestedAttributeObject{ - Attributes: map[string]schema.Attribute{ - "key": schema.StringAttribute{ - MarkdownDescription: "Key for the tag mapper", - Required: true, - }, - "value_pattern": schema.StringAttribute{ - MarkdownDescription: "Value pattern for the tag mapper", - Required: true, - }, - }, - }, - }, - }, - }, - "aws_sso": schema.SingleNestedAttribute{ - MarkdownDescription: "AWS SSO configuration", - Optional: true, - Attributes: map[string]schema.Attribute{ - "scim_endpoint": schema.StringAttribute{ - MarkdownDescription: "The SCIM endpoint you can find in your AWS IAM Identity Center Automatic provisioning config.", - Required: true, - }, - "arn": schema.StringAttribute{ - MarkdownDescription: "The ARN of your AWS IAM Identity Center Instance. E.g. `arn:aws:sso:::instance/ssoins-123456789abc`.", - Required: true, - }, - "group_name_pattern": schema.StringAttribute{ - MarkdownDescription: "Configures the pattern that defines the desired name of AWS IAM Identity Center groups managed by meshStack. It follows the usual replicator string pattern features and provides the additional replacement 'platformGroupAlias', which contains the role name suffix, which is configurable via Role Mappings in this platform config or via a meshLandingZone. Operators must ensure the group names will be unique within the same AWS IAM Identity Center Instance with that configuration. meshStack will additionally prefix the group name with 'mst-' to be able to identify the groups that are managed by meshStack.", - Required: true, - }, - "sso_access_token": schema.StringAttribute{ - MarkdownDescription: "The AWS IAM Identity Center SCIM Access Token that was generated via the Automatic provisioning config in AWS IAM Identity Center.", - Optional: true, - Sensitive: true, - }, - "aws_role_mappings": schema.ListNestedAttribute{ - MarkdownDescription: "AWS role mappings for AWS SSO", - Optional: true, - NestedObject: schema.NestedAttributeObject{ - Attributes: map[string]schema.Attribute{ - "project_role_ref": meshProjectRoleAttribute(), - "aws_role": schema.StringAttribute{ - MarkdownDescription: "The AWS role name", - Required: true, - }, - "permission_set_arns": schema.ListAttribute{ - MarkdownDescription: "List of permission set ARNs associated with this role mapping", - ElementType: types.StringType, - Optional: true, - }, - }, - }, - }, - "sign_in_url": schema.StringAttribute{ - MarkdownDescription: "The AWS IAM Identity Center sign in Url, that must be used by end-users to log in via AWS IAM Identity Center to AWS Management Console.", - Optional: true, - }, - }, - }, - "enrollment_configuration": schema.SingleNestedAttribute{ - MarkdownDescription: "AWS account enrollment configuration.", - Optional: true, - Attributes: map[string]schema.Attribute{ - "management_account_id": schema.StringAttribute{ - MarkdownDescription: "The Account ID of the management account configured for the platform instance.", - Required: true, - }, - "account_factory_product_id": schema.StringAttribute{ - MarkdownDescription: "The Product ID of the AWS Account Factory Product in AWS Service Catalog that should be used for enrollment. Starts with `prod-`.", - Required: true, - }, - }, - }, - "self_downgrade_access_role": schema.BoolAttribute{ - MarkdownDescription: "Flag for self downgrade access role. If set, meshStack will revoke its rights on the managed account that were only needed for initial account creation.", - Optional: true, - }, - "skip_user_group_permission_cleanup": schema.BoolAttribute{ - MarkdownDescription: "Flag to skip user group permission cleanup. For certain use cases you might want to preserve user groups and replicated permission after a tenant was deleted on the AWS platform. Checking this option preserves those permissions. Please keep in mind that the platform operator is then responsible for cleaning them up later.", - Optional: true, - }, - "allow_hierarchical_organizational_unit_assignment": schema.BoolAttribute{ - MarkdownDescription: "Configuration flag to enable or disable hierarchical organizational unit assignment in AWS. If set to true: Accounts can be moved to child organizational units of the organizational unit defined in the Landing Zone. This is useful if you want to manage the account location with a deeper and more granular hierarchy. If set to false: Accounts will always be moved directly to the organizational unit defined in the Landing Zone.", Optional: true, - }, - }, - } -} - -func azureReplicationConfigSchema() schema.Attribute { - return schema.SingleNestedAttribute{ - MarkdownDescription: "Azure-specific replication configuration for the platform.", - Optional: true, - Attributes: map[string]schema.Attribute{ - "service_principal": schema.SingleNestedAttribute{ - MarkdownDescription: "Service principal configuration for Azure", - Optional: true, - Attributes: map[string]schema.Attribute{ - "client_id": schema.StringAttribute{ - MarkdownDescription: "The Application (Client) ID. In Azure Portal, this is the Application ID of the 'Enterprise Application' but can also be retrieved via the 'App Registration' object as 'Application (Client) ID", - Required: true, - }, - "auth_type": schema.StringAttribute{ - MarkdownDescription: "Authentication type (`CREDENTIALS` or `WORKLOAD_IDENTITY`)", - Required: true, - }, - "credentials_auth_client_secret": schema.StringAttribute{ - MarkdownDescription: "Client secret (if authType is `CREDENTIALS`)", - Optional: true, - Sensitive: true, - }, - "object_id": schema.StringAttribute{ - MarkdownDescription: "The Object ID of the Enterprise Application. You can get this Object ID via the API (e.g. when using our Terraform provider) or from Enterprise applications pane in Microsoft Entra admin center.", - Required: true, - }, - }, - }, - "provisioning": schema.SingleNestedAttribute{ - MarkdownDescription: "To provide Azure Subscription for your organization’s meshProjects, meshcloud supports using Enterprise Enrollment or allocating from a pool of pre-provisioned subscriptions. One of the subFields enterpriseEnrollment, customerAgreement or preProvisioned must be provided!", - Optional: true, - Attributes: map[string]schema.Attribute{ - "subscription_owner_object_ids": schema.ListAttribute{ - MarkdownDescription: "One or more principals Object IDs (e.g. user groups, SPNs) that meshStack will ensure have an 'Owner' role assignment on the managed subscriptions. This can be useful to satisfy Azure’s constraint of at least one direct 'Owner' role assignment per Subscription. If you want to use a Service Principal please use the Enterprise Application Object ID. You can not use the replicator object ID here, because meshStack always removes its high privilege access after a Subscription creation.", - Optional: true, - ElementType: types.StringType, - }, - "enterprise_enrollment": schema.SingleNestedAttribute{ - MarkdownDescription: "meshcloud can automatically provision new subscriptions from an Enterprise Enrollment Account owned by your organization. This is suitable for large organizations that have a Microsoft Enterprise Agreement, Microsoft Customer Agreement or a Microsoft Partner Agreement and want to provide a large number of subscriptions in a fully automated fashion.", - Optional: true, - Attributes: map[string]schema.Attribute{ - "enrollment_account_id": schema.StringAttribute{ - MarkdownDescription: "ID of the EA Enrollment Account used for the Subscription creation. Should look like this: `/providers/Microsoft.Billing/billingAccounts/1234567/enrollmentAccounts/7654321`. For more information, review the [Azure docs](https://docs.microsoft.com/en-us/azure/cost-management-billing/manage/programmatically-create-subscription-enterprise-agreement?tabs=rest-getEnrollments%2Crest-EA#find-accounts-you-have-access-to).", - Required: true, - }, - "subscription_offer_type": schema.StringAttribute{ - MarkdownDescription: "The Microsoft Subscription offer type to use when creating subscriptions. Only Production for standard and DevTest for Dev/Test subscriptions are supported for the Non Legacy Subscription Enrollment. For the Legacy Subscription Enrollment also other types can be defined.", - Required: true, - }, - "use_legacy_subscription_enrollment": schema.BoolAttribute{ - MarkdownDescription: "Deprecated: Uses the old Subscription enrollment API in its preview version. This enrollment is less reliable and should not be used for new Azure Platform Integrations.", - Optional: true, - }, - "subscription_creation_error_cooldown_sec": schema.Int64Attribute{ - MarkdownDescription: "This value must be defined in seconds. It is a safety mechanism to avoid duplicate Subscription creation in case of an error on Azure’s MCA API. This delay should be a bit higher than it usually takes to create subscriptions. For big installations this is somewhere between 5-15 minutes. The default of 900s should be fine for most installations.", - Optional: true, - }, - }, - }, - "customer_agreement": schema.SingleNestedAttribute{ - MarkdownDescription: "meshcloud can automatically provision new subscriptions from a Customer Agreement Account owned by your organization. This is suitable for larger organizations that have such a Customer Agreement with Microsoft, and want to provide a large number of subscriptions in a fully automated fashion.", - Optional: true, - Attributes: map[string]schema.Attribute{ - "source_service_principal": schema.SingleNestedAttribute{ - MarkdownDescription: "Configure the SPN used by meshStack to create a new Subscription in your MCA billing scope. For more information on the required permissions, see the [Azure docs](https://learn.microsoft.com/en-us/azure/cost-management-billing/manage/programmatically-create-subscription-microsoft-customer-agreement-across-tenants).", - Optional: true, - Attributes: map[string]schema.Attribute{ - "client_id": schema.StringAttribute{ - MarkdownDescription: "The Application (Client) ID. In Azure Portal, this is the Application ID of the \"Enterprise Application\" but can also be retrieved via the \"App Registration\" object as \"Application (Client) ID\".", - Required: true, - }, - "auth_type": schema.StringAttribute{ - MarkdownDescription: "Must be one of `CREDENTIALS` or `WORKLOAD_IDENTITY`. Workload Identity Federation is the one that we recommend as it enables the most secure approach to provide access to your Azure tenant without using long lived credentials. Credential Authentication is an alternative approach where you have to provide a clientSecret manually to meshStack and meshStack stores it encrypted.", - Required: true, - }, - "credentials_auth_client_secret": schema.StringAttribute{ - MarkdownDescription: "Must be set if and only if authType is CREDENTIALS. A valid secret for accessing the application. In Azure Portal, this can be configured on the \"App Registration\" under Certificates & secrets. [How is this information secured?](https://docs.meshcloud.io/operations/security-faq/#how-does-meshstack-securely-handle-my-cloud-platform-credentials)", - Optional: true, - Sensitive: true, - }, - }, - }, - "destination_entra_id": schema.StringAttribute{ - MarkdownDescription: "Microsoft Entra ID Tenant UUID where created subscriptions should be moved. Set this to the Microsoft Entra ID Tenant hosting your landing zones.", - Required: true, - }, - "source_entra_tenant": schema.StringAttribute{ - MarkdownDescription: "Microsoft Entra ID Tenant UUID or domain name used for creating subscriptions. Set this to the Microsoft Entra ID Tenant owning the MCA Billing Scope. If source and destination Microsoft Entra ID Tenants are the same, you need to use UUID.", - Required: true, - }, - "billing_scope": schema.StringAttribute{ - MarkdownDescription: "ID of the MCA Billing Scope used for creating subscriptions. Must follow this format: `/providers/Microsoft.Billing/billingAccounts/$accountId/billingProfiles/$profileId/invoiceSections/$sectionId`.", - Required: true, - }, - "subscription_creation_error_cooldown_sec": schema.Int64Attribute{ - MarkdownDescription: "This value must be defined in seconds. It is a safety mechanism to avoid duplicate Subscription creation in case of an error on Azure’s MCA API. This delay should be a bit higher than it usually takes to create subscriptions. For big installations this is somewhere between 5-15 minutes. The default of 900s should be fine for most installations.", - Optional: true, - }, - }, - }, - "pre_provisioned": schema.SingleNestedAttribute{ - MarkdownDescription: "If your organization does not have access to an Enterprise Enrollment, you can alternatively configure meshcloud to consume subscriptions from a pool of externally-provisioned subscriptions. This is useful for smaller organizations that wish to use 'Pay-as-you-go' subscriptions or if you’re organization partners with an Azure Cloud Solution Provider to provide your subscriptions. The meshcloud Azure replication detects externally-provisioned subscriptions based on a configurable prefix in the subscription name. Upon assignment to a meshProject, the subscription is inflated with the right Landing Zone configuration and removed from the subscription pool.", - Optional: true, - Attributes: map[string]schema.Attribute{ - "unused_subscription_name_prefix": schema.StringAttribute{ - MarkdownDescription: "The prefix that identifies unused subscriptions. Subscriptions will be renamed during meshStack’s project replication, at which point they should no longer carry this prefix.", - Required: true, - }, - }, - }, - }, - }, - "b2b_user_invitation": schema.SingleNestedAttribute{ - MarkdownDescription: "Optional B2B user invitation configuration. When configured, instructs the replicator to create AAD B2B guest invitations for users missing in the AAD tenant managed by this meshPlatform.", - Optional: true, - Attributes: map[string]schema.Attribute{ - "redirect_url": schema.StringAttribute{ - MarkdownDescription: "This is the URL that Azure’s consent experience redirects users to after they accept their invitation.", - Optional: true, - }, - "send_azure_invitation_mail": schema.BoolAttribute{ - MarkdownDescription: "When true, meshStack instructs Azure to send out Invitation mails to invited users. These mails allow users to redeem their invitation to the AAD tenant only using email and Azure Portal.", - Optional: true, - }, - }, - }, - "subscription_name_pattern": schema.StringAttribute{ - MarkdownDescription: "Configures the pattern that defines the desired name of Azure Subscriptions managed by meshStack.", - Optional: true, - }, - "group_name_pattern": schema.StringAttribute{ - MarkdownDescription: "Configures the pattern that defines the desired name of AAD groups managed by meshStack. It follows the usual replicator string pattern features and provides the additional replacement 'platformGroupAlias', which contains the role name suffix, which is configurable via Role Mappings in this platform config or via a meshLandingZone. Operators must ensure the group names are unique in the managed AAD Tenant.", - Optional: true, - }, - "blueprint_service_principal": schema.StringAttribute{ - MarkdownDescription: " \t\n\nObject ID of the Enterprise Application belonging to the Microsoft Application 'Azure Blueprints'. meshStack will grant the necessary permissions on managed Subscriptions to this SPN so that it can create System Assigned Managed Identities (SAMI) for Blueprint execution.", - Optional: true, - }, - "blueprint_location": schema.StringAttribute{ - MarkdownDescription: "The Azure location where replication creates and updates Blueprint Assignments. Note that it’s still possible that the Blueprint creates resources in other locations, this is merely the location where the Blueprint Assignment is managed.", - Optional: true, - }, - "azure_role_mappings": schema.ListNestedAttribute{ - MarkdownDescription: "Azure role mappings for Azure role definitions.", - Optional: true, - NestedObject: schema.NestedAttributeObject{ - Attributes: map[string]schema.Attribute{ - "project_role_ref": meshProjectRoleAttribute(), - "azure_role": schema.SingleNestedAttribute{ - MarkdownDescription: "The Azure role definition.", - Required: true, - Attributes: map[string]schema.Attribute{ - "alias": schema.StringAttribute{ - MarkdownDescription: "The alias/name of the Azure role.", - Required: true, - }, - "id": schema.StringAttribute{ - MarkdownDescription: "The Azure role definition ID.", - Required: true, - }, - }, - }, - }, - }, - }, - "tenant_tags": schema.SingleNestedAttribute{ - MarkdownDescription: "Tenant tagging configuration.", - Optional: true, - Attributes: map[string]schema.Attribute{ - "namespace_prefix": schema.StringAttribute{ - MarkdownDescription: "This is the prefix for all labels created by meshStack. It helps to keep track of which labels are managed by meshStack. It is recommended to let this prefix end with a delimiter like an underscore.", - Required: true, - }, - "tag_mappers": schema.ListNestedAttribute{ - MarkdownDescription: "List of tag mappers for tenant tags", - Optional: true, - NestedObject: schema.NestedAttributeObject{ - Attributes: map[string]schema.Attribute{ - "key": schema.StringAttribute{ - MarkdownDescription: "Key for the tag mapper", - Required: true, - }, - "value_pattern": schema.StringAttribute{ - MarkdownDescription: "Value pattern for the tag mapper", - Required: true, - }, - }, - }, - }, - }, - }, - "user_look_up_strategy": schema.StringAttribute{ - MarkdownDescription: "User lookup strategy (`userPrincipalName` or `email`). Users can either be looked up in cloud platforms by email or UPN (User Principal Name). In most cases email is the matching way as it is the only identifier that is consistently used throughout all cloud platforms and meshStack.", - Optional: true, - }, - "skip_user_group_permission_cleanup": schema.BoolAttribute{ - MarkdownDescription: "Flag to skip user group permission cleanup. For certain use cases you might want to preserve user groups and replicated permission after a tenant was deleted on the Azure platform. Checking this option preserves those permissions. Please keep in mind that the platform operator is then responsible for cleaning them up later.", - Optional: true, - }, - "administrative_unit_id": schema.StringAttribute{ - MarkdownDescription: "If you enter an administrative unit ID the replicated (and potentially existing) groups will be put into this AU. This can be used to limit the permission scopes which are required for the replicator principal. If you remove the AU ID again or change it, the groups will not be removed from the old AU.", - Optional: true, - }, - "allow_hierarchical_management_group_assignment": schema.BoolAttribute{ - MarkdownDescription: "Configuration flag to enable or disable hierarchical management group assignment in Azure. If set to true: Subscriptions can be moved to sub management groups of the management group defined in the Landing Zone. This is useful if you want to manage the subscription location with a deeper and more granular hierarchy. If set to false: Subscriptions will always be moved directly to the management group defined in the Landing Zone.", - Optional: true, - }, - }, - } -} - -func azureRgReplicationConfigSchema() schema.Attribute { - return schema.SingleNestedAttribute{ - MarkdownDescription: "Azure Resource Group-specific replication configuration for the platform.", - Optional: true, - Attributes: map[string]schema.Attribute{ - "service_principal": schema.SingleNestedAttribute{ - MarkdownDescription: "Service principal configuration for Azure Resource Group access.", - Optional: true, - Attributes: map[string]schema.Attribute{ - "client_id": schema.StringAttribute{ - MarkdownDescription: "The Application (Client) ID. In Azure Portal, this is the Application ID of the 'Enterprise Application' but can also be retrieved via the 'App Registration' object as 'Application (Client) ID", - Required: true, - }, - "auth_type": schema.StringAttribute{ - MarkdownDescription: "Authentication type (`CREDENTIALS` or `WORKLOAD_IDENTITY`)", - Required: true, - }, - "credentials_auth_client_secret": schema.StringAttribute{ - MarkdownDescription: "Client secret (if authType is `CREDENTIALS`)", - Optional: true, - Sensitive: true, - }, - "object_id": schema.StringAttribute{ - MarkdownDescription: "The Object ID of the Enterprise Application. You can get this Object ID via the API (e.g. when using our Terraform provider) or from Enterprise applications pane in Microsoft Entra admin center.", - Required: true, - }, - }, - }, - "subscription": schema.StringAttribute{ - MarkdownDescription: "The Subscription that will contain all the created Resource Groups. Once you set the Subscription, you must not change it.", - Optional: true, - }, - "resource_group_name_pattern": schema.StringAttribute{ - MarkdownDescription: "Configures the pattern that defines the desired name Resource Group managed by meshStack. It follows the usual replicator string pattern features. Operators must ensure the group names are unique within the Subscription.", - Optional: true, - }, - "user_group_name_pattern": schema.StringAttribute{ - MarkdownDescription: "Configures the pattern that defines the desired name of AAD groups managed by meshStack. It follows the usual replicator string pattern features and provides the additional replacement 'platformGroupAlias', which contains the role name suffix. This suffix is configurable via Role Mappings in this platform config.", - Optional: true, - }, - "b2b_user_invitation": schema.SingleNestedAttribute{ - MarkdownDescription: "Optional B2B user invitation configuration. When configured, instructs the replicator to create AAD B2B guest invitations for users missing in the AAD tenant managed by this meshPlatform.", - Optional: true, - Attributes: map[string]schema.Attribute{ - "redirect_url": schema.StringAttribute{ - MarkdownDescription: "This is the URL that Azure’s consent experience redirects users to after they accept their invitation.", - Optional: true, - }, - "send_azure_invitation_mail": schema.BoolAttribute{ - MarkdownDescription: "When true, meshStack instructs Azure to send out Invitation mails to invited users. These mails allow users to redeem their invitation to the AAD tenant only using email and Azure Portal.", - Optional: true, - }, - }, - }, - "user_look_up_strategy": schema.StringAttribute{ - MarkdownDescription: "User lookup strategy (`userPrincipalName` or `email`). Users can either be looked up in cloud platforms by email or UPN (User Principal Name). In most cases email is the matching way as it is the only identifier that is consistently used throughout all cloud platforms and meshStack.", - Optional: true, - }, - "tenant_tags": schema.SingleNestedAttribute{ - MarkdownDescription: "Tenant tags configuration", - Optional: true, - Attributes: map[string]schema.Attribute{ - "namespace_prefix": schema.StringAttribute{ - MarkdownDescription: "This is the prefix for all labels created by meshStack. It helps to keep track of which labels are managed by meshStack. It is recommended to let this prefix end with a delimiter like an underscore.", - Required: true, - }, - "tag_mappers": schema.ListNestedAttribute{ - MarkdownDescription: "List of tag mappers for tenant tags", - Optional: true, - NestedObject: schema.NestedAttributeObject{ - Attributes: map[string]schema.Attribute{ - "key": schema.StringAttribute{ - MarkdownDescription: "Key for the tag mapper", - Required: true, - }, - "value_pattern": schema.StringAttribute{ - MarkdownDescription: "Value pattern for the tag mapper", - Required: true, - }, - }, - }, - }, - }, - }, - "skip_user_group_permission_cleanup": schema.BoolAttribute{ - MarkdownDescription: "For certain use cases you might want to preserve user groups and replicated permission after a tenant was deleted on the Azure platform. Checking this option preserves those permissions. Please keep in mind that the platform operator is then responsible for cleaning them up later.", - Optional: true, - }, - "administrative_unit_id": schema.StringAttribute{ - MarkdownDescription: "If you enter an administrative unit ID the replicated (and potentially existing) groups will be put into this AU. This can be used to limit the permission scopes which are required for the replicator principal. If you remove the AU ID again or change it, the groups will not be removed from the old AU.", - Optional: true, - }, - "allow_hierarchical_management_group_assignment": schema.BoolAttribute{ - MarkdownDescription: "Configuration flag to enable or disable hierarchical management group assignment in Azure. If set to true: Subscriptions can be moved to child management groups of the management group defined in the Landing Zone. This is useful if you want to manage the subscription location with a deeper and more granular hierarchy. If set to false: Subscriptions will always be moved directly to the management group defined in the Landing Zone.", - Optional: true, - }, - }, - } -} - -func gcpReplicationConfigSchema() schema.Attribute { - return schema.SingleNestedAttribute{ - MarkdownDescription: "GCP-specific replication configuration for the platform.", - Optional: true, - Attributes: map[string]schema.Attribute{ - "service_account_config": schema.SingleNestedAttribute{ - MarkdownDescription: "Service account configuration. Either `serviceAccountCredentialsConfig` or `serviceAccountWorkloadIdentityConfig` must be provided.", - Optional: true, - Attributes: map[string]schema.Attribute{ - "service_account_credentials_config": schema.SingleNestedAttribute{ - MarkdownDescription: "Service account credentials configuration (alternative to serviceAccountWorkloadIdentityConfig)", - Optional: true, - Attributes: map[string]schema.Attribute{ - "service_account_credentials_b64": schema.StringAttribute{ - MarkdownDescription: "Base64 encoded credentials.json file for a GCP ServiceAccount. The replicator uses this Service Account to automate GCP API operations (IAM, ResourceManager etc.).", - Optional: true, - Sensitive: true, - }, - }, - }, - "service_account_workload_identity_config": schema.SingleNestedAttribute{ - MarkdownDescription: "Service account workload identity configuration (alternative to serviceAccountCredentialsConfig)", - Optional: true, - Attributes: map[string]schema.Attribute{ - "audience": schema.StringAttribute{ - MarkdownDescription: "The audience associated with your workload identity pool provider.", - Optional: true, - }, - "service_account_email": schema.StringAttribute{ - MarkdownDescription: "The email address of the Service Account, that gets impersonated for calling Google APIs via Workload Identity Federation.", - Optional: true, - }, - }, - }, - }, - }, - "domain": schema.StringAttribute{ - MarkdownDescription: "The domain used for cloud identity directory-groups created and managed by meshStack. meshStack maintains separate groups for each meshProject role on each managed GCP project.", - Optional: true, - }, - "customer_id": schema.StringAttribute{ - MarkdownDescription: "A Google Customer ID. It typically starts with a 'C'.", - Optional: true, - }, - "group_name_pattern": schema.StringAttribute{ - MarkdownDescription: "All the commonly available replicator string template properties are available. Additionally you can also use 'platformGroupAlias' as a placeholder to access the specific project role from the role mappings done in this platform configuration or in the meshLandingZone configuration.", - Optional: true, - }, - "project_name_pattern": schema.StringAttribute{ - MarkdownDescription: "All the commonly available replicator string template properties are available. The result must be 4 to 30 characters. Allowed characters are: lowercase and uppercase letters, numbers, hyphen, single-quote, double-quote, space, and exclamation point. When length restrictions are applied, the abbreviation will be in the middle and marked by a single-quote.", - Optional: true, - }, - "project_id_pattern": schema.StringAttribute{ - MarkdownDescription: "All the commonly available replicator string template properties are available. The resulting string must not exceed a total length of 30 characters. Only alphanumeric + hyphen are allowed. We recommend that configuration include at least 3 characters of the random parameter to reduce the chance of naming collisions as the project Ids must be globally unique within GCP.", - Optional: true, - }, - "billing_account_id": schema.StringAttribute{ - MarkdownDescription: "The ID of the billing account to associate with all GCP projects managed by meshStack", - Optional: true, - }, - "user_lookup_strategy": schema.StringAttribute{ - MarkdownDescription: "Users can either be looked up by E-Mail or externalAccountId. This must also be the property that is placed in the external user id (EUID) of your meshUser entity to match. E-Mail is usually a good choice as this is often set up as the EUID throughout all cloud platforms and meshStack. ('email' or 'externalId')", - Optional: true, - }, - "gcp_role_mappings": schema.ListNestedAttribute{ - MarkdownDescription: "Mapping of platform roles to GCP IAM roles.", - Optional: true, - NestedObject: schema.NestedAttributeObject{ - Attributes: map[string]schema.Attribute{ - "project_role_ref": meshProjectRoleAttribute(), - "gcp_role": schema.StringAttribute{ - MarkdownDescription: "The GCP IAM role", - Required: true, - }, - }, - }, - }, - "allow_hierarchical_folder_assignment": schema.BoolAttribute{ - MarkdownDescription: "Configuration flag to enable or disable hierarchical folder assignment in GCP. If set to true: Projects can be moved to sub folders of the folder defined in the Landing Zone. This is useful if you want to manage the project location with a deeper and more granular hierarchy. If set to false: Projects will always be moved directly to the folder defined in the Landing Zone.", - Optional: true, - }, - "tenant_tags": schema.SingleNestedAttribute{ - MarkdownDescription: "Tenant tags configuration", - Optional: true, - Attributes: map[string]schema.Attribute{ - "namespace_prefix": schema.StringAttribute{ - MarkdownDescription: "Namespace prefix for tenant tags", - Optional: true, - }, - "tag_mappers": schema.ListNestedAttribute{ - MarkdownDescription: "List of tag mappers for tenant tags", - Optional: true, - NestedObject: schema.NestedAttributeObject{ - Attributes: map[string]schema.Attribute{ - "key": schema.StringAttribute{ - MarkdownDescription: "Key for the tag mapper", - Required: true, - }, - "value_pattern": schema.StringAttribute{ - MarkdownDescription: "Value pattern for the tag mapper", - Required: true, - }, - }, - }, - }, - }, - }, - "skip_user_group_permission_cleanup": schema.BoolAttribute{ - MarkdownDescription: "For certain use cases you might want to preserve user groups and replicated permission after a tenant was deleted on the GCP platform. Checking this option preserves those permissions. Please keep in mind that the platform operator is then responsible for cleaning them up later.", - Optional: true, - }, - }, - } -} - -func kubernetesReplicationConfigSchema() schema.Attribute { - return schema.SingleNestedAttribute{ - MarkdownDescription: "Replication configuration for Kubernetes (optional, but required for replication)", - Optional: true, - Attributes: map[string]schema.Attribute{ - "client_config": schema.SingleNestedAttribute{ - MarkdownDescription: "Client configuration for Kubernetes", - Optional: true, - Attributes: map[string]schema.Attribute{ - "access_token": schema.StringAttribute{ - MarkdownDescription: "The Access Token of the service account for replicator access.", - Optional: true, - Sensitive: true, - }, - }, - }, - "namespace_name_pattern": schema.StringAttribute{ - MarkdownDescription: "All the commonly available replicator string template properties are available. Kubernetes Namespace Names must be no longer than 63 characters, must start and end with a lowercase letter or number, and may contain lowercase letters, numbers, and hyphens.", - Optional: true, - }, - }, - } -} - -func openShiftReplicationConfigSchema() schema.Attribute { - return schema.SingleNestedAttribute{ - MarkdownDescription: "Replication configuration for OpenShift (optional, but required for replication)", - Optional: true, - Attributes: map[string]schema.Attribute{ - "client_config": schema.SingleNestedAttribute{ - MarkdownDescription: "Client configuration for OpenShift", - Optional: true, - Attributes: map[string]schema.Attribute{ - "access_token": schema.StringAttribute{ - MarkdownDescription: "The Access Token of the service account for replicator access.", - Optional: true, - Sensitive: true, - }, - }, - }, - "web_console_url": schema.StringAttribute{ - MarkdownDescription: "The Web Console URL that is used to redirect the user to the cloud platform. An example Web Console URL is https://console-openshift-console.apps.okd4.dev.eu-de-central.msh.host", - Optional: true, - }, - "project_name_pattern": schema.StringAttribute{ - MarkdownDescription: "All the commonly available replicator string template properties are available. OpenShift Project Names must be no longer than 63 characters, must start and end with a lowercase letter or number, and may contain lowercase letters, numbers, and hyphens.", - Optional: true, - }, - "enable_template_instantiation": schema.BoolAttribute{ - MarkdownDescription: "Here you can enable templates not only being rolled out to OpenShift but also instantiated during replication. Templates can be configured in meshLandingZones. Please keep in mind that the replication service account needs all the rights that are required to apply the templates that are configured in meshLandingZones.", - Optional: true, - }, - "openshift_role_mappings": schema.ListNestedAttribute{ - MarkdownDescription: "OpenShift role mappings for OpenShift roles.", - Optional: true, - NestedObject: schema.NestedAttributeObject{ - Attributes: map[string]schema.Attribute{ - "project_role_ref": meshProjectRoleAttribute(), - "openshift_role": schema.StringAttribute{ - MarkdownDescription: "The OpenShift role name", - Required: true, - }, - }, - }, - }, - "identity_provider_name": schema.StringAttribute{ - MarkdownDescription: "Identity provider name", - Optional: true, - }, - "tenant_tags": schema.SingleNestedAttribute{ - MarkdownDescription: "Tenant tags configuration", - Optional: true, - Attributes: map[string]schema.Attribute{ - "namespace_prefix": schema.StringAttribute{ - MarkdownDescription: "This is the prefix for all labels created by meshStack. It helps to keep track of which labels are managed by meshStack. It is recommended to let this prefix end with a delimiter like an underscore.", - Optional: true, - }, - "tag_mappers": schema.ListNestedAttribute{ - MarkdownDescription: "List of tag mappers for tenant tags", - Optional: true, - NestedObject: schema.NestedAttributeObject{ - Attributes: map[string]schema.Attribute{ - "key": schema.StringAttribute{ - MarkdownDescription: "Key for the tag mapper", - Required: true, - }, - "value_pattern": schema.StringAttribute{ - MarkdownDescription: "Value pattern for the tag mapper", - Required: true, - }, - }, - }, - }, - }, + Default: int64default.StaticInt64(65), }, }, } @@ -1172,6 +312,9 @@ func (r *platformResource) Create(ctx context.Context, req resource.CreateReques } handleObfuscatedSecrets(&createdPlatform.Spec.Config, &platform.Spec.Config, resp.Diagnostics) + if resp.Diagnostics.HasError() { + return + } resp.Diagnostics.Append(resp.State.Set(ctx, createdPlatform)...) } @@ -1203,6 +346,9 @@ func (r *platformResource) Read(ctx context.Context, req resource.ReadRequest, r } handleObfuscatedSecrets(&readPlatform.Spec.Config, &statePlatformSpec.Config, resp.Diagnostics) + if resp.Diagnostics.HasError() { + return + } resp.Diagnostics.Append(resp.State.Set(ctx, readPlatform)...) } @@ -1246,6 +392,9 @@ func (r *platformResource) Update(ctx context.Context, req resource.UpdateReques } handleObfuscatedSecrets(&updatedPlatform.Spec.Config, &platform.Spec.Config, resp.Diagnostics) + if resp.Diagnostics.HasError() { + return + } resp.Diagnostics.Append(resp.State.Set(ctx, updatedPlatform)...) } diff --git a/internal/provider/platform_resource_obfuscationhandling.go b/internal/provider/platform_resource_obfuscationhandling.go index 7150fe5..4d26ab4 100644 --- a/internal/provider/platform_resource_obfuscationhandling.go +++ b/internal/provider/platform_resource_obfuscationhandling.go @@ -27,73 +27,85 @@ func handleObfuscatedSecrets(obfuscated *client.PlatformConfig, plain *client.Pl switch obfuscated.Type { case "aks": - if obfuscated.Aks != nil && obfuscated.Aks.Replication != nil && plain.Aks != nil && plain.Aks.Replication != nil { - // access token - if obfuscated.Aks.Replication.AccessToken != nil && - plain.Aks.Replication.AccessToken != nil && - *obfuscated.Aks.Replication.AccessToken == obfuscatedValue { - obfuscated.Aks.Replication.AccessToken = plain.Aks.Replication.AccessToken + if obfuscated.Aks != nil && plain.Aks != nil { + if obfuscated.Aks.Replication != nil && plain.Aks.Replication != nil { + // access token + if obfuscated.Aks.Replication.AccessToken == obfuscatedValue { + obfuscated.Aks.Replication.AccessToken = plain.Aks.Replication.AccessToken + } + // SP client secret + if obfuscated.Aks.Replication.ServicePrincipal.CredentialsAuthClientSecret != nil && + plain.Aks.Replication.ServicePrincipal.CredentialsAuthClientSecret != nil && + *obfuscated.Aks.Replication.ServicePrincipal.CredentialsAuthClientSecret == obfuscatedValue { + obfuscated.Aks.Replication.ServicePrincipal.CredentialsAuthClientSecret = plain.Aks.Replication.ServicePrincipal.CredentialsAuthClientSecret + } } - // SP client secret - if obfuscated.Aks.Replication.ServicePrincipal != nil && - plain.Aks.Replication.ServicePrincipal != nil && - obfuscated.Aks.Replication.ServicePrincipal.CredentialsAuthClientSecret != nil && - plain.Aks.Replication.ServicePrincipal.CredentialsAuthClientSecret != nil && - *obfuscated.Aks.Replication.ServicePrincipal.CredentialsAuthClientSecret == obfuscatedValue { - obfuscated.Aks.Replication.ServicePrincipal.CredentialsAuthClientSecret = plain.Aks.Replication.ServicePrincipal.CredentialsAuthClientSecret + // metering access token + if obfuscated.Aks.Metering != nil && plain.Aks.Metering != nil && + obfuscated.Aks.Metering.ClientConfig.AccessToken == obfuscatedValue { + obfuscated.Aks.Metering.ClientConfig.AccessToken = plain.Aks.Metering.ClientConfig.AccessToken } } case "aws": - if obfuscated.Aws != nil && obfuscated.Aws.Replication != nil && plain.Aws != nil && plain.Aws.Replication != nil { - // replication access-config service-user secret key - if obfuscated.Aws.Replication.AccessConfig != nil && - plain.Aws.Replication.AccessConfig != nil && - obfuscated.Aws.Replication.AccessConfig.ServiceUserConfig != nil && - plain.Aws.Replication.AccessConfig.ServiceUserConfig != nil && - obfuscated.Aws.Replication.AccessConfig.ServiceUserConfig.SecretKey != nil && - plain.Aws.Replication.AccessConfig.ServiceUserConfig.SecretKey != nil && - *obfuscated.Aws.Replication.AccessConfig.ServiceUserConfig.SecretKey == obfuscatedValue { - obfuscated.Aws.Replication.AccessConfig.ServiceUserConfig.SecretKey = plain.Aws.Replication.AccessConfig.ServiceUserConfig.SecretKey + if obfuscated.Aws != nil && plain.Aws != nil { + if obfuscated.Aws.Replication != nil && plain.Aws.Replication != nil { + // replication access-config service-user secret key + if obfuscated.Aws.Replication.AccessConfig.ServiceUserConfig != nil && + plain.Aws.Replication.AccessConfig.ServiceUserConfig != nil && + obfuscated.Aws.Replication.AccessConfig.ServiceUserConfig.SecretKey == obfuscatedValue { + obfuscated.Aws.Replication.AccessConfig.ServiceUserConfig.SecretKey = plain.Aws.Replication.AccessConfig.ServiceUserConfig.SecretKey + } + // replication AWS SSO token + if obfuscated.Aws.Replication.AwsSso != nil && + plain.Aws.Replication.AwsSso != nil && + obfuscated.Aws.Replication.AwsSso.SsoAccessToken == obfuscatedValue { + obfuscated.Aws.Replication.AwsSso.SsoAccessToken = plain.Aws.Replication.AwsSso.SsoAccessToken + } } - // replication AWS SSO token - if obfuscated.Aws.Replication.AwsSso != nil && - plain.Aws.Replication.AwsSso != nil && - obfuscated.Aws.Replication.AwsSso.SsoAccessToken != nil && - plain.Aws.Replication.AwsSso.SsoAccessToken != nil && - *obfuscated.Aws.Replication.AwsSso.SsoAccessToken == obfuscatedValue { - obfuscated.Aws.Replication.AwsSso.SsoAccessToken = plain.Aws.Replication.AwsSso.SsoAccessToken + // metering access-config service-user secret key + if obfuscated.Aws.Metering != nil && plain.Aws.Metering != nil && + obfuscated.Aws.Metering.AccessConfig.ServiceUserConfig != nil && + plain.Aws.Metering.AccessConfig.ServiceUserConfig != nil && + obfuscated.Aws.Metering.AccessConfig.ServiceUserConfig.SecretKey == obfuscatedValue { + obfuscated.Aws.Metering.AccessConfig.ServiceUserConfig.SecretKey = plain.Aws.Metering.AccessConfig.ServiceUserConfig.SecretKey } } case "azure": - if obfuscated.Azure != nil && obfuscated.Azure.Replication != nil && plain.Azure != nil && plain.Azure.Replication != nil { - // replication SP client secret - if obfuscated.Azure.Replication.ServicePrincipal != nil && - plain.Azure.Replication.ServicePrincipal != nil && - obfuscated.Azure.Replication.ServicePrincipal.CredentialsAuthClientSecret != nil && - plain.Azure.Replication.ServicePrincipal.CredentialsAuthClientSecret != nil && - *obfuscated.Azure.Replication.ServicePrincipal.CredentialsAuthClientSecret == obfuscatedValue { - obfuscated.Azure.Replication.ServicePrincipal.CredentialsAuthClientSecret = plain.Azure.Replication.ServicePrincipal.CredentialsAuthClientSecret - } - // replication provisioning customer agreement SP client secret - if obfuscated.Azure.Replication.Provisioning.CustomerAgreement != nil && - plain.Azure.Replication.Provisioning.CustomerAgreement != nil { - if obfuscated.Azure.Replication.Provisioning.CustomerAgreement.SourceServicePrincipal != nil && - plain.Azure.Replication.Provisioning.CustomerAgreement.SourceServicePrincipal != nil && + if obfuscated.Azure != nil && plain.Azure != nil { + if obfuscated.Azure.Replication != nil && plain.Azure.Replication != nil { + // replication SP client secret + if obfuscated.Azure.Replication.ServicePrincipal.CredentialsAuthClientSecret != nil && + plain.Azure.Replication.ServicePrincipal.CredentialsAuthClientSecret != nil && + *obfuscated.Azure.Replication.ServicePrincipal.CredentialsAuthClientSecret == obfuscatedValue { + obfuscated.Azure.Replication.ServicePrincipal.CredentialsAuthClientSecret = plain.Azure.Replication.ServicePrincipal.CredentialsAuthClientSecret + } + // replication provisioning customer agreement SP client secret + if obfuscated.Azure.Replication.Provisioning != nil && + plain.Azure.Replication.Provisioning != nil && + obfuscated.Azure.Replication.Provisioning.CustomerAgreement != nil && + plain.Azure.Replication.Provisioning.CustomerAgreement != nil && obfuscated.Azure.Replication.Provisioning.CustomerAgreement.SourceServicePrincipal.CredentialsAuthClientSecret != nil && plain.Azure.Replication.Provisioning.CustomerAgreement.SourceServicePrincipal.CredentialsAuthClientSecret != nil && *obfuscated.Azure.Replication.Provisioning.CustomerAgreement.SourceServicePrincipal.CredentialsAuthClientSecret == obfuscatedValue { obfuscated.Azure.Replication.Provisioning.CustomerAgreement.SourceServicePrincipal.CredentialsAuthClientSecret = plain.Azure.Replication.Provisioning.CustomerAgreement.SourceServicePrincipal.CredentialsAuthClientSecret } } + // metering SP client secret + if obfuscated.Azure.Metering != nil && plain.Azure.Metering != nil { + if obfuscated.Azure.Metering.ServicePrincipal.CredentialsAuthClientSecret != nil && + plain.Azure.Metering.ServicePrincipal.CredentialsAuthClientSecret != nil && + *obfuscated.Azure.Metering.ServicePrincipal.CredentialsAuthClientSecret == obfuscatedValue { + obfuscated.Azure.Metering.ServicePrincipal.CredentialsAuthClientSecret = plain.Azure.Metering.ServicePrincipal.CredentialsAuthClientSecret + } + } } case "azurerg": - if obfuscated.AzureRg != nil && obfuscated.AzureRg.Replication != nil && plain.AzureRg != nil && plain.AzureRg.Replication != nil { + if obfuscated.AzureRg != nil && plain.AzureRg != nil { // replication SP client secret - if obfuscated.AzureRg.Replication.ServicePrincipal != nil && - plain.AzureRg.Replication.ServicePrincipal != nil && + if obfuscated.AzureRg.Replication != nil && plain.AzureRg.Replication != nil && obfuscated.AzureRg.Replication.ServicePrincipal.CredentialsAuthClientSecret != nil && plain.AzureRg.Replication.ServicePrincipal.CredentialsAuthClientSecret != nil && *obfuscated.AzureRg.Replication.ServicePrincipal.CredentialsAuthClientSecret == obfuscatedValue { @@ -102,42 +114,49 @@ func handleObfuscatedSecrets(obfuscated *client.PlatformConfig, plain *client.Pl } case "kubernetes": - if obfuscated.Kubernetes != nil && obfuscated.Kubernetes.Replication != nil && plain.Kubernetes != nil && plain.Kubernetes.Replication != nil { - // access token - if obfuscated.Kubernetes.Replication.ClientConfig != nil && - plain.Kubernetes.Replication.ClientConfig != nil && - obfuscated.Kubernetes.Replication.ClientConfig.AccessToken != nil && - plain.Kubernetes.Replication.ClientConfig.AccessToken != nil && - *obfuscated.Kubernetes.Replication.ClientConfig.AccessToken == obfuscatedValue { + if obfuscated.Kubernetes != nil && plain.Kubernetes != nil { + // replication access token + if obfuscated.Kubernetes.Replication != nil && plain.Kubernetes.Replication != nil && + obfuscated.Kubernetes.Replication.ClientConfig.AccessToken == obfuscatedValue { obfuscated.Kubernetes.Replication.ClientConfig.AccessToken = plain.Kubernetes.Replication.ClientConfig.AccessToken } + // metering access token + if obfuscated.Kubernetes.Metering != nil && plain.Kubernetes.Metering != nil && + obfuscated.Kubernetes.Metering.ClientConfig.AccessToken == obfuscatedValue { + obfuscated.Kubernetes.Metering.ClientConfig.AccessToken = plain.Kubernetes.Metering.ClientConfig.AccessToken + } } case "gcp": - if obfuscated.Gcp != nil && obfuscated.Gcp.Replication != nil && plain.Gcp != nil && plain.Gcp.Replication != nil { - // service account credentials - if obfuscated.Gcp.Replication.ServiceAccountConfig != nil && - plain.Gcp.Replication.ServiceAccountConfig != nil && + if obfuscated.Gcp != nil && plain.Gcp != nil { + // replication service account credentials + if obfuscated.Gcp.Replication != nil && plain.Gcp.Replication != nil && obfuscated.Gcp.Replication.ServiceAccountConfig.ServiceAccountCredentialsConfig != nil && plain.Gcp.Replication.ServiceAccountConfig.ServiceAccountCredentialsConfig != nil && - obfuscated.Gcp.Replication.ServiceAccountConfig.ServiceAccountCredentialsConfig.ServiceAccountCredentialsB64 != nil && - plain.Gcp.Replication.ServiceAccountConfig.ServiceAccountCredentialsConfig.ServiceAccountCredentialsB64 != nil && - *obfuscated.Gcp.Replication.ServiceAccountConfig.ServiceAccountCredentialsConfig.ServiceAccountCredentialsB64 == obfuscatedValue { + obfuscated.Gcp.Replication.ServiceAccountConfig.ServiceAccountCredentialsConfig.ServiceAccountCredentialsB64 == obfuscatedValue { obfuscated.Gcp.Replication.ServiceAccountConfig.ServiceAccountCredentialsConfig = plain.Gcp.Replication.ServiceAccountConfig.ServiceAccountCredentialsConfig } + // metering service account credentials + if obfuscated.Gcp.Metering != nil && plain.Gcp.Metering != nil && + obfuscated.Gcp.Metering.ServiceAccountConfig.ServiceAccountCredentialsConfig != nil && + plain.Gcp.Metering.ServiceAccountConfig.ServiceAccountCredentialsConfig != nil && + obfuscated.Gcp.Metering.ServiceAccountConfig.ServiceAccountCredentialsConfig.ServiceAccountCredentialsB64 == obfuscatedValue { + obfuscated.Gcp.Metering.ServiceAccountConfig.ServiceAccountCredentialsConfig = plain.Gcp.Metering.ServiceAccountConfig.ServiceAccountCredentialsConfig + } } case "openshift": - if obfuscated.OpenShift != nil && obfuscated.OpenShift.Replication != nil && plain.OpenShift != nil && plain.OpenShift.Replication != nil { - // access token - if obfuscated.OpenShift.Replication.ClientConfig != nil && - plain.OpenShift.Replication.ClientConfig != nil && - obfuscated.OpenShift.Replication.ClientConfig.AccessToken != nil && - plain.OpenShift.Replication.ClientConfig.AccessToken != nil && - *obfuscated.OpenShift.Replication.ClientConfig.AccessToken == obfuscatedValue { + if obfuscated.OpenShift != nil && plain.OpenShift != nil { + // replication access token + if obfuscated.OpenShift.Replication != nil && plain.OpenShift.Replication != nil && + obfuscated.OpenShift.Replication.ClientConfig.AccessToken == obfuscatedValue { obfuscated.OpenShift.Replication.ClientConfig.AccessToken = plain.OpenShift.Replication.ClientConfig.AccessToken } + // metering access token + if obfuscated.OpenShift.Metering != nil && plain.OpenShift.Metering != nil && + obfuscated.OpenShift.Metering.ClientConfig.AccessToken == obfuscatedValue { + obfuscated.OpenShift.Metering.ClientConfig.AccessToken = plain.OpenShift.Metering.ClientConfig.AccessToken + } } - } } diff --git a/internal/provider/platform_resource_schema_aws.go b/internal/provider/platform_resource_schema_aws.go new file mode 100644 index 0000000..1267e95 --- /dev/null +++ b/internal/provider/platform_resource_schema_aws.go @@ -0,0 +1,221 @@ +package provider + +import ( + "github.com/hashicorp/terraform-plugin-framework/resource/schema" + "github.com/hashicorp/terraform-plugin-framework/types" +) + +func awsPlatformSchema() schema.Attribute { + return schema.SingleNestedAttribute{ + MarkdownDescription: "Configuration for AWS", + Optional: true, + Attributes: map[string]schema.Attribute{ + "region": schema.StringAttribute{ + MarkdownDescription: "AWS region", + Optional: true, + }, + "replication": awsReplicationConfigSchema(), + "metering": awsMeteringConfigSchema(), + }, + } +} + +func awsAccessConfigSchema() schema.Attribute { + return schema.SingleNestedAttribute{ + MarkdownDescription: "meshStack currently supports 2 types of authentication. Workload Identity Federation (using OIDC) is the one that we recommend as it enables secure access to your AWS account without using long lived credentials. Alternatively, you can use credential based authentication by providing access and secret keys. Either the `service_user_config` or `workload_identity_config` must be provided.", + Required: true, + Attributes: map[string]schema.Attribute{ + "organization_root_account_role": schema.StringAttribute{ + MarkdownDescription: "ARN of the Management Account Role. The Management Account contains your AWS organization. E.g. `arn:aws:iam::123456789:role/MeshfedServiceRole`.", + Required: true, + }, + "organization_root_account_external_id": schema.StringAttribute{ + MarkdownDescription: "ExternalId to enhance security in a multi account setup when assuming the organization root account role.", + Optional: true, + }, + "service_user_config": schema.SingleNestedAttribute{ + MarkdownDescription: "Service user configuration (alternative to `workload_identity_config`)", + Optional: true, + Attributes: map[string]schema.Attribute{ + "access_key": schema.StringAttribute{ + MarkdownDescription: "AWS access key for service user", + Required: true, + }, + "secret_key": schema.StringAttribute{ + MarkdownDescription: "AWS secret key for service user", + Required: true, + Sensitive: true, + }, + }, + }, + "workload_identity_config": schema.SingleNestedAttribute{ + MarkdownDescription: "Workload identity configuration (alternative to `service_user_config`)", + Optional: true, + Attributes: map[string]schema.Attribute{ + "role_arn": schema.StringAttribute{ + MarkdownDescription: "ARN of the role that should be used as the entry point for meshStack by assuming it via web identity.", + Required: true, + }, + }, + }, + }, + } +} + +func awsMeteringConfigSchema() schema.Attribute { + return schema.SingleNestedAttribute{ + MarkdownDescription: "Metering configuration for AWS (optional, but required for metering)", + Optional: true, + Attributes: map[string]schema.Attribute{ + "access_config": awsAccessConfigSchema(), + "filter": schema.StringAttribute{ + MarkdownDescription: "Filter for AWS metering data.", + Required: true, + }, + "reserved_instance_fair_chargeback": schema.BoolAttribute{ + MarkdownDescription: "Flag to enable fair chargeback for reserved instances.", + Required: true, + }, + "savings_plan_fair_chargeback": schema.BoolAttribute{ + MarkdownDescription: "Flag to enable fair chargeback for savings plans.", + Required: true, + }, + "processing": meteringProcessingConfigSchema(), + }, + } +} + +func awsReplicationConfigSchema() schema.Attribute { + return schema.SingleNestedAttribute{ + MarkdownDescription: "Replication configuration for AWS (optional, but required for replication)", + Optional: true, + Attributes: map[string]schema.Attribute{ + "access_config": awsAccessConfigSchema(), + "wait_for_external_avm": schema.BoolAttribute{ + MarkdownDescription: "Flag to wait for external AVM. Please use this setting with care! It is currently very specific to certain tags being present on the account! In general, we recommend not to activate this functionality! In a meshLandingZone an AVM can be triggered via an AWS StackSet or via a Lambda Function. If meshStack shall wait for the AVM to complete when creating a new platform tenant, this flag must be checked. meshStack will identify completion of the AVM by checking the presence of the following tags on the AWS account: 'ProductName' is set to workspace identifier and 'Stage' is set to project identifier.", + Required: true, + }, + "automation_account_role": schema.StringAttribute{ + MarkdownDescription: "ARN of the Automation Account Role. The Automation Account contains all AWS StackSets and Lambda Functions that shall be executed via meshLandingZones. E.g. `arn:aws:iam::123456789:role/MeshfedAutomationRole`.", + Required: true, + }, + "automation_account_external_id": schema.StringAttribute{ + MarkdownDescription: "ExternalId to enhance security in a multi account setup when assuming the automation account role.", + Optional: true, + }, + "account_access_role": schema.StringAttribute{ + MarkdownDescription: "The name for the Account Access Role that will be rolled out to all managed accounts. Only a name, not an ARN must be set here, as the ARN must be built dynamically for every managed AWS Account. The replicator service user needs to assume this role in all accounts to manage them.", + Required: true, + }, + "account_alias_pattern": schema.StringAttribute{ + MarkdownDescription: "With a String Pattern you can define how the account alias of the created AWS account will be named. E.g. `#{workspaceIdentifier}-#{projectIdentifier}`. Attention: Account Alias must be globally unique in AWS. So consider defining a unique prefix.", + Required: true, + }, + "enforce_account_alias": schema.BoolAttribute{ + MarkdownDescription: "Flag to enforce account alias. If set, meshStack will guarantee on every replication that the configured Account Alias is applied. Otherwise it will only set the Account Alias once during tenant creation.", + Required: true, + }, + "account_email_pattern": schema.StringAttribute{ + MarkdownDescription: "With a String Pattern you can define how the account email address of the created AWS account will be set. E.g. `aws+#{workspaceIdentifier}.#{projectIdentifier}@yourcompany.com`. Please consider that this email address is limited to 64 characters! Also have a look at our docs for more information.", + Required: true, + }, + "tenant_tags": schema.SingleNestedAttribute{ + MarkdownDescription: "Tenant tags configuration", + Optional: true, + Attributes: map[string]schema.Attribute{ + "namespace_prefix": schema.StringAttribute{ + MarkdownDescription: "Namespace prefix for tenant tags", + Required: true, + }, + "tag_mappers": schema.ListNestedAttribute{ + MarkdownDescription: "List of tag mappers for tenant tags", + Optional: true, + NestedObject: schema.NestedAttributeObject{ + Attributes: map[string]schema.Attribute{ + "key": schema.StringAttribute{ + MarkdownDescription: "Key for the tag mapper", + Required: true, + }, + "value_pattern": schema.StringAttribute{ + MarkdownDescription: "Value pattern for the tag mapper", + Required: true, + }, + }, + }, + }, + }, + }, + "aws_sso": schema.SingleNestedAttribute{ + MarkdownDescription: "AWS SSO configuration", + Optional: true, + Attributes: map[string]schema.Attribute{ + "scim_endpoint": schema.StringAttribute{ + MarkdownDescription: "The SCIM endpoint you can find in your AWS IAM Identity Center Automatic provisioning config.", + Required: true, + }, + "arn": schema.StringAttribute{ + MarkdownDescription: "The ARN of your AWS IAM Identity Center Instance. E.g. `arn:aws:sso:::instance/ssoins-123456789abc`.", + Required: true, + }, + "group_name_pattern": schema.StringAttribute{ + MarkdownDescription: "Configures the pattern that defines the desired name of AWS IAM Identity Center groups managed by meshStack. It follows the usual replicator string pattern features and provides the additional replacement 'platformGroupAlias', which contains the role name suffix, which is configurable via Role Mappings in this platform config or via a meshLandingZone. Operators must ensure the group names will be unique within the same AWS IAM Identity Center Instance with that configuration. meshStack will additionally prefix the group name with 'mst-' to be able to identify the groups that are managed by meshStack.", + Required: true, + }, + "sso_access_token": schema.StringAttribute{ + MarkdownDescription: "The AWS IAM Identity Center SCIM Access Token that was generated via the Automatic provisioning config in AWS IAM Identity Center.", + Optional: true, + Sensitive: true, + }, + "aws_role_mappings": schema.ListNestedAttribute{ + MarkdownDescription: "AWS role mappings for AWS SSO", + Optional: true, + NestedObject: schema.NestedAttributeObject{ + Attributes: map[string]schema.Attribute{ + "project_role_ref": meshProjectRoleAttribute(false), + "aws_role": schema.StringAttribute{ + MarkdownDescription: "The AWS role name", + Required: true, + }, + "permission_set_arns": schema.ListAttribute{ + MarkdownDescription: "List of permission set ARNs associated with this role mapping", + ElementType: types.StringType, + Optional: true, + }, + }, + }, + }, + "sign_in_url": schema.StringAttribute{ + MarkdownDescription: "The AWS IAM Identity Center sign in Url, that must be used by end-users to log in via AWS IAM Identity Center to AWS Management Console.", + Optional: true, + }, + }, + }, + "enrollment_configuration": schema.SingleNestedAttribute{ + MarkdownDescription: "AWS account enrollment configuration.", + Optional: true, + Attributes: map[string]schema.Attribute{ + "management_account_id": schema.StringAttribute{ + MarkdownDescription: "The Account ID of the management account configured for the platform instance.", + Required: true, + }, + "account_factory_product_id": schema.StringAttribute{ + MarkdownDescription: "The Product ID of the AWS Account Factory Product in AWS Service Catalog that should be used for enrollment. Starts with `prod-`.", + Required: true, + }, + }, + }, + "self_downgrade_access_role": schema.BoolAttribute{ + MarkdownDescription: "Flag for self downgrade access role. If set, meshStack will revoke its rights on the managed account that were only needed for initial account creation.", + Required: true, + }, + "skip_user_group_permission_cleanup": schema.BoolAttribute{ + MarkdownDescription: "Flag to skip user group permission cleanup. For certain use cases you might want to preserve user groups and replicated permission after a tenant was deleted on the AWS platform. Checking this option preserves those permissions. Please keep in mind that the platform operator is then responsible for cleaning them up later.", + Required: true, + }, + "allow_hierarchical_organizational_unit_assignment": schema.BoolAttribute{ + MarkdownDescription: "Configuration flag to enable or disable hierarchical organizational unit assignment in AWS. If set to true: Accounts can be moved to child organizational units of the organizational unit defined in the Landing Zone. This is useful if you want to manage the account location with a deeper and more granular hierarchy. If set to false: Accounts will always be moved directly to the organizational unit defined in the Landing Zone.", + Required: true, + }, + }, + } +} diff --git a/internal/provider/platform_resource_schema_azure.go b/internal/provider/platform_resource_schema_azure.go new file mode 100644 index 0000000..1acc76a --- /dev/null +++ b/internal/provider/platform_resource_schema_azure.go @@ -0,0 +1,383 @@ +package provider + +import ( + "github.com/hashicorp/terraform-plugin-framework/resource/schema" + "github.com/hashicorp/terraform-plugin-framework/types" +) + +// Plain Azure + +func azurePlatformSchema() schema.Attribute { + return schema.SingleNestedAttribute{ + MarkdownDescription: "Azure platform configuration.", + Optional: true, + Attributes: map[string]schema.Attribute{ + "entra_tenant": schema.StringAttribute{ + MarkdownDescription: "Azure Active Directory (Entra ID) tenant", + Required: true, + }, + "replication": azureReplicationConfigSchema(), + "metering": azureMeteringConfigSchema(), + }, + } +} + +func azureReplicationConfigSchema() schema.Attribute { + return schema.SingleNestedAttribute{ + MarkdownDescription: "Azure-specific replication configuration for the platform.", + Optional: true, + Attributes: map[string]schema.Attribute{ + "service_principal": schema.SingleNestedAttribute{ + MarkdownDescription: "Service principal configuration for Azure", + Required: true, + Attributes: map[string]schema.Attribute{ + "client_id": schema.StringAttribute{ + MarkdownDescription: "The Application (Client) ID. In Azure Portal, this is the Application ID of the 'Enterprise Application' but can also be retrieved via the 'App Registration' object as 'Application (Client) ID", + Required: true, + }, + "auth_type": schema.StringAttribute{ + MarkdownDescription: "Authentication type (`CREDENTIALS` or `WORKLOAD_IDENTITY`)", + Required: true, + }, + "credentials_auth_client_secret": schema.StringAttribute{ + MarkdownDescription: "Client secret (if authType is `CREDENTIALS`)", + Optional: true, + Sensitive: true, + }, + "object_id": schema.StringAttribute{ + MarkdownDescription: "The Object ID of the Enterprise Application. You can get this Object ID via the API (e.g. when using our Terraform provider) or from Enterprise applications pane in Microsoft Entra admin center.", + Required: true, + }, + }, + }, + "provisioning": schema.SingleNestedAttribute{ + MarkdownDescription: "To provide Azure Subscription for your organization's meshProjects, meshcloud supports using Enterprise Enrollment or allocating from a pool of pre-provisioned subscriptions. One of the subFields enterpriseEnrollment, customerAgreement or preProvisioned must be provided!", + Optional: true, + Attributes: map[string]schema.Attribute{ + "subscription_owner_object_ids": schema.ListAttribute{ + MarkdownDescription: "One or more principals Object IDs (e.g. user groups, SPNs) that meshStack will ensure have an 'Owner' role assignment on the managed subscriptions. This can be useful to satisfy Azure's constraint of at least one direct 'Owner' role assignment per Subscription. If you want to use a Service Principal please use the Enterprise Application Object ID. You can not use the replicator object ID here, because meshStack always removes its high privilege access after a Subscription creation.", + Optional: true, + ElementType: types.StringType, + }, + "enterprise_enrollment": schema.SingleNestedAttribute{ + MarkdownDescription: "meshcloud can automatically provision new subscriptions from an Enterprise Enrollment Account owned by your organization. This is suitable for large organizations that have a Microsoft Enterprise Agreement, Microsoft Customer Agreement or a Microsoft Partner Agreement and want to provide a large number of subscriptions in a fully automated fashion.", + Optional: true, + Attributes: map[string]schema.Attribute{ + "enrollment_account_id": schema.StringAttribute{ + MarkdownDescription: "ID of the EA Enrollment Account used for the Subscription creation. Should look like this: `/providers/Microsoft.Billing/billingAccounts/1234567/enrollmentAccounts/7654321`. For more information, review the [Azure docs](https://docs.microsoft.com/en-us/azure/cost-management-billing/manage/programmatically-create-subscription-enterprise-agreement?tabs=rest-getEnrollments%2Crest-EA#find-accounts-you-have-access-to).", + Required: true, + }, + "subscription_offer_type": schema.StringAttribute{ + MarkdownDescription: "The Microsoft Subscription offer type to use when creating subscriptions. Only Production for standard and DevTest for Dev/Test subscriptions are supported for the Non Legacy Subscription Enrollment. For the Legacy Subscription Enrollment also other types can be defined.", + Required: true, + }, + "use_legacy_subscription_enrollment": schema.BoolAttribute{ + MarkdownDescription: "Deprecated: Uses the old Subscription enrollment API in its preview version. This enrollment is less reliable and should not be used for new Azure Platform Integrations.", + Optional: true, + }, + "subscription_creation_error_cooldown_sec": schema.Int64Attribute{ + MarkdownDescription: "This value must be defined in seconds. It is a safety mechanism to avoid duplicate Subscription creation in case of an error on Azure's MCA API. This delay should be a bit higher than it usually takes to create subscriptions. For big installations this is somewhere between 5-15 minutes. The default of 900s should be fine for most installations.", + Optional: true, + }, + }, + }, + "customer_agreement": schema.SingleNestedAttribute{ + MarkdownDescription: "meshcloud can automatically provision new subscriptions from a Customer Agreement Account owned by your organization. This is suitable for larger organizations that have such a Customer Agreement with Microsoft, and want to provide a large number of subscriptions in a fully automated fashion.", + Optional: true, + Attributes: map[string]schema.Attribute{ + "source_service_principal": schema.SingleNestedAttribute{ + MarkdownDescription: "Configure the SPN used by meshStack to create a new Subscription in your MCA billing scope. For more information on the required permissions, see the [Azure docs](https://learn.microsoft.com/en-us/azure/cost-management-billing/manage/programmatically-create-subscription-microsoft-customer-agreement-across-tenants).", + Optional: true, + Attributes: map[string]schema.Attribute{ + "client_id": schema.StringAttribute{ + MarkdownDescription: "The Application (Client) ID. In Azure Portal, this is the Application ID of the \"Enterprise Application\" but can also be retrieved via the \"App Registration\" object as \"Application (Client) ID\".", + Required: true, + }, + "auth_type": schema.StringAttribute{ + MarkdownDescription: "Must be one of `CREDENTIALS` or `WORKLOAD_IDENTITY`. Workload Identity Federation is the one that we recommend as it enables the most secure approach to provide access to your Azure tenant without using long lived credentials. Credential Authentication is an alternative approach where you have to provide a clientSecret manually to meshStack and meshStack stores it encrypted.", + Required: true, + }, + "credentials_auth_client_secret": schema.StringAttribute{ + MarkdownDescription: "Must be set if and only if authType is CREDENTIALS. A valid secret for accessing the application. In Azure Portal, this can be configured on the \"App Registration\" under Certificates & secrets. [How is this information secured?](https://docs.meshcloud.io/operations/security-faq/#how-does-meshstack-securely-handle-my-cloud-platform-credentials)", + Optional: true, + Sensitive: true, + }, + }, + }, + "destination_entra_id": schema.StringAttribute{ + MarkdownDescription: "Microsoft Entra ID Tenant UUID where created subscriptions should be moved. Set this to the Microsoft Entra ID Tenant hosting your landing zones.", + Required: true, + }, + "source_entra_tenant": schema.StringAttribute{ + MarkdownDescription: "Microsoft Entra ID Tenant UUID or domain name used for creating subscriptions. Set this to the Microsoft Entra ID Tenant owning the MCA Billing Scope. If source and destination Microsoft Entra ID Tenants are the same, you need to use UUID.", + Required: true, + }, + "billing_scope": schema.StringAttribute{ + MarkdownDescription: "ID of the MCA Billing Scope used for creating subscriptions. Must follow this format: `/providers/Microsoft.Billing/billingAccounts/$accountId/billingProfiles/$profileId/invoiceSections/$sectionId`.", + Required: true, + }, + "subscription_creation_error_cooldown_sec": schema.Int64Attribute{ + MarkdownDescription: "This value must be defined in seconds. It is a safety mechanism to avoid duplicate Subscription creation in case of an error on Azure's MCA API. This delay should be a bit higher than it usually takes to create subscriptions. For big installations this is somewhere between 5-15 minutes. The default of 900s should be fine for most installations.", + Optional: true, + }, + }, + }, + "pre_provisioned": schema.SingleNestedAttribute{ + MarkdownDescription: "If your organization does not have access to an Enterprise Enrollment, you can alternatively configure meshcloud to consume subscriptions from a pool of externally-provisioned subscriptions. This is useful for smaller organizations that wish to use 'Pay-as-you-go' subscriptions or if you're organization partners with an Azure Cloud Solution Provider to provide your subscriptions. The meshcloud Azure replication detects externally-provisioned subscriptions based on a configurable prefix in the subscription name. Upon assignment to a meshProject, the subscription is inflated with the right Landing Zone configuration and removed from the subscription pool.", + Optional: true, + Attributes: map[string]schema.Attribute{ + "unused_subscription_name_prefix": schema.StringAttribute{ + MarkdownDescription: "The prefix that identifies unused subscriptions. Subscriptions will be renamed during meshStack's project replication, at which point they should no longer carry this prefix.", + Required: true, + }, + }, + }, + }, + }, + "b2b_user_invitation": schema.SingleNestedAttribute{ + MarkdownDescription: "Optional B2B user invitation configuration. When configured, instructs the replicator to create AAD B2B guest invitations for users missing in the AAD tenant managed by this meshPlatform.", + Optional: true, + Attributes: map[string]schema.Attribute{ + "redirect_url": schema.StringAttribute{ + MarkdownDescription: "This is the URL that Azure's consent experience redirects users to after they accept their invitation.", + Required: true, + }, + "send_azure_invitation_mail": schema.BoolAttribute{ + MarkdownDescription: "When true, meshStack instructs Azure to send out Invitation mails to invited users. These mails allow users to redeem their invitation to the AAD tenant only using email and Azure Portal.", + Required: true, + }, + }, + }, + "subscription_name_pattern": schema.StringAttribute{ + MarkdownDescription: "Configures the pattern that defines the desired name of Azure Subscriptions managed by meshStack.", + Required: true, + }, + "group_name_pattern": schema.StringAttribute{ + MarkdownDescription: "Configures the pattern that defines the desired name of AAD groups managed by meshStack. It follows the usual replicator string pattern features and provides the additional replacement 'platformGroupAlias', which contains the role name suffix, which is configurable via Role Mappings in this platform config or via a meshLandingZone. Operators must ensure the group names are unique in the managed AAD Tenant.", + Required: true, + }, + "blueprint_service_principal": schema.StringAttribute{ + MarkdownDescription: " \t\n\nObject ID of the Enterprise Application belonging to the Microsoft Application 'Azure Blueprints'. meshStack will grant the necessary permissions on managed Subscriptions to this SPN so that it can create System Assigned Managed Identities (SAMI) for Blueprint execution.", + Required: true, + }, + "blueprint_location": schema.StringAttribute{ + MarkdownDescription: "The Azure location where replication creates and updates Blueprint Assignments. Note that it's still possible that the Blueprint creates resources in other locations, this is merely the location where the Blueprint Assignment is managed.", + Optional: true, + }, + "azure_role_mappings": schema.ListNestedAttribute{ + MarkdownDescription: "Azure role mappings for Azure role definitions.", + Required: true, + NestedObject: schema.NestedAttributeObject{ + Attributes: map[string]schema.Attribute{ + "project_role_ref": meshProjectRoleAttribute(false), + "azure_role": schema.SingleNestedAttribute{ + MarkdownDescription: "The Azure role definition.", + Required: true, + Attributes: map[string]schema.Attribute{ + "alias": schema.StringAttribute{ + MarkdownDescription: "The alias/name of the Azure role.", + Required: true, + }, + "id": schema.StringAttribute{ + MarkdownDescription: "The Azure role definition ID.", + Required: true, + }, + }, + }, + }, + }, + }, + "tenant_tags": schema.SingleNestedAttribute{ + MarkdownDescription: "Tenant tagging configuration.", + Optional: true, + Attributes: map[string]schema.Attribute{ + "namespace_prefix": schema.StringAttribute{ + MarkdownDescription: "This is the prefix for all labels created by meshStack. It helps to keep track of which labels are managed by meshStack. It is recommended to let this prefix end with a delimiter like an underscore.", + Required: true, + }, + "tag_mappers": schema.ListNestedAttribute{ + MarkdownDescription: "List of tag mappers for tenant tags", + Optional: true, + NestedObject: schema.NestedAttributeObject{ + Attributes: map[string]schema.Attribute{ + "key": schema.StringAttribute{ + MarkdownDescription: "Key for the tag mapper", + Required: true, + }, + "value_pattern": schema.StringAttribute{ + MarkdownDescription: "Value pattern for the tag mapper", + Required: true, + }, + }, + }, + }, + }, + }, + "user_look_up_strategy": schema.StringAttribute{ + MarkdownDescription: "User lookup strategy (`userPrincipalName` or `email`). Users can either be looked up in cloud platforms by email or UPN (User Principal Name). In most cases email is the matching way as it is the only identifier that is consistently used throughout all cloud platforms and meshStack.", + Required: true, + }, + "skip_user_group_permission_cleanup": schema.BoolAttribute{ + MarkdownDescription: "Flag to skip user group permission cleanup. For certain use cases you might want to preserve user groups and replicated permission after a tenant was deleted on the Azure platform. Checking this option preserves those permissions. Please keep in mind that the platform operator is then responsible for cleaning them up later.", + Required: true, + }, + "administrative_unit_id": schema.StringAttribute{ + MarkdownDescription: "If you enter an administrative unit ID the replicated (and potentially existing) groups will be put into this AU. This can be used to limit the permission scopes which are required for the replicator principal. If you remove the AU ID again or change it, the groups will not be removed from the old AU.", + Optional: true, + }, + "allow_hierarchical_management_group_assignment": schema.BoolAttribute{ + MarkdownDescription: "Configuration flag to enable or disable hierarchical management group assignment in Azure. If set to true: Subscriptions can be moved to sub management groups of the management group defined in the Landing Zone. This is useful if you want to manage the subscription location with a deeper and more granular hierarchy. If set to false: Subscriptions will always be moved directly to the management group defined in the Landing Zone.", + Required: true, + }, + }, + } +} + +func azureMeteringConfigSchema() schema.Attribute { + return schema.SingleNestedAttribute{ + MarkdownDescription: "Metering configuration for Azure (optional, but required for metering)", + Optional: true, + Attributes: map[string]schema.Attribute{ + "service_principal": schema.SingleNestedAttribute{ + MarkdownDescription: "Service principal configuration for Azure metering", + Required: true, + Attributes: map[string]schema.Attribute{ + "client_id": schema.StringAttribute{ + MarkdownDescription: "The Application (Client) ID. In Azure Portal, this is the Application ID of the 'Enterprise Application' but can also be retrieved via the 'App Registration' object as 'Application (Client) ID", + Required: true, + }, + "auth_type": schema.StringAttribute{ + MarkdownDescription: "Authentication type (`CREDENTIALS` or `WORKLOAD_IDENTITY`)", + Required: true, + }, + "credentials_auth_client_secret": schema.StringAttribute{ + MarkdownDescription: "Client secret (if authType is `CREDENTIALS`)", + Optional: true, + Sensitive: true, + }, + "object_id": schema.StringAttribute{ + MarkdownDescription: "The Object ID of the Enterprise Application. You can get this Object ID via the API (e.g. when using our Terraform provider) or from Enterprise applications pane in Microsoft Entra admin center.", + Required: true, + }, + }, + }, + "processing": meteringProcessingConfigSchema(), + }, + } +} + +// Azure RG + +func azureRgPlatformSchema() schema.Attribute { + return schema.SingleNestedAttribute{ + MarkdownDescription: "Azure Resource Group platform configuration.", + Optional: true, + Attributes: map[string]schema.Attribute{ + "entra_tenant": schema.StringAttribute{ + MarkdownDescription: "Azure Active Directory (Entra ID) tenant", + Required: true, + }, + "replication": azureRgReplicationConfigSchema(), + }, + } +} + +func azureRgReplicationConfigSchema() schema.Attribute { + return schema.SingleNestedAttribute{ + MarkdownDescription: "Azure Resource Group-specific replication configuration for the platform.", + Optional: true, + Attributes: map[string]schema.Attribute{ + "service_principal": schema.SingleNestedAttribute{ + MarkdownDescription: "Service principal configuration for Azure Resource Group access.", + Required: true, + Attributes: map[string]schema.Attribute{ + "client_id": schema.StringAttribute{ + MarkdownDescription: "The Application (Client) ID. In Azure Portal, this is the Application ID of the 'Enterprise Application' but can also be retrieved via the 'App Registration' object as 'Application (Client) ID", + Required: true, + }, + "auth_type": schema.StringAttribute{ + MarkdownDescription: "Authentication type (`CREDENTIALS` or `WORKLOAD_IDENTITY`)", + Required: true, + }, + "credentials_auth_client_secret": schema.StringAttribute{ + MarkdownDescription: "Client secret (if authType is `CREDENTIALS`)", + Optional: true, + Sensitive: true, + }, + "object_id": schema.StringAttribute{ + MarkdownDescription: "The Object ID of the Enterprise Application. You can get this Object ID via the API (e.g. when using our Terraform provider) or from Enterprise applications pane in Microsoft Entra admin center.", + Required: true, + }, + }, + }, + "subscription": schema.StringAttribute{ + MarkdownDescription: "The Subscription that will contain all the created Resource Groups. Once you set the Subscription, you must not change it.", + Required: true, + }, + "resource_group_name_pattern": schema.StringAttribute{ + MarkdownDescription: "Configures the pattern that defines the desired name Resource Group managed by meshStack. It follows the usual replicator string pattern features. Operators must ensure the group names are unique within the Subscription.", + Required: true, + }, + "user_group_name_pattern": schema.StringAttribute{ + MarkdownDescription: "Configures the pattern that defines the desired name of AAD groups managed by meshStack. It follows the usual replicator string pattern features and provides the additional replacement 'platformGroupAlias', which contains the role name suffix. This suffix is configurable via Role Mappings in this platform config.", + Required: true, + }, + "b2b_user_invitation": schema.SingleNestedAttribute{ + MarkdownDescription: "Optional B2B user invitation configuration. When configured, instructs the replicator to create AAD B2B guest invitations for users missing in the AAD tenant managed by this meshPlatform.", + Optional: true, + Attributes: map[string]schema.Attribute{ + "redirect_url": schema.StringAttribute{ + MarkdownDescription: "This is the URL that Azure's consent experience redirects users to after they accept their invitation.", + Required: true, + }, + "send_azure_invitation_mail": schema.BoolAttribute{ + MarkdownDescription: "When true, meshStack instructs Azure to send out Invitation mails to invited users. These mails allow users to redeem their invitation to the AAD tenant only using email and Azure Portal.", + Required: true, + }, + }, + }, + "user_look_up_strategy": schema.StringAttribute{ + MarkdownDescription: "User lookup strategy (`userPrincipalName` or `email`). Users can either be looked up in cloud platforms by email or UPN (User Principal Name). In most cases email is the matching way as it is the only identifier that is consistently used throughout all cloud platforms and meshStack.", + Required: true, + }, + "tenant_tags": schema.SingleNestedAttribute{ + MarkdownDescription: "Tenant tags configuration", + Optional: true, + Attributes: map[string]schema.Attribute{ + "namespace_prefix": schema.StringAttribute{ + MarkdownDescription: "This is the prefix for all labels created by meshStack. It helps to keep track of which labels are managed by meshStack. It is recommended to let this prefix end with a delimiter like an underscore.", + Required: true, + }, + "tag_mappers": schema.ListNestedAttribute{ + MarkdownDescription: "List of tag mappers for tenant tags", + Optional: true, + NestedObject: schema.NestedAttributeObject{ + Attributes: map[string]schema.Attribute{ + "key": schema.StringAttribute{ + MarkdownDescription: "Key for the tag mapper", + Required: true, + }, + "value_pattern": schema.StringAttribute{ + MarkdownDescription: "Value pattern for the tag mapper", + Required: true, + }, + }, + }, + }, + }, + }, + "skip_user_group_permission_cleanup": schema.BoolAttribute{ + MarkdownDescription: "For certain use cases you might want to preserve user groups and replicated permission after a tenant was deleted on the Azure platform. Checking this option preserves those permissions. Please keep in mind that the platform operator is then responsible for cleaning them up later.", + Required: true, + }, + "administrative_unit_id": schema.StringAttribute{ + MarkdownDescription: "If you enter an administrative unit ID the replicated (and potentially existing) groups will be put into this AU. This can be used to limit the permission scopes which are required for the replicator principal. If you remove the AU ID again or change it, the groups will not be removed from the old AU.", + Optional: true, + }, + "allow_hierarchical_management_group_assignment": schema.BoolAttribute{ + MarkdownDescription: "Configuration flag to enable or disable hierarchical management group assignment in Azure. If set to true: Subscriptions can be moved to child management groups of the management group defined in the Landing Zone. This is useful if you want to manage the subscription location with a deeper and more granular hierarchy. If set to false: Subscriptions will always be moved directly to the management group defined in the Landing Zone.", + Required: true, + }, + }, + } +} diff --git a/internal/provider/platform_resource_schema_gcp.go b/internal/provider/platform_resource_schema_gcp.go new file mode 100644 index 0000000..bca9856 --- /dev/null +++ b/internal/provider/platform_resource_schema_gcp.go @@ -0,0 +1,170 @@ +package provider + +import ( + "github.com/hashicorp/terraform-plugin-framework/resource/schema" +) + +func gcpPlatformSchema() schema.Attribute { + return schema.SingleNestedAttribute{ + MarkdownDescription: "Google Cloud Platform (GCP) platform configuration.", + Optional: true, + Attributes: map[string]schema.Attribute{ + "replication": gcpReplicationConfigSchema(), + "metering": gcpMeteringConfigSchema(), + }, + } +} + +func gcpReplicationConfigSchema() schema.Attribute { + return schema.SingleNestedAttribute{ + MarkdownDescription: "GCP-specific replication configuration for the platform.", + Optional: true, + Attributes: map[string]schema.Attribute{ + "service_account_config": gcpServiceAccountConfigSchema(), + "domain": schema.StringAttribute{ + MarkdownDescription: "The domain used for cloud identity directory-groups created and managed by meshStack. meshStack maintains separate groups for each meshProject role on each managed GCP project.", + Required: true, + }, + "customer_id": schema.StringAttribute{ + MarkdownDescription: "A Google Customer ID. It typically starts with a 'C'.", + Required: true, + }, + "group_name_pattern": schema.StringAttribute{ + MarkdownDescription: "All the commonly available replicator string template properties are available. Additionally you can also use 'platformGroupAlias' as a placeholder to access the specific project role from the role mappings done in this platform configuration or in the meshLandingZone configuration.", + Required: true, + }, + "project_name_pattern": schema.StringAttribute{ + MarkdownDescription: "All the commonly available replicator string template properties are available. The result must be 4 to 30 characters. Allowed characters are: lowercase and uppercase letters, numbers, hyphen, single-quote, double-quote, space, and exclamation point. When length restrictions are applied, the abbreviation will be in the middle and marked by a single-quote.", + Required: true, + }, + "project_id_pattern": schema.StringAttribute{ + MarkdownDescription: "All the commonly available replicator string template properties are available. The resulting string must not exceed a total length of 30 characters. Only alphanumeric + hyphen are allowed. We recommend that configuration include at least 3 characters of the random parameter to reduce the chance of naming collisions as the project Ids must be globally unique within GCP.", + Required: true, + }, + "billing_account_id": schema.StringAttribute{ + MarkdownDescription: "The ID of the billing account to associate with all GCP projects managed by meshStack", + Required: true, + }, + "user_lookup_strategy": schema.StringAttribute{ + MarkdownDescription: "Users can either be looked up by E-Mail or externalAccountId. This must also be the property that is placed in the external user id (EUID) of your meshUser entity to match. E-Mail is usually a good choice as this is often set up as the EUID throughout all cloud platforms and meshStack. ('email' or 'externalId')", + Required: true, + }, + "used_external_id_type": schema.StringAttribute{ + MarkdownDescription: "Used external ID type for user lookup", + Optional: true, + }, + "gcp_role_mappings": schema.ListNestedAttribute{ + MarkdownDescription: "Mapping of platform roles to GCP IAM roles.", + Required: true, + NestedObject: schema.NestedAttributeObject{ + Attributes: map[string]schema.Attribute{ + "project_role_ref": meshProjectRoleAttribute(false), + "gcp_role": schema.StringAttribute{ + MarkdownDescription: "The GCP IAM role", + Required: true, + }, + }, + }, + }, + "allow_hierarchical_folder_assignment": schema.BoolAttribute{ + MarkdownDescription: "Configuration flag to enable or disable hierarchical folder assignment in GCP. If set to true: Projects can be moved to sub folders of the folder defined in the Landing Zone. This is useful if you want to manage the project location with a deeper and more granular hierarchy. If set to false: Projects will always be moved directly to the folder defined in the Landing Zone.", + Required: true, + }, + "tenant_tags": schema.SingleNestedAttribute{ + MarkdownDescription: "Tenant tags configuration", + Optional: true, + Attributes: map[string]schema.Attribute{ + "namespace_prefix": schema.StringAttribute{ + MarkdownDescription: "Namespace prefix for tenant tags", + Required: true, + }, + "tag_mappers": schema.ListNestedAttribute{ + MarkdownDescription: "List of tag mappers for tenant tags", + Optional: true, + NestedObject: schema.NestedAttributeObject{ + Attributes: map[string]schema.Attribute{ + "key": schema.StringAttribute{ + MarkdownDescription: "Key for the tag mapper", + Required: true, + }, + "value_pattern": schema.StringAttribute{ + MarkdownDescription: "Value pattern for the tag mapper", + Required: true, + }, + }, + }, + }, + }, + }, + "skip_user_group_permission_cleanup": schema.BoolAttribute{ + MarkdownDescription: "For certain use cases you might want to preserve user groups and replicated permission after a tenant was deleted on the GCP platform. Checking this option preserves those permissions. Please keep in mind that the platform operator is then responsible for cleaning them up later.", + Required: true, + }, + }, + } +} + +func gcpServiceAccountConfigSchema() schema.Attribute { + return schema.SingleNestedAttribute{ + MarkdownDescription: "Service account configuration. Either `serviceAccountCredentialsConfig` or `serviceAccountWorkloadIdentityConfig` must be provided.", + Required: true, + Attributes: map[string]schema.Attribute{ + "service_account_credentials_config": schema.SingleNestedAttribute{ + MarkdownDescription: "Service account credentials configuration (alternative to serviceAccountWorkloadIdentityConfig)", + Optional: true, + Attributes: map[string]schema.Attribute{ + "service_account_credentials_b64": schema.StringAttribute{ + MarkdownDescription: "Base64 encoded credentials.json file for a GCP ServiceAccount. The replicator uses this Service Account to automate GCP API operations (IAM, ResourceManager etc.).", + Required: true, + Sensitive: true, + }, + }, + }, + "service_account_workload_identity_config": schema.SingleNestedAttribute{ + MarkdownDescription: "Service account workload identity configuration (alternative to serviceAccountCredentialsConfig)", + Optional: true, + Attributes: map[string]schema.Attribute{ + "audience": schema.StringAttribute{ + MarkdownDescription: "The audience associated with your workload identity pool provider.", + Required: true, + }, + "service_account_email": schema.StringAttribute{ + MarkdownDescription: "The email address of the Service Account, that gets impersonated for calling Google APIs via Workload Identity Federation.", + Required: true, + }, + }, + }, + }, + } +} + +func gcpMeteringConfigSchema() schema.Attribute { + return schema.SingleNestedAttribute{ + MarkdownDescription: "Metering configuration for GCP (optional, but required for metering)", + Optional: true, + Attributes: map[string]schema.Attribute{ + "service_account_config": gcpServiceAccountConfigSchema(), + "bigquery_table": schema.StringAttribute{ + MarkdownDescription: "BigQuery table for metering data.", + Required: true, + }, + "bigquery_table_for_carbon_footprint": schema.StringAttribute{ + MarkdownDescription: "BigQuery table for carbon footprint data.", + Optional: true, + }, + "carbon_footprint_data_collection_start_month": schema.StringAttribute{ + MarkdownDescription: "Start month for carbon footprint data collection.", + Optional: true, + }, + "partition_time_column": schema.StringAttribute{ + MarkdownDescription: "Partition time column for BigQuery table.", + Required: true, + }, + "additional_filter": schema.StringAttribute{ + MarkdownDescription: "Additional filter for metering data.", + Optional: true, + }, + "processing": meteringProcessingConfigSchema(), + }, + } +} diff --git a/internal/provider/platform_resource_schema_kubernetes.go b/internal/provider/platform_resource_schema_kubernetes.go new file mode 100644 index 0000000..5943cf0 --- /dev/null +++ b/internal/provider/platform_resource_schema_kubernetes.go @@ -0,0 +1,277 @@ +package provider + +import ( + "github.com/hashicorp/terraform-plugin-framework/resource/schema" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/booldefault" +) + +// Vanilla Kubernetes + +func kubernetesPlatformSchema() schema.Attribute { + return schema.SingleNestedAttribute{ + MarkdownDescription: "Kubernetes platform configuration.", + Optional: true, + Attributes: map[string]schema.Attribute{ + "base_url": schema.StringAttribute{ + MarkdownDescription: "This URL is the base URL to your Kubernetes Cluster, which is used to call the APIs to create new Kubernetes projects, get raw data for metering the Kubernetes projects, etc. An example base URL is: https://k8s.dev.eu-de-central.msh.host:6443", + Required: true, + }, + "disable_ssl_validation": schema.BoolAttribute{ + MarkdownDescription: "Flag to disable SSL validation for the Kubernetes cluster. SSL Validation should at best never be disabled, but for integration of some private cloud platforms in an early state, they might not yet be using valid SSL certificates. In that case it can make sense to disable SSL validation here to already test integration of these platforms.", + Optional: true, + Computed: true, + Default: booldefault.StaticBool(false), + }, + "replication": kubernetesReplicationConfigSchema(), + "metering": kubernetesMeteringConfigSchema(), + }, + } +} + +func kubernetesClientConfigSchema(description string) schema.Attribute { + return schema.SingleNestedAttribute{ + MarkdownDescription: description, + Required: true, + Attributes: map[string]schema.Attribute{ + "access_token": schema.StringAttribute{ + MarkdownDescription: "The Access Token of the service account for replicator access.", + Required: true, + Sensitive: true, + }, + }, + } +} + +func kubernetesReplicationConfigSchema() schema.Attribute { + return schema.SingleNestedAttribute{ + MarkdownDescription: "Replication configuration for Kubernetes (optional, but required for replication)", + Optional: true, + Attributes: map[string]schema.Attribute{ + "client_config": kubernetesClientConfigSchema("Client configuration for Kubernetes"), + "namespace_name_pattern": schema.StringAttribute{ + MarkdownDescription: "All the commonly available replicator string template properties are available. Kubernetes Namespace Names must be no longer than 63 characters, must start and end with a lowercase letter or number, and may contain lowercase letters, numbers, and hyphens.", + Required: true, + }, + }, + } +} + +func kubernetesMeteringConfigSchema() schema.Attribute { + return schema.SingleNestedAttribute{ + MarkdownDescription: "Metering configuration for Kubernetes (optional, but required for metering)", + Optional: true, + Attributes: map[string]schema.Attribute{ + "client_config": kubernetesClientConfigSchema("Client configuration for Kubernetes metering"), + "processing": meteringProcessingConfigSchema(), + }, + } +} + +// OpenShift (OKD) + +func openShiftPlatformSchema() schema.Attribute { + return schema.SingleNestedAttribute{ + MarkdownDescription: "OpenShift platform configuration.", + Optional: true, + Attributes: map[string]schema.Attribute{ + "base_url": schema.StringAttribute{ + MarkdownDescription: "This URL is the base URL to your OpenShift Cluster, which is used to call the APIs to create new OpenShift projects, get raw data for metering the OpenShift projects, etc. An example base URL is: https://api.okd4.dev.eu-de-central.msh.host:6443", + Required: true, + }, + "disable_ssl_validation": schema.BoolAttribute{ + MarkdownDescription: "Flag to disable SSL validation for the OpenShift cluster. SSL Validation should at best never be disabled, but for integration of some private cloud platforms in an early state, they might not yet be using valid SSL certificates. In that case it can make sense to disable SSL validation here to already test integration of these platforms.", + Optional: true, + Computed: true, + Default: booldefault.StaticBool(false), + }, + "replication": openShiftReplicationConfigSchema(), + "metering": openShiftMeteringConfigSchema(), + }, + } +} +func openShiftReplicationConfigSchema() schema.Attribute { + return schema.SingleNestedAttribute{ + MarkdownDescription: "Replication configuration for OpenShift (optional, but required for replication)", + Optional: true, + Attributes: map[string]schema.Attribute{ + "client_config": kubernetesClientConfigSchema("Client configuration for OpenShift"), + "web_console_url": schema.StringAttribute{ + MarkdownDescription: "The Web Console URL that is used to redirect the user to the cloud platform. An example Web Console URL is https://console-openshift-console.apps.okd4.dev.eu-de-central.msh.host", + Optional: true, + }, + "project_name_pattern": schema.StringAttribute{ + MarkdownDescription: "All the commonly available replicator string template properties are available. OpenShift Project Names must be no longer than 63 characters, must start and end with a lowercase letter or number, and may contain lowercase letters, numbers, and hyphens.", + Required: true, + }, + "enable_template_instantiation": schema.BoolAttribute{ + MarkdownDescription: "Here you can enable templates not only being rolled out to OpenShift but also instantiated during replication. Templates can be configured in meshLandingZones. Please keep in mind that the replication service account needs all the rights that are required to apply the templates that are configured in meshLandingZones.", + Required: true, + }, + "openshift_role_mappings": schema.ListNestedAttribute{ + MarkdownDescription: "OpenShift role mappings for OpenShift roles.", + Optional: true, + NestedObject: schema.NestedAttributeObject{ + Attributes: map[string]schema.Attribute{ + "project_role_ref": meshProjectRoleAttribute(false), + "openshift_role": schema.StringAttribute{ + MarkdownDescription: "The OpenShift role name", + Required: true, + }, + }, + }, + }, + "identity_provider_name": schema.StringAttribute{ + MarkdownDescription: "Identity provider name", + Required: true, + }, + "tenant_tags": schema.SingleNestedAttribute{ + MarkdownDescription: "Tenant tags configuration", + Optional: true, + Attributes: map[string]schema.Attribute{ + "namespace_prefix": schema.StringAttribute{ + MarkdownDescription: "This is the prefix for all labels created by meshStack. It helps to keep track of which labels are managed by meshStack. It is recommended to let this prefix end with a delimiter like an underscore.", + Required: true, + }, + "tag_mappers": schema.ListNestedAttribute{ + MarkdownDescription: "List of tag mappers for tenant tags", + Optional: true, + NestedObject: schema.NestedAttributeObject{ + Attributes: map[string]schema.Attribute{ + "key": schema.StringAttribute{ + MarkdownDescription: "Key for the tag mapper", + Required: true, + }, + "value_pattern": schema.StringAttribute{ + MarkdownDescription: "Value pattern for the tag mapper", + Required: true, + }, + }, + }, + }, + }, + }, + }, + } +} + +func openShiftMeteringConfigSchema() schema.Attribute { + return schema.SingleNestedAttribute{ + MarkdownDescription: "Metering configuration for OpenShift (optional, but required for metering)", + Optional: true, + Attributes: map[string]schema.Attribute{ + "client_config": kubernetesClientConfigSchema("Client configuration for OpenShift metering"), + "processing": meteringProcessingConfigSchema(), + }, + } +} + +// AKS + +func aksPlatformSchema() schema.Attribute { + return schema.SingleNestedAttribute{ + MarkdownDescription: "Azure Kubernetes Service configuration", + Optional: true, + Attributes: map[string]schema.Attribute{ + "base_url": schema.StringAttribute{ + MarkdownDescription: "Base URL of the AKS cluster", + Required: true, + }, + "disable_ssl_validation": schema.BoolAttribute{ + MarkdownDescription: "Flag to disable SSL validation for the AKS cluster. (SSL Validation should at best never be disabled, but for integration of some private cloud platforms in an early state, they might not yet be using valid SSL certificates. In that case it can make sense to disable SSL validation here to already test integration of these platforms.)", + Optional: true, + Computed: true, + Default: booldefault.StaticBool(false), + }, + "replication": aksReplicationConfigSchema(), + "metering": aksMeteringConfigSchema(), + }, + } +} + +func aksReplicationConfigSchema() schema.Attribute { + return schema.SingleNestedAttribute{ + MarkdownDescription: "Replication configuration for AKS (optional, but required for replication)", + Optional: true, + Attributes: map[string]schema.Attribute{ + "access_token": schema.StringAttribute{ + MarkdownDescription: "The Access Token of the service account for replicator access.", + Required: true, + Sensitive: true, + }, + "namespace_name_pattern": schema.StringAttribute{ + MarkdownDescription: "Pattern for naming namespaces in AKS", + Required: true, + }, + "group_name_pattern": schema.StringAttribute{ + MarkdownDescription: "Pattern for naming groups in AKS", + Required: true, + }, + "service_principal": schema.SingleNestedAttribute{ + MarkdownDescription: "Service principal configuration for AKS", + Required: true, + Attributes: map[string]schema.Attribute{ + "client_id": schema.StringAttribute{ + MarkdownDescription: "The Application (Client) ID. In Azure Portal, this is the Application ID of the 'Enterprise Application' but can also be retrieved via the 'App Registration' object as 'Application (Client) ID'.", + Required: true, + }, + "auth_type": schema.StringAttribute{ + MarkdownDescription: "Authentication type for the service principal (`CREDENTIALS` or `WORKLOAD_IDENTITY`)", + Required: true, + }, + "credentials_auth_client_secret": schema.StringAttribute{ + MarkdownDescription: "Client secret for the service principal (if `authType` is `CREDENTIALS`)", + Optional: true, + Sensitive: true, + }, + "entra_tenant": schema.StringAttribute{ + MarkdownDescription: "Domain name or ID of the Entra Tenant that holds the Service Principal.", + Required: true, + }, + "object_id": schema.StringAttribute{ + MarkdownDescription: "The Object ID of the Enterprise Application. You can get this Object ID via the API (e.g. when using our Terraform provider) or from Enterprise applications pane in Microsoft Entra admin center.", + Required: true, + }, + }, + }, + "aks_subscription_id": schema.StringAttribute{ + MarkdownDescription: "Subscription ID for the AKS cluster", + Required: true, + }, + "aks_cluster_name": schema.StringAttribute{ + MarkdownDescription: "Name of the AKS cluster.", + Required: true, + }, + "aks_resource_group": schema.StringAttribute{ + MarkdownDescription: "Resource group for the AKS cluster", + Required: true, + }, + "redirect_url": schema.StringAttribute{ + MarkdownDescription: "This is the URL that Azure's consent experience redirects users to after they accept their invitation.", + Optional: true, + }, + "send_azure_invitation_mail": schema.BoolAttribute{ + MarkdownDescription: "Flag to send Azure invitation emails. When true, meshStack instructs Azure to send out Invitation mails to invited users.", + Required: true, + }, + "user_look_up_strategy": schema.StringAttribute{ + MarkdownDescription: "Strategy for user lookup in Azure (`userPrincipalName` or `email`)", + Required: true, + }, + "administrative_unit_id": schema.StringAttribute{ + MarkdownDescription: "If you enter an administrative unit ID the replicated (and potentially existing) groups will be put into this AU. This can be used to limit the permission scopes which are required for the replicator principal. If you remove the AU ID again or change it, the groups will not be removed from the old AU.", + Optional: true, + }, + }, + } +} + +func aksMeteringConfigSchema() schema.Attribute { + return schema.SingleNestedAttribute{ + MarkdownDescription: "Metering configuration for AKS (optional, but required for metering)", + Optional: true, + Attributes: map[string]schema.Attribute{ + "client_config": kubernetesClientConfigSchema("Client configuration for AKS metering"), + "processing": meteringProcessingConfigSchema(), + }, + } +} diff --git a/internal/provider/schema_utils.go b/internal/provider/schema_utils.go index c1528a9..b3c4e3f 100644 --- a/internal/provider/schema_utils.go +++ b/internal/provider/schema_utils.go @@ -11,13 +11,14 @@ import ( // meshProjectRoleAttribute returns a schema attribute for meshProject role references. // This is used across multiple resources (landingzone, platform) to maintain consistency. -func meshProjectRoleAttribute() schema.SingleNestedAttribute { +func meshProjectRoleAttribute(computed bool) schema.SingleNestedAttribute { return schema.SingleNestedAttribute{ MarkdownDescription: "the meshProject role", Required: true, Attributes: map[string]schema.Attribute{ "name": schema.StringAttribute{ - Required: true, + Computed: computed, + Required: !computed, MarkdownDescription: "The identifier of the meshProjectRole", }, "kind": schema.StringAttribute{