Pulumi Azure: get keyvault key version - pulumi

I want to use customer managed key for the sql server. For that I need to load the key from the keyvault but I cannot get the version of the key, which is required according to the pulumi documentation:
:param pulumi.Input[str] key_name: The name of the server key to be
operated on (updated or created). The key name is required to be in
the format of 'vault_key_version'. For example, if the keyId is
https://YourVaultName.vault.azure.net/keys/YourKeyName/YourKeyVersion,
then the server key name should be formatted as:
YourVaultName_YourKeyName_YourKeyVersion
Relevant code:
def create_tde_key(self, key: keyvault.Key, vault_name: str):
key_name = "{}_{}_{}".format(vault_name, key.name, key.version ) // here I need the version but there is only key.key_uri_with_version
tde_key = sql.ServerKey('tde-key-' + self.location_flag,
key_name = key_name,
resource_group_name = self.resource_group_name,
server_name = self.sql_server,
server_key_type = sql.ServerKeyType.AZURE_KEY_VAULT,
uri = key.key_uri_with_version
)
tried to disassemble key.key_uri_with_version this way:
key_version = key.key_uri_with_version[key.key_uri_with_version.rfind('/') + 1:]
but then I got TypeError: 'Output' object is not callable
I tried to use lambdas to get the string Output from key.key_uri_with_version but got the same TypeError as before.
I tried hardcoding the version and it is working so somehow I need to get the keyversion.
Any idea what should I do?

Related

ExtendedPropertyDefinition declaration for EmailMessage in Powershell throws exception

since I got to know that ExtendedProperties have its limit for a specific mailbox in the EWS cloud I am trying to switch up my code to have only one ExtendedProperty and just change its value each time I am assigning the property to an e-mail message I am sending to then find it and work on the e-mail message object later on in the program.
I am having a hard time setting this up correctly even though I am following the docs, but it just seems to not work out for me.
This is the code part that throws an Exception: "Multiple ambigious overloads found for "ExtendedPropertyDefinition" and the argument count "3" :
# email declaration exposing the $email object
.
.
.
# property declaration and setting the value
# since I want to have only one extended property, this is actually a valid GUID string that I then # convert to a Guid type
$GUIDproperty = "00000000-0000-0000-0000-000000000000"
$propertyGUID = [Guid]$GUIDproperty
# since I want to have a unique value each time set to the existing extended property
$propertyValue = [guid]::NewGuid().ToString()
$propertyName = "Id"
$ExtendedProperty = [Microsoft.Exchange.WebServices.Data.ExtendedPropertyDefinition]::new($propertyGUID, $propertyName, $propertyType)
# well I dont even reach this part, but just for the big picture
$email.SetExtendedProperty($ExtendedProperty, $propertyValue)
The docs I have followed for that are the following:
https://learn.microsoft.com/en-us/dotnet/api/microsoft.exchange.webservices.data.extendedpropertydefinition.-ctor?view=exchange-ews-api#microsoft-exchange-webservices-data-extendedpropertydefinition-ctor(microsoft-exchange-webservices-data-defaultextendedpropertyset-system-string-microsoft-exchange-webservices-data-mapipropertytype)
https://learn.microsoft.com/en-us/dotnet/api/microsoft.exchange.webservices.data.folder.setextendedproperty?redirectedfrom=MSDN&view=exchange-ews-api#Microsoft_Exchange_WebServices_Data_Folder_SetExtendedProperty_Microsoft_Exchange_WebServices_Data_ExtendedPropertyDefinition_System_Object_
https://learn.microsoft.com/en-us/dotnet/api/system.guid?view=net-7.0
The following works okay for me
$propertyType = [Microsoft.Exchange.WebServices.Data.MapiPropertyType]::String
$GUIDproperty = "82e3d64f-e26d-4321-8fc3-c31aa790197c"
$propertyGUID = [Guid]$GUIDproperty
$propertyValue = [guid]::NewGuid().ToString()
$propertyName = "MyPropId"
$ExtendedProperty = [Microsoft.Exchange.WebServices.Data.ExtendedPropertyDefinition]::new($propertyGUID, $propertyName, $propertyType)
return $ExtendedProperty
You don't specify what you using in the $propertyType so that maybe it, could also be to do with the versions you using. What version of PowerShell and the EWS Managed API are you trying ?

Accidentally URL Encoding URI Twice, Invalid Signature Response

