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_container_app add support for key vault secret references as secret #23958

Closed
wants to merge 10 commits into from

Conversation

x-delfino
Copy link
Contributor

@x-delfino x-delfino commented Nov 19, 2023

Adding support for key vault references for container apps. Resolving #23668 and #21739. Introduces the following properties for secret blocks for azurerm_container_app resources:

  • identity
  • key_vault_url

Have included tests & docs and have run make pr-check - all tests are passing successfully.

I had to split out the Dapr secrets as they don't look to actually support these additional properties. I know that the API reference for Dapr components includes them, but the API doesn't actually support them as far as I can tell. Trying to use these values against the API results in: Secret with name 'secretName' cannot have have a null value. And including value just adds a normal secret.

I believe Dapr component key vault secret references are actually handled as follows:

  • Configure key vault secret store component as detailed here.
  • Reference these in the secretsRef metadata properties for another component as detailed here.

I can take a look at raising a separate PR for adding secret reference support for the Dapr components. Apologies this took a while, I got a bit thrown off by the Dapr bits and never got round into reading up on it properly - but I'm fairly confident in my conclusion

Copy link
Collaborator

@magodo magodo left a comment

Choose a reason for hiding this comment

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

Thanks for this PR!
I've taken a look through and left some comments inline, but this is mostly looking good to me 👍

internal/services/containerapps/helpers/container_apps.go Outdated Show resolved Hide resolved
internal/services/containerapps/helpers/container_apps.go Outdated Show resolved Hide resolved
internal/services/containerapps/helpers/container_apps.go Outdated Show resolved Hide resolved
website/docs/r/container_app.html.markdown Outdated Show resolved Hide resolved
internal/services/containerapps/helpers/container_apps.go Outdated Show resolved Hide resolved
internal/services/containerapps/helpers/container_apps.go Outdated Show resolved Hide resolved
}
secret {
name = "key-vault-secret"
identity = azurerm_user_assigned_identity.test.id
Copy link
Collaborator

Choose a reason for hiding this comment

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

Can we also test for the system assigned identity case?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

do we need this in a separate test or within the existing one?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Can be in the same test case, but in some separate steps, e.g. UAI -> UAI,SAI -> SAI, so that we can test out the update logic.

Copy link
Contributor Author

@x-delfino x-delfino Nov 23, 2023

Choose a reason for hiding this comment

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

i've added withKeyVaultSecretIdentityUpdate which does:

  • User Assigned
  • User Assigned & System Assigned
  • System Assigned

I've included the provisioning of the System Assigned identity within the User Assigned template (withKeyVaultSecretUserIdentity). This is as the API validates managed identity access to secrets when the container app is updated - so the identity and role assignment need to be created prior to the secret reference. I couldn't think of a cleaner way of doing this - any suggestions?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Typically, this requires a separate TF resource which extract these key vault parts out, e.g. https://github.com/hashicorp/terraform-provider-azurerm/blob/7596b072d0b8bf04585d0b77facd8296640d8a2a/internal/services/kusto/kusto_cluster_customer_managed_key_resource.go. In the container app case, there probably wants a azurerm_container_app_secret resource, which allows users to manage a secret at one time.

With above, users then are able to provision the resources in the following order: container app -> role assignment to the container app system assigned identity -> one or more container app secrets

Copy link
Contributor Author

Choose a reason for hiding this comment

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

okay cool i'll work on getting that created

@x-delfino
Copy link
Contributor Author

thanks for taking a look at this so quickly @magodo - will make the requested changes this evening

@x-delfino
Copy link
Contributor Author

I need to update the docs for the dapr secrets still

Copy link
Member

@jackofallops jackofallops left a comment

Choose a reason for hiding this comment

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

Hi @x-delfino - I've left a few comments in addition to the earlier review. If you can take a look at those, I'll continue review.

Thanks

}

func SecretsSchema() *pluginsdk.Schema {
return &pluginsdk.Schema{
Type: pluginsdk.TypeSet,
Type: pluginsdk.TypeList,
Copy link
Member

Choose a reason for hiding this comment

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

Unfortunately, this has to be a set as the API does not guarantee secret order on return, meaning that it can cause a diff in cases where there are 2 or more secrets.

Suggested change
Type: pluginsdk.TypeList,
Type: pluginsdk.TypeSet,

Copy link
Collaborator

Choose a reason for hiding this comment

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

I've checked with the service team about this, they told me:

Currently, it is ordered. But we recommend you not depend on the order.

Copy link
Member

Choose a reason for hiding this comment

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

I've checked with the service team about this, they told me:

Currently, it is ordered. But we recommend you not depend on the order.

@magodo - I tested this as part of the review, and the response is not ordered unfortunately I saw intermittent diffs on the responses. If it's supposed to be ordered per the service team, we should have an issue on the API specs to track this bug?

Copy link
Collaborator

Choose a reason for hiding this comment

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

From their response, the service team doesn't mean to guarantee the order as their goal, as they strongly recommend me not depend on the order..

Copy link
Contributor Author

Choose a reason for hiding this comment

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

apologies for delayed response. okay, my rudimentary testing was returning them in the same order but good to have clarification from the service team.

The issue is that the response includes the key vault secret value when key vault references are used. So we need to be able to ignore the secret value for secrets that use key vault references, but can't use ignore_changes on a list. I'm not sure of the best way to approach this. I think we could strip the secret value in FlattenContainerAppSecrets if a key vault reference is being used? Would that be an acceptable approach?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I've reverted to a set now. The secret value is not being stored when key vault references are used now (done in FlattenContainerAppSecrets). Is this an acceptable approach @jackofallops, @magodo?

internal/services/containerapps/helpers/container_apps.go Outdated Show resolved Hide resolved
Comment on lines 414 to 422
stateSecrets := stateSecretsRaw.(*schema.Set).List()
configSecrets := configSecretsRaw.(*schema.Set).List()
stateSecrets := stateSecretsRaw.([]interface{})
configSecrets := configSecretsRaw.([]interface{})
Copy link
Member

Choose a reason for hiding this comment

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

See below, this needs to remain a TypeSet unfortunately.

@davidkarlsen
Copy link
Contributor

@x-delfino Will you continue in this PR with the suggested changes?

@x-delfino
Copy link
Contributor Author

@x-delfino Will you continue in this PR with the suggested changes?

apologies, i've been away. I'll have time to work on this over the next couple of days

@davidkarlsen
Copy link
Contributor

Any more changes needed or is this ready for review and merge?

@@ -2214,17 +2218,33 @@ func SecretsSchema() *pluginsdk.Schema {
Sensitive: true,
Elem: &pluginsdk.Resource{
Schema: map[string]*pluginsdk.Schema{
"identity": {
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe you should use RequireWith and ConflictWith to not allow a user to fill in all 4 fields at once

Description: "The identity to use for accessing key vault reference.",
},

"key_vault_secret_id": {
Copy link
Contributor

Choose a reason for hiding this comment

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

Why not using key_vault_secret_url ? the value is an URL and not an identifier and keeping the same name everywhere may be better for understanding

commonids.ValidateUserAssignedIdentityID,
validation.StringInSlice([]string{"System"}, false),
),
Description: "The identity to use for accessing key vault reference.",
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
Description: "The identity to use for accessing key vault reference.",
Description: "Resource ID of a managed identity to authenticate with Azure Key Vault, or System to use a system-assigned identity.",

https://learn.microsoft.com/en-us/azure/templates/microsoft.app/containerapps?pivots=deployment-language-terraform#secret-2

Type: pluginsdk.TypeString,
Optional: true,
ValidateFunc: keyVaultValidate.NestedItemIdWithOptionalVersion,
Description: "The id of the key vault secret.",
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
Description: "The id of the key vault secret.",
Description: "Azure Key Vault URL pointing to the secret referenced by the container app.",

https://learn.microsoft.com/en-us/azure/templates/microsoft.app/containerapps?pivots=deployment-language-terraform#secret-2

"key_vault_secret_id": {
Type: pluginsdk.TypeString,
Computed: true,
Description: "The id of the key vault secret.",
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
Description: "The id of the key vault secret.",
Description: "Azure Key Vault URL pointing to the secret referenced by the container app.",

https://learn.microsoft.com/en-us/azure/templates/microsoft.app/containerapps?pivots=deployment-language-terraform#secret-2

"identity": {
Type: pluginsdk.TypeString,
Computed: true,
Description: "The identity to use for accessing key vault reference.",
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
Description: "The identity to use for accessing key vault reference.",
Description: "Resource ID of a managed identity to authenticate with Azure Key Vault, or System to use a system-assigned identity.",

https://learn.microsoft.com/en-us/azure/templates/microsoft.app/containerapps?pivots=deployment-language-terraform#secret-2

@@ -2257,21 +2289,36 @@ func SecretsDataSourceSchema() *pluginsdk.Schema {
}
}

func ExpandContainerSecrets(input []Secret) *[]containerapps.Secret {
func validateContainerSecret(s Secret) error {
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this useful if you use RequireWith and ConflictWith?

@eddy-vera
Copy link

@x-delfino: Do you know when you have time to continue this PR? Thanks in advance for your reply and work on this.

@x-delfino
Copy link
Contributor Author

unfortunately a few other commitments have taken priority and I'm not going to have time to give this attention for a couple of weeks realistically. If anyone has a bit more capacity to look at this in the meantime - feel free, otherwise I'll work on it when I have some time

@eddy-vera
Copy link

@x-delfino Any idea when you would have time to pick this up? Or are there others capable of doing this?

@GurliGebis
Copy link

@x-delfino Any idea when you would have time to pick this up? Or are there others capable of doing this?

Look at #24773

@stephybun
Copy link
Member

Thanks for all your effort on this @x-delfino!

Since you're unable to continue this in the near future and another PR has been opened building on the work done here, I'm going to close this so that the work and review effort can be consolidated in one PR.

For everyone interested in this feature please subscribe to #24773 for updates. Thanks!

@stephybun stephybun closed this Mar 5, 2024
Copy link

I'm going to lock this pull request because it has been closed for 30 days ⏳. This helps our maintainers find and focus on the active contributions.
If you have found a problem that seems related to this change, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Apr 19, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
8 participants