Open amolari opened 2 years ago
Thanks for your request. We are now tracking this internally with ID ESECLDTPLT-3051.
Hi @amolari, this RFE is still in our backlog, but here are examples for all three clouds that will let you download and install AT packages from storage using IAM tokens with the current code:
# aws
controls:
logLevel: info
logFilename: /var/log/cloud/bigIpRuntimeInit.log
pre_onboard_enabled: []
runtime_parameters:
- name: INSTANCE_PROFILE
type: url
value: 'http://169.254.169.254/latest/meta-data/iam/security-credentials/'
- name: TEMPORARY_CREDENTIALS
type: url
value: 'http://169.254.169.254/latest/meta-data/iam/security-credentials/{{{INSTANCE_PROFILE}}}'
bigip_ready_enabled:
- name: download_packages
type: inline
commands:
- "date=\"`date +'%a, %d %b %Y %H:%M:%S %z'`\"; signature_string=\"GET\n\n\n${date}\nx-amz-security-token:{{{TEMPORARY_CREDENTIALS.Token}}}\n/<myBucketName>/<myKey>/f5-appsvcs-templates-1.16.0-1.noarch.rpm\"; signature=`/bin/echo -en \"${signature_string}\" | openssl sha1 -hmac {{{TEMPORARY_CREDENTIALS.SecretAccessKey}}} -binary | base64`; authorization=\"AWS {{{TEMPORARY_CREDENTIALS.AccessKeyId}}}:${signature}\"; curl -s -H \"Date: ${date}\" -H \"X-AMZ-Security-Token: {{{TEMPORARY_CREDENTIALS.Token}}}\" -H \"Authorization: ${authorization}\" \"https://<myBucketName>.s3.amazonaws.com/<myKey>/f5-appsvcs-templates-1.16.0-1.noarch.rpm\" -o /var/config/rest/downloads/f5-appsvcs-templates-1.16.0-1.noarch.rpm"
extension_packages:
install_operations:
- extensionType: fast
extensionVersion: 1.16.0
extensionUrl: file:///var/config/rest/downloads/f5-appsvcs-templates-1.16.0-1.noarch.rpm
post_onboard_enabled: []
# azure
controls:
logLevel: info
logFilename: /var/log/cloud/bigIpRuntimeInit.log
pre_onboard_enabled: []
runtime_parameters:
- name: ACCESS_TOKEN
type: url
query: access_token
value: 'http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https%3A%2F%2Fstorage.azure.com%2F'
headers:
- name: Metadata
value: true
- name: x-ms-version
value: '2017-11-09'
bigip_ready_enabled:
- name: download_packages
type: inline
commands:
- 'curl https://<myStorageAccountName>.blob.core.windows.net/<myContainerName>/f5-appsvcs-templates-1.16.0-1.noarch.rpm -o /var/config/rest/downloads/f5-appsvcs-templates-1.16.0-1.noarch.rpm -H "x-ms-version:2017-11-09" -H "Authorization: Bearer {{{ACCESS_TOKEN}}}"'
extension_packages:
install_operations:
- extensionType: fast
extensionVersion: 1.16.0
extensionUrl: file:///var/config/rest/downloads/f5-appsvcs-templates-1.16.0-1.noarch.rpm
post_onboard_enabled: []
# google
controls:
logLevel: info
logFilename: /var/log/cloud/bigIpRuntimeInit.log
pre_onboard_enabled: []
runtime_parameters:
- name: ACCESS_TOKEN
type: url
query: access_token
value: 'http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/<myServiceAccount>/token'
headers:
- name: Metadata-Flavor
value: Google
bigip_ready_enabled:
- name: download_packages
type: inline
commands:
- 'curl https://storage.googleapis.com/storage/v1/b/<myBucketName>/f5-appsvcs-templates-1.16.0-1.noarch.rpm -o /var/config/rest/downloads/f5-appsvcs-templates-1.16.0-1.noarch.rpm -H "Authorization: Bearer {{{ACCESS_TOKEN}}}"'
extension_packages:
install_operations:
- extensionType: fast
extensionVersion: 1.16.0
extensionUrl: file:///var/config/rest/downloads/f5-appsvcs-templates-1.16.0-1.noarch.rpm
post_onboard_enabled: []
@mikeshimkus About the GCP use-case I have the issue that the workaround cannot be directly used for the Vault secretProvider.
My declaration has:
- name: GLOBAL
type: secret
verifyTls: true
secretProvider:
type: Vault
environment: hashicorp
vaultServer: https://vault.xxxxx.com
appRolePath: /v1/namespace/auth/approle/login
secretsEngine: kv2
secretPath: namespace/secret/data/global
field: data
version: '1'
authBackend:
type: approle
roleId:
type: url
value: https://storage.googleapis.com/storage/v1/b/<myBucketName>/role-id_file
secretId:
type: inline
value: <secret_id>
unwrap: true
My buckets are not public => auth is required
The issue are in the roleId:
At this time my workaround is to fetch the file with curl (auth bearer) locally and point the url value to file:///
Hi @amolari, according to Vault best practices the role ID isn't considered sensitive, however it makes sense to limit its exposure. If it needs to be treated like a secret, you could store it in Google secrets manager, retrieve it using the secrets provider, and reference the returned value using the "inline" type for roleId instead of "url".
Another option would be to use the metadata runtime parameter time to retrieve it from instance metadata, also using the roleId inline type. Or you could bake it into the image as Hashicorp suggests and use the local file URL.
The internal issue we currently have is for securely downloading files to the device, we would need a new issue for extending that bucket authentication to HTTP requests made by other providers. I will chat with the product owners and report back here.
@amolari This could work as well:
controls:
logLevel: info
logFilename: /var/log/cloud/bigIpRuntimeInit.log
runtime_parameters:
- name: ACCESS_TOKEN
type: url
query: access_token
value: 'http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/<myServiceAccount>/token'
headers:
- name: Metadata-Flavor
value: Google
- name: ROLE_ID
type: url
value: 'https://storage.googleapis.com/storage/v1/b/<myBucketName>/role-id_file'
headers:
- name: Authorization
value: Bearer {{{ACCESS_TOKEN}}}
- name: GLOBAL
type: secret
verifyTls: true
secretProvider:
type: Vault
environment: hashicorp
vaultServer: https://vault.xxxxx.com
appRolePath: /v1/namespace/auth/approle/login
secretsEngine: kv2
secretPath: namespace/secret/data/global
field: data
version: '1'
authBackend:
type: approle
roleId:
type: inline
value: {{{ROLE_ID}}}
secretId:
type: inline
value: <secret_id>
unwrap: true
@mikeshimkus thank you for your answer. I've tested your proposed workaround and I see:
value: {{{ROLE_ID}}}
gives the error:
error: Invalid declaration: "data.runtime_parameters[2].secretProvider.authBackend.roleId.value should be string, data.runtime_parameters[2].secretProvider.authBackend.roleId.value should be string, data.runtime_parameters[2].secretProvider.authBackend.roleId should match \"then\" schemavalue: "{{{ROLE_ID}}}"
. However, it doesn't get the value => silly: Request response: 400 {"errors":["missing role_id"]}
To find out if this "chaining" of runtime_parameters works, I've set a troubleshooting command in the post_onboard_enabled such as
- name: troubleshoot
type: inline
commands:
- echo "ACCESS_TOKEN= {{{ ACCESS_TOKEN }}}"
- echo "ROLE_ID= {{{ ROLE_ID }}}"
the outputed values are correct.
My guess is that refering to another runtime_parameter is not working in the specific type=secret use-case. Is that the case? Thank you
It seems like runtime init only resolves parameters twice, not specifically related to the secret type. In this case it may require three rounds of parameter resolution.
Seems like implementing this as part of a secure downloader would be better, but need to examine that. If part of that were a built-in function to get IAM tokens, I think it would allow you to do this (but would need to be separate from downloader itself, since downloading to the device doesn't work for you).
The url type property (in runtime_parameters, extension_services, post_onboard_enables, pre_onboard_enable) results in a simple HTTP get request to fetch scripts, parameters or declarations. I'm asking for the possibility, in addition, to use the cloud-vendor (through its sdk) methods to fetch the refered objects.
Example: with AWS, have a s3 type property with the bucket+key information as parameters. The request to fetch the object will be executed with, for ex. the s3.getObject method.
Goal: be able to place those scripts, parameters or declarations on a bucket and comply to stricter enterprise policies, such as
With the actual code, AFAIK it's not possible to satisfy those requirements Note: I refer to AWS just because of my prio use-case. However, it makes sense to do the same for all cloud providers.