-
Notifications
You must be signed in to change notification settings - Fork 80
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
Azure keyvault secret datasource #89
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is looking nice! I miss the docs though. I see you generated the partials but they are not being used anywhere.
return (&DatasourceOutput{}).FlatMapstructure().HCL2Spec() | ||
} | ||
|
||
// We need to stub packersdk ui "say" function. UI is not available from this package, I guess this is the best we can do for now |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this sounds like something we need to think about 🤔 nice workaround though!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree with @sylviamoss that we need to think about the use of UI within datasources. But IMHO I don't think it is needed for this datasource.
The use of the say function is solely for displaying the debug like messages from the GetServicePrincipalTokens function which can add some additional noise to the output since datasources execute before an actual build.
For this case I would suggestion going with the logSay function but with a few small tweaks. Which will only show up when running a Packer build with the debug logs enabled PACKER_LOG=1 packer build template.pkr.hcl
.
func logSay(s string) {
log.Println("[DEBUG] packer-datasource-azure-keyvaultsecret:", s)
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
Hello, First of all, to avoid unnecessary code duplication for authentication, I reused some code from the builder (namely, You will also notice that I have not implemented any acceptance test for the datasource yet. I'm actually pretty confused about how it should work. I tried to look at the amazon plugin, and the acceptance seemingly requires credentials to pass. Can I get some guidance on how to implement this test? Thank you! |
Just added added a documentation page shamelessly inspired by the amazon one :) |
Hey @NicolasFloquet, thanks for working on this. Again, this is looking nice! You're right, the UI is not available to the Datasource and it should be. This will require some thinking to find the best approach to do it. The first thing it comes to my mind is that we are going to change the Datasource interface to let For the acceptance test, you can pass credentials via environment variables and document that these are needed in order to run the test. The amazon ones assume the credentials are set as env variables. Does that help you? Feel free to keep making any question you need 😃 |
Hello @sylviamoss, I think my pull request is ready for review now :) |
docs/datasources/index.mdx
Outdated
The Azure plugin is able to fetch data from Azure. To achieve this, the plugin comes with | ||
data sources to retrieve keyvault secrets. | ||
page_title: Azure - Data Sources | ||
sidebar_title: Overview |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sidebar_title works but is old, we are using nav_title now.
sidebar_title: Overview | |
nav_title: Overview |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
type=string | ||
} | ||
variable "client_id" { | ||
type=string |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think these can default to the environment, is easier to have them set already than setting the PKR_VAR_client_id. What do you think?
type=string | |
type=string | |
default = "${env("AZURE_CLIENT_ID")}" |
type=string | ||
} | ||
variable "client_secret" { | ||
type=string |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
type=string | |
type=string | |
default = "${env("AZURE_CLIENT_SECRET")}" |
type=string | ||
} | ||
variable "tenant_id" { | ||
type=string |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
type=string | |
type=string | |
default = "${env("AZURE_TENANT_ID")}" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is TENANT_ID still needed?
It has been removed from the other acceptance test as the ARM_SUBSCRIPTION_ID appears to be enough. But I'm not sure from the context of this change.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually at first I wanted to stay with subscription Id, but the acceptance test uses azure-sdk-for-go for secret creation/deletion, and as far as I know the SDK only works with tenant Id (https://docs.microsoft.com/en-us/azure/developer/go/azure-sdk-authorization#use-environment-based-authentication).
For simplicity purpose I also used tenant id in the template.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah okay I see. That is why os.Setenv("AZURE_AD_RESOURCE", "https://vault.azure.net")
is also needed. Thanks for the response here TIL.
client_id = "${var.client_id}" | ||
client_secret = "${var.client_secret}" | ||
tenant_id = "${var.tenant_id}" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can also just add a comment to this file telling that the AZURE_*
envs are necessary to be set. If so you can remove the variables and these three lines, as well as their reference in getAuthorizer()
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm assuming azure consumes the env variables by default like AWS does. I think it does because I run my azure builds like this 🤔
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried Azure builder with only AZURE_* environment variable and it didn't work, it actually falls back to managed identity authentication, which obviously cannot work on my computer.
I'm genuinely curious to know how it works for you!
Having the same behavior than AWS plugin would be great indeed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The builder is setup to use managed identity if the user does not explicitly set subscription_id, client_id, and client_secret. Which is not configured automatically when using the AZURE_* environment variables. We run our builds and tests with the following variables:
"variables": {
"client_id": "{{ env `ARM_CLIENT_ID` }}",
"client_secret": "{{ env `ARM_CLIENT_SECRET` }}",
"object_id": "{{ env `ARM_OBJECT_ID` }}",
"subscription_id": "{{ env `ARM_SUBSCRIPTION_ID` }}",
"tenant_id": "{{ env `ARM_TENANT_ID` }}",
"resource_group_name": "{{ env `ARM_RESOURCE_GROUP_NAME` }}",
"storage_account": "{{ env `ARM_STORAGE_ACCOUNT` }}"
},
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay, this is way clearer! I'll push a change match this setup then :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍 For the record this is an example in JSON. An HCL2 equivalent would be something like
variable "client_id" {
type = string
default = "${env("ARM_CLIENT_ID")}"
}
variable "client_secret" {
type = string
default = "${env("ARM_CLIENT_SECRET")}"
}
variable "object_id" {
type = string
default = "${env("ARM_OBJECT_ID")}"
}
variable "resource_group_name" {
type = string
default = "${env("ARM_RESOURCE_GROUP_NAME")}"
}
variable "storage_account" {
type = string
default = "${env("ARM_STORAGE_ACCOUNT")}"
}
variable "subscription_id" {
type = string
default = "${env("ARM_SUBSCRIPTION_ID")}"
}
variable "tenant_id" {
type = string
default = "${env("ARM_TENANT_ID")}"
}```
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@NicolasFloquet I agree with @sylviamoss this looks is looking good. I left a few additional suggestions and my thoughts on the logSay function workaround. I would like to pull this down and test as well. But at a glance it looks good.
|
||
func getAuthorizer() (autorest.Authorizer, error) { | ||
os.Setenv("AZURE_AD_RESOURCE", "https://vault.azure.net") | ||
os.Setenv("AZURE_TENANT_ID", os.Getenv("PKR_VAR_tenant_id")) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To simplify the acceptance testing setup the expected environment variables should be the same as expected by the current builder acceptance tests. This way you don't have to set anything, maybe other than the AZURE_AD_RESOURCE which looks like it can be a const for the test cases.
// * ARM_CLIENT_ID |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After your last comment about the AZURE_* variables I understand why you have this setup. Instead of PKR_VAR_* I recommend using the environment variables already required for the the acceptance tests. For example
os.Setenv("AZURE_TENANT_ID", os.Getenv("ARM_TENANT_ID"))
os.Setenv("AZURE_CLIENT_ID", os.Getenv("ARM_CLIENT_ID"))
...
I also recommend that a comment be added to the top of this file indicating which env variables are needed for the tests.
ContentType string | ||
Tags map[string]*string | ||
|
||
client keyvault.BaseClient |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: Run go fmt against the files to format the source.
type=string | ||
} | ||
variable "tenant_id" { | ||
type=string |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is TENANT_ID still needed?
It has been removed from the other acceptance test as the ARM_SUBSCRIPTION_ID appears to be enough. But I'm not sure from the context of this change.
return (&DatasourceOutput{}).FlatMapstructure().HCL2Spec() | ||
} | ||
|
||
// We need to stub packersdk ui "say" function. UI is not available from this package, I guess this is the best we can do for now |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree with @sylviamoss that we need to think about the use of UI within datasources. But IMHO I don't think it is needed for this datasource.
The use of the say function is solely for displaying the debug like messages from the GetServicePrincipalTokens function which can add some additional noise to the output since datasources execute before an actual build.
For this case I would suggestion going with the logSay function but with a few small tweaks. Which will only show up when running a Packer build with the debug logs enabled PACKER_LOG=1 packer build template.pkr.hcl
.
func logSay(s string) {
log.Println("[DEBUG] packer-datasource-azure-keyvaultsecret:", s)
}
Hello,
So this is a first implementation of a datasource for keyvault secrets.
Configuration requires a keyvault name (I used "keyvault_id" to stay consistent with terraform's azure-arm), and a secret name. Datasource use the same authentication parameters than the builder:
Example:
Output is also similar to what you get with terraform:
id
(string) - The Key Vault Secret ID.value
(string) - The value of the Key Vault Secret.content_type
(string) - The content type for the Key Vault Secret.tags
(map[string]*string) - Any tags assigned to this resource.Closes #83