I'll try to explain this best I can. I'm trying to perform a simple GET against the NetSuite "employees" API (using PowerShell). As you can see in the $query below, this variable needs to be URL encoded (spaces in the query) which I am doing on line 20 of the below snippet. I'm then taking that encoded URL along with a couple other variables and building the $base_string. I use the $base_string to create the Base64 OAuth signature and, on line 36, URL encode the signature. My response from NetSuite is always Invalid Signature.
When I perform any sort of "standard" query (like the one immediately below, without spaces... meaning no changes to the URL after encoding) I do not get an Invalid Signature response. This leads me to believe the problem is entirely related to the more unique query I am attempting and, possibly, the fact that it is being "double-encoded."
I'd appreciate any feedback as I would really benefit from being able to perform a query against the "custentity" variable in the below snippet.
$query = "/services/rest/record/v1/employee/$($netsuite_id)" # This query will find a user via their NetSuite ID.
$url = "https://$($realm.ToLower().Replace("_","-")).suitetalk.api.netsuite.com"
$query = "/services/rest/record/v1/employee?q=custentity_coupa_emp_id IS $($employee_id)" # This query will find a user via a custom entity --- their Coupa ID.
$oauth_nonce = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes([System.DateTime]::Now.Ticks.ToString()))
$oauth_timestamp = [int64](([datetime]::UtcNow)-(Get-Date "1970-01-01")).TotalSeconds
# BUILD THE BASE STRING VARIABLE
$oAuthParamsForSigning = #{}
$oAuthParamsForSigning.Add("oauth_consumer_key",$oauth_consumer_key)
$oAuthParamsForSigning.Add("oauth_token",$oauth_token)
$oAuthParamsForSigning.Add("oauth_signature_method",$oauth_signature_method)
$oAuthParamsForSigning.Add("oauth_nonce",$oauth_nonce)
$oAuthParamsForSigning.Add("oauth_timestamp",$oauth_timestamp)
$oAuthParamsForSigning.Add("oauth_version",$oauth_version)
$oAuthParamsString = ($oAuthParamsForSigning.Keys | Sort-Object | % {
"$_=$($oAuthParamsForSigning[$_])"
}) -join "&"
$encodedOAuthParamsString = [uri]::EscapeDataString($oAuthParamsString)
# BUILD THE ENCODED FULL URL VARIABLE
$encodedUrl = [uri]::EscapeDataString($url+$query)
# BUILD THE OAUTH SIGNATURE VARIABLE: KEY (CONSUMER SECRET + TOKEN SECRET) + BASE STRING
$base_string = $HTTP_method + "&" + $encodedUrl + "&" + $encodedOAuthParamsString
$key = $oauth_consumer_secret + "&" + $oauth_token_secret
$hmacsha256 = New-Object System.Security.Cryptography.HMACSHA256
$hmacsha256.Key = [System.Text.Encoding]::ASCII.GetBytes($key)
$oauth_signature = [System.Convert]::ToBase64String($hmacsha256.ComputeHash([System.Text.Encoding]::ASCII.GetBytes($base_string)))
# BUILD THE HEADERS VARIABLE
$authHeaderString = ($oAuthParamsForSigning.Keys | Sort-Object | % {
"$_=`"$([uri]::EscapeDataString($oAuthParamsForSigning[$_]))`""
}) -join ","
$authHeaderString += ",realm=`"$([uri]::EscapeDataString($realm))`""
$authHeaderString += ",oauth_signature=`"$([uri]::EscapeDataString($oauth_signature))`""
$authHeaders = #{
"Content-Type"="application/json"
;"Prefer"="transient"
;"Authorization"="OAuth $authHeaderString"
;"Accept"="*/*"
;"Cache-Control"="no-cache"
;"Host"="3489459-sb1.suitetalk.api.netsuite.com"
;"Accept-Encoding"="gzip, deflate, br"
;"Cookie"="NS_ROUTING_VERSION=LAGGING"
}
I have no background with PowerShell but I've had this issue previously with Python and it's tricky without using libraries. I found out that:
Your Base URL cannot contain query params. Meaning your base url should be:
"https://$($realm.ToLower().Replace("_","-")).suitetalk.api.netsuite.com/services/rest/record/v1/employee"
Since you're only doing GET request, just throw your query into a payload (JSON formatted). At least with my SuiteQL this is how I did it. Moving the query to payload worked for me.
For POST Request, the parameters will need to be included in the Base String Creation, sorted alphabetically or by value if keys are the same name.
My query for example for SuiteQL was query = json.dumps({ q: SELECT FROM WHERE })

Azure Data Factory Rest API - With AccountCode, APIKey & Token

I have a use case wherein, I need to connect to an API for data request.
The API requires a valid token to process the requests.
To generate the token, I have a accountCode & secret key
Assume BaseURL as
BaseURL - http://api.xxxxx.com/{accountCode}/data (Value of account needs to be passed)
**Below script in Python/Java needs to be run to fetch the dateToken & token
If we use Python 3.6 or above. Below is the code -**
--START-- {
import time
import requests
from hashlib import md5
account_code = "<account_name>"
key = "<api_key>"
actual_unix_time = int(time.time_ns() / 1000) # in milliseconds
TTL = 31536000000 # for 1 year
expiration_time = actual_unix_time + TTL
base_url = "https://api.xxxxx.com"
url = f"/{account_code}/data?fromDate=last6Hours&granularity=minute&type=ALL%2CVOD%2CLIVE&operation=reduceJoin&metrics=bufferratio"
pre_url = f"{url}&dateToken={expiration_time}"
token_generated = md5(f"{pre_url}{key}".encode('utf-8'))
token_value = token_generated.hexdigest()
request_url = f"{base_url}{pre_url}&token={token_value}"
response = requests.get(request_url)
print(response)
print(response.text)
} --END--
- If we use Java. Below is the code -
--START-- {
var key = pm.environment.get("NPAW-API-KEY");
var base_url = "https://api.xxxxx.com";
var url = pm.request.url.toString();
var path = url.replace(base_url, '');
var pre_url = pm.variables.replaceIn(path);
var moment = require('moment');
var actual_unix_time = moment().unix()*1000;
var TTL = 31536000000
var expiration_time = (actual_unix_time + TTL);
var pre_url = pre_url+"&dateToken="+expiration_time;
var token_generated = CryptoJS.MD5(pre_url + key).toString();
var token_value = token_generated;
var request_url = (base_url+pre_url+'&token='+token_value).toString();
}--END--
Example of how the final URL - https://api.xxxxx.com/kb-vivek/data?fromDate=today&granularity=hour&type=ALL,VOD,LIVE&operation=reduceJoin&metrics=views,playtime&dateToken=1699016056000&token=7a9c97a4d4f108d1d32be2f7f8d00731
I tried to use Postman, wherein, I could pass the above script in the Pre-Request script and set environment variables for accountCode & Secret Key and I was able to achieve the result as desired.
Question: How can I achieve this in Azure Data Factory?
To achieve the requirement, we need to use a combination of set variables and dataflows (to generate md5 hex string and store final url in a file).
First, I have created 4 parameters with values as shown below:
base_url: https://api.xxxxx.com
account_code: <account_name>
key: <api_key>
TTL: 31536000000
First, I have created a variable to build url. I used the following dynamic content:
/#{pipeline().parameters.account_code}/data?fromDate=last6Hours&granularity=minute&type=ALL%2CVOD%2CLIVE&operation=reduceJoin&metrics=bufferratio
Next, I have built the pre_url with the following dynamic content:
#{variables('url')}&dateToken=#{add(div(sub(ticks(utcNow()), ticks('1970-01-01')),10),31536000000)}
Now, to encode the string and convert it to md5 hex string, I have used dataflow. I have passed base_url, pre_url and key to the dataflow from the pipeline.
I have taken a sample csv file with only one row from blob storage (the data in this file does not matter but make sure it has 1 row only).
I have created a derived column to create final URL by concatenating base_url, pre_url and encoded md5 hex string. Use the following content:
$base_url+$pre_url+'&token='+md5(encode(concat($pre_url,$key)))
Now I am writing this data to a file by using output to single file option in the sink settings.
When I debug the pipeline, the file will be written to my storage account. The contents of the file will be as shown below:
NOTE:
Now since you want to generate date token once and use it for a year, I have written the data to a file.
You run this pipeline once and generate a file with required URL (as above). Anytime you want to access this URL, you can use look up activity to access the URL anywhere required.
I have used utcNow() to generate dateToken. But if you have any specific date in mind, you can simply use that in the correct format (in place of utcNow()).

Terraform: getting project id from azuredevops_project resource. Error data.azuredevops_projects.projectname.projects is set of object with 1 element

I am trying to access azuredevops project from terraform using azuredevops_devops resource. Using that project, I want to access repositories and create a new repo. But I am getting error in the second data block where I try to assign to project_id, but the output block prints the correct details.
data "azuredevops_projects" "sampleproject"{
name = "sample"
}
output "projectdetails"{
value = [for obj in data.azuredevops_projects.sampleproject.projects : obj.name]
}
error I receive here is: Incorrect attribute value type.data.azuredevops_projects.sampleproject.projects is set of object with 1 element :
data "azuredevops_git_repository" "samplerepo"{
project_id = [for obj in data.azuredevops_projects.sampleproject.projects : obj.name]
name = "Services-Template"
}
I am new to terraform, just practicing this for learning purpose.
Thanks for your answers, I tried everything but the below solution worked
initial outcome:
+ projectdetails = [
+ "74899dhjhjk-8909-4a97-9e9b-73488hfjikjd9",
]
outcoume after below solution:
element(data.azuredevops_projects.sampleproject.projects.*.project_id,0)
"74899dhjhjk-8909-4a97-9e9b-73488hfjikjd9"

How do I set multiple AppSettings values using xWebConfigKeyValue?

I'm trying to use the xWebConfigKeyValue resource of the DSC module xWebAdministration to set multiple values on our application's web.config file. This is an excerpt from our configuration with the main activities surrounding the web.config changes:
Configuration C4M
{
Param(
[Parameter(Mandatory)]
[string] $BuildDropLocation
)
Import-DscResource -Module xWebAdministration
Node $AllNodes.NodeName
{
$managementPortalInstallPath = 'c:\Company\ManagementPortal'
File ManagementPortalContents
{
DestinationPath = $managementPortalInstallPath
SourcePath = "$BuildDropLocation\ManagementPortal"
Type = 'Directory'
Recurse = $True
}
xWebConfigKeyValue RecaptchaPublicKey
{
WebsitePath = $managementPortalInstallPath
ConfigSection = 'AppSettings'
Key = 'recaptchaPublicKey'
Value = $Node.RecaptchaPublicKey
DependsOn = '[File]ManagementPortalContents'
}
xWebConfigKeyValue RecaptchaPrivateKey
{
WebsitePath = $managementPortalInstallPath
ConfigSection = 'AppSettings'
Key = 'recaptchaPrivateKey'
Value = $Node.RecaptchaPrivateKey
DependsOn = '[File]ManagementPortalContents'
}
}
}
But when I try to run the configuration, I get the following error:
Add-NodeKeys : The key properties combination
'C:\Company\ManagementPortal::AppSettings' is duplicated for keys
'WebsitePath,ConfigSection' of resource 'xWebConfigKeyValue' in node
'myNode'. Please make sure key properties are unique for each
resource in a node. At line:160 char:9
+ Add-NodeKeys $keyValues $keyNames $keywordName
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [Write-Error], InvalidOperationException
+ FullyQualifiedErrorId : DuplicateKeyInNode,Add-NodeKeys
After seeing the error, I took a look at the modules schema.mof file, and noticed that the appSettings key is not a key to the configuration at C:\Program Files\WindowsPowerShell\Modules\xWebAdministration\DSCResources\MSFT_xWebConfigKeyValue\MSFT_xWebConfigKeyValue.schema.mof:
[ClassVersion("1.0.0.0"), FriendlyName("xWebConfigKeyValue")]
class MSFT_xWebConfigKeyValue : OMI_BaseResource
{
[Key, Description("Path to website location(IIS or WebAdministration format)")] String WebsitePath;
[Key, Description("Config Section to be update"), ValueMap{"AppSettings"}, Values{"AppSettings"}] String ConfigSection;
[Write, ValueMap{"Present","Absent"}, Values{"Present","Absent"}] String Ensure;
[Required, Description("Key for AppSettings")] String Key;
[Write, Description("Value for AppSettings")] String Value;
[Write, Description("If the given key value pair is for attribute, default is element")] Boolean IsAttribute;
};
Since only the site path and config section are keys, I can't have multiple instances of the resource pointing to the same appSettings block but with different appSetting keys. How can I configure multiple appSetting keys then?
You can't configure two xWebConfigKeyValue resources in the same Configuration because, as you've found, the resource key only contains the WebsitePath and ConfigSection properties and doesn't discriminate on the Key property.
I think your immediate options are:
Create a new cWebConfigKeyValue resource module based on xWebConfigKeyValue, and add the "Key" attribute to the "Key" property in the "cWebConfigKeyValue.schema.mof" to fix it yourself.
or
Define the clashing resources in separate Configuration blocks. I've had to do this in a project that uses the xService resource.
Neither of these is a particularly good solution, but it might unblock you until a better fix comes along.