Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

azurerm_spring_cloud_connection, azurerm_app_service_connection: Add support for secret_store #20613

Merged
merged 1 commit into from
Feb 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions internal/services/serviceconnector/helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,27 @@ type AuthInfoModel struct {
Certificate string `tfschema:"certificate"`
}

type SecretStoreModel struct {
KeyVaultId string `tfschema:"key_vault_id"`
}

func secretStoreSchema() *pluginsdk.Schema {
return &pluginsdk.Schema{
Type: pluginsdk.TypeList,
Optional: true,
MaxItems: 1,
Elem: &pluginsdk.Resource{
Schema: map[string]*schema.Schema{
"key_vault_id": {
Type: pluginsdk.TypeString,
Required: true,
ValidateFunc: validation.StringIsNotEmpty,
},
},
},
}
}

func authInfoSchema() *pluginsdk.Schema {
return &pluginsdk.Schema{
Type: pluginsdk.TypeList,
Expand Down Expand Up @@ -83,6 +104,18 @@ func authInfoSchema() *pluginsdk.Schema {
}
}

func expandSecretStore(input []SecretStoreModel) *servicelinker.SecretStore {
if len(input) == 0 {
return nil
}
v := input[0]

keyVaultId := v.KeyVaultId
return &servicelinker.SecretStore{
KeyVaultId: utils.String(keyVaultId),
}
}

func expandServiceConnectorAuthInfo(input []AuthInfoModel) (servicelinker.AuthInfoBase, error) {
if len(input) == 0 {
return nil, fmt.Errorf("authentication should be defined")
Expand Down Expand Up @@ -286,3 +319,16 @@ func flattenTargetService(input servicelinker.TargetServiceBase) string {

return targetServiceId
}

func flattenSecretStore(input servicelinker.SecretStore) []SecretStoreModel {
var keyVaultId string
if input.KeyVaultId != nil {
keyVaultId = *input.KeyVaultId
}

return []SecretStoreModel{
{
KeyVaultId: keyVaultId,
},
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,13 @@ import (
type AppServiceConnectorResource struct{}

type AppServiceConnectorResourceModel struct {
Name string `tfschema:"name"`
AppServiceId string `tfschema:"app_service_id"`
TargetResourceId string `tfschema:"target_resource_id"`
ClientType string `tfschema:"client_type"`
AuthInfo []AuthInfoModel `tfschema:"authentication"`
VnetSolution string `tfschema:"vnet_solution"`
Name string `tfschema:"name"`
AppServiceId string `tfschema:"app_service_id"`
TargetResourceId string `tfschema:"target_resource_id"`
ClientType string `tfschema:"client_type"`
AuthInfo []AuthInfoModel `tfschema:"authentication"`
VnetSolution string `tfschema:"vnet_solution"`
SecretStore []SecretStoreModel `tfschema:"secret_store"`
}

func (r AppServiceConnectorResource) Arguments() map[string]*schema.Schema {
Expand Down Expand Up @@ -70,6 +71,8 @@ func (r AppServiceConnectorResource) Arguments() map[string]*schema.Schema {
}, false),
},

"secret_store": secretStoreSchema(),

"vnet_solution": {
Type: pluginsdk.TypeString,
Optional: true,
Expand Down Expand Up @@ -136,6 +139,11 @@ func (r AppServiceConnectorResource) Create() sdk.ResourceFunc {
}
}

if model.SecretStore != nil {
secretStore := expandSecretStore(model.SecretStore)
serviceConnectorProperties.SecretStore = secretStore
}

if model.ClientType != "" {
clientType := servicelinker.ClientType(model.ClientType)
serviceConnectorProperties.ClientType = &clientType
Expand Down Expand Up @@ -206,6 +214,10 @@ func (r AppServiceConnectorResource) Read() sdk.ResourceFunc {
state.VnetSolution = string(*props.VNetSolution.Type)
}

if props.SecretStore != nil {
state.SecretStore = flattenSecretStore(*props.SecretStore)
}

return metadata.Encode(&state)
}
return nil
Expand Down Expand Up @@ -265,6 +277,10 @@ func (r AppServiceConnectorResource) Update() sdk.ResourceFunc {
linkerProps.VNetSolution = &vnetSolution
}

if d.HasChange("secret_store") {
linkerProps.SecretStore = (*links.SecretStore)(expandSecretStore(state.SecretStore))
}

if d.HasChange("authentication") {
linkerProps.AuthInfo = state.AuthInfo
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,21 @@ func TestAccServiceConnectorAppServiceStorageBlob_basic(t *testing.T) {
})
}

func TestAccServiceConnectorAppServiceStorageBlob_secretStore(t *testing.T) {
data := acceptance.BuildTestData(t, "azurerm_app_service_connection", "test")
r := ServiceConnectorAppServiceResource{}

data.ResourceTest(t, r, []acceptance.TestStep{
{
Config: r.secretStore(data),
Check: acceptance.ComposeTestCheckFunc(
check.That(data.ResourceName).ExistsInAzure(r),
),
},
data.ImportStep(),
})
}

func TestAccServiceConnectorAppServiceCosmosdb_update(t *testing.T) {
data := acceptance.BuildTestData(t, "azurerm_app_service_connection", "test")
r := ServiceConnectorAppServiceResource{}
Expand Down Expand Up @@ -200,6 +215,107 @@ resource "azurerm_app_service_connection" "test" {
`, template, data.RandomString, data.RandomInteger)
}

func (r ServiceConnectorAppServiceResource) secretStore(data acceptance.TestData) string {
return fmt.Sprintf(`
provider "azurerm" {
features {
key_vault {
recover_soft_deleted_key_vaults = false
purge_soft_delete_on_destroy = false
purge_soft_deleted_keys_on_destroy = false
}
}
}

data "azurerm_client_config" "current" {}

resource "azurerm_resource_group" "test" {
name = "acctestRG-%[2]d"
location = "%[1]s"
}

resource "azurerm_storage_account" "test" {
name = "acctestacc%[4]s"
resource_group_name = azurerm_resource_group.test.name
location = azurerm_resource_group.test.location
account_tier = "Standard"
account_replication_type = "LRS"
}

resource "azurerm_service_plan" "test" {
name = "acctestASP-%[2]d"
location = azurerm_resource_group.test.location
resource_group_name = azurerm_resource_group.test.name
os_type = "Linux"
sku_name = "P1v2"
}

resource "azurerm_virtual_network" "test" {
name = "vnet-%[3]d"
address_space = ["10.0.0.0/16"]
location = azurerm_resource_group.test.location
resource_group_name = azurerm_resource_group.test.name
}

resource "azurerm_subnet" "test1" {
name = "subnet1"
resource_group_name = azurerm_resource_group.test.name
virtual_network_name = azurerm_virtual_network.test.name
address_prefixes = ["10.0.1.0/24"]
private_endpoint_network_policies_enabled = true

delegation {
name = "delegation"

service_delegation {
name = "Microsoft.Web/serverFarms"
actions = ["Microsoft.Network/virtualNetworks/subnets/action"]
}
}
}


resource "azurerm_linux_web_app" "test" {
name = "acctestWA-%[3]d"
location = azurerm_resource_group.test.location
resource_group_name = azurerm_resource_group.test.name
service_plan_id = azurerm_service_plan.test.id
virtual_network_subnet_id = azurerm_subnet.test1.id

site_config {}
lifecycle {
ignore_changes = [
app_settings["AZURE_STORAGEBLOB_RESOURCEENDPOINT"],
identity,
]
}
}

resource "azurerm_key_vault" "test" {
name = "accAKV-%[4]s"
location = azurerm_resource_group.test.location
resource_group_name = azurerm_resource_group.test.name
tenant_id = data.azurerm_client_config.current.tenant_id
sku_name = "standard"
purge_protection_enabled = true
}

resource "azurerm_app_service_connection" "test" {
name = "acctestserviceconnector%[3]d"
app_service_id = azurerm_linux_web_app.test.id
target_resource_id = azurerm_storage_account.test.id
client_type = "java"

secret_store {
key_vault_id = azurerm_key_vault.test.id
}
authentication {
type = "systemAssignedIdentity"
}
}
`, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomString)
}

func (r ServiceConnectorAppServiceResource) complete(data acceptance.TestData) string {
return fmt.Sprintf(`
provider "azurerm" {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,13 @@ import (
type SpringCloudConnectorResource struct{}

type SpringCloudConnectorResourceModel struct {
Name string `tfschema:"name"`
SpringCloudId string `tfschema:"spring_cloud_id"`
TargetResourceId string `tfschema:"target_resource_id"`
ClientType string `tfschema:"client_type"`
AuthInfo []AuthInfoModel `tfschema:"authentication"`
VnetSolution string `tfschema:"vnet_solution"`
Name string `tfschema:"name"`
SpringCloudId string `tfschema:"spring_cloud_id"`
TargetResourceId string `tfschema:"target_resource_id"`
ClientType string `tfschema:"client_type"`
AuthInfo []AuthInfoModel `tfschema:"authentication"`
VnetSolution string `tfschema:"vnet_solution"`
SecretStore []SecretStoreModel `tfschema:"secret_store"`
}

func (r SpringCloudConnectorResource) Arguments() map[string]*schema.Schema {
Expand Down Expand Up @@ -72,6 +73,8 @@ func (r SpringCloudConnectorResource) Arguments() map[string]*schema.Schema {
}, false),
},

"secret_store": secretStoreSchema(),

"vnet_solution": {
Type: pluginsdk.TypeString,
Optional: true,
Expand Down Expand Up @@ -138,6 +141,11 @@ func (r SpringCloudConnectorResource) Create() sdk.ResourceFunc {
}
}

if model.SecretStore != nil {
secretStore := expandSecretStore(model.SecretStore)
serviceConnectorProperties.SecretStore = secretStore
}

if model.ClientType != "" {
clientType := servicelinker.ClientType(model.ClientType)
serviceConnectorProperties.ClientType = &clientType
Expand Down Expand Up @@ -207,6 +215,10 @@ func (r SpringCloudConnectorResource) Read() sdk.ResourceFunc {
state.VnetSolution = string(*props.VNetSolution.Type)
}

if props.SecretStore != nil {
state.SecretStore = flattenSecretStore(*props.SecretStore)
}

return metadata.Encode(&state)
}
return nil
Expand Down Expand Up @@ -266,6 +278,10 @@ func (r SpringCloudConnectorResource) Update() sdk.ResourceFunc {
linkerProps.VNetSolution = &vnetSolution
}

if d.HasChange("secret_store") {
linkerProps.SecretStore = (*links.SecretStore)(expandSecretStore(state.SecretStore))
}

if d.HasChange("authentication") {
linkerProps.AuthInfo = state.AuthInfo
}
Expand Down
Loading