I have been working with textract for this past month using boto3, when I tried using the QUERIES feature this would throw an error saying that queries config is not a valid parameter so I decided to go with the amazon service API, but I get as a response;here my code, I;m following the docs to get the signature.
import requests
import boto3
import sys, os, base64, datetime, hashlib, hmac
import json
session = boto3.Session()
credentials = session.get_credentials()
credentials = credentials.get_frozen_credentials()
access_key = credentials.access_key
secret_key = credentials.secret_key
print()
method = 'POST'
service = 'textract'
amz_target = 'Textract.StartDocumentAnalysis'
host = 'textract.us-east-1.amazonaws.com'
region = 'us-east-1'
endpoint = 'https://textract.us-east-1.amazonaws.com'
canonical_uri = '/'
content_type = 'application/x-amz-json-1.1'
# request_parameters = 'Action=DescribeRegions&Version=2013-10-15'
def sign(key, msg):
return hmac.new(key, msg.encode('utf-8'), hashlib.sha256).digest()
def getSignatureKey(key, dateStamp, regionName, serviceName):
kDate = sign(('AWS4' + key).encode('utf-8'), dateStamp)
kRegion = sign(kDate, regionName)
kService = sign(kRegion, serviceName)
kSigning = sign(kService, 'aws4_request')
return kSigning
# Create a date for headers and the credential string
t = datetime.datetime.utcnow()
amz_date = t.strftime('%Y%m%dT%H%M%SZ')
date_stamp = t.strftime('%Y%m%d') # Date w/o time, used in credential scope
amz_target = 'Textract.'
canonical_headers = 'content-type:' + content_type + '\n' + 'host:' + host + '\n' + 'x-amz-date:' + amz_date + '\n' + 'x-amz-target:' + amz_target + '\n'
signed_headers = 'content-type;host;x-amz-date;x-amz-target'
canonical_querystring = ''
payload = {
"DocumentLocation": {
"S3Object": {
"Bucket": "",
"Name": "",
}
},
"FeatureTypes": [ "FORMS" ],
"JobTag": "123",
"NotificationChannel": {
"RoleArn": "",
"SNSTopicArn": ""
},
"QueriesConfig": {
"Queries": [
{
"Alias": "string",
"Pages": [ "1-4" ],
"Text": "what is the policy number ?"
}
]
}
}
payload_hash = hashlib.sha256(json.dumps(payload).encode('utf-8')).hexdigest()
canonical_request = method + '\n' + canonical_uri + '\n' + canonical_querystring + '\n' + canonical_headers + '\n' + signed_headers + '\n' + payload_hash
algorithm = 'AWS4-HMAC-SHA256'
credential_scope = date_stamp + '/' + region + '/' + service + '/' + 'aws4_request'
string_to_sign = algorithm + '\n' + amz_date + '\n' + credential_scope + '\n' + hashlib.sha256(canonical_request.encode('utf-8')).hexdigest()
signing_key = getSignatureKey(secret_key, date_stamp, region, service)
signature = hmac.new(signing_key, (string_to_sign).encode('utf-8'), hashlib.sha256).hexdigest()
authorization_header = algorithm + ' ' + 'Credential=' + access_key + '/' + credential_scope + ', ' + 'SignedHeaders=' + signed_headers + ', ' + 'Signature=' + signature
headers = {'Content-Type':content_type,
'X-Amz-Date':amz_date,
'X-Amz-Target':amz_target,
'Authorization':authorization_header}
print('Request URL = ' + endpoint)
r = requests.post("https://textract.us-east-1.amazonaws.com", data=json.dumps(payload), headers=headers)
print(r.text)
Related
locals {
acl_out = flatten([
for opi, clsan in var.appr : [
for co, coo in clsan : [
for applo in coo : [
for op in ( co == "RO" ? ["READ","DESCRIBE"] : ["WRITE"]) : {
oper = op
appid_lo = applo
opic-name = opi
process = co
}
]
]
]
])
}
variable "appr" {
description = "A complex object "
type = map(object({
#displayname = string
RO = optional(list(string))
WO = optional(list(string))
}))
}
If co = RO then ["READ","DESCRIBE"]
If co = WO then [WRITE]
Above expression fails with null value, If WO not defined/unset in product 2, If statement need to corrected
Input :
Working
appr = {
product1 = { WO = ["6470"], RO = ["6471","5538"] },
product2 = { WO = ["5555"], RO = ["6472"]},
product3 = { WO = ["6473"], RO = ["6474"] },
}
Not Working
appr = {
product1 = { WO = ["6470"], RO = ["6471","5538"] },
product2 = { RO = ["6472"]},
product3 = { WO = ["6473"], RO = ["6474"] },
}
Error:
A null value cannot be used as the collection in a 'for' expression.
Tried this way also fails
for op in ( co == "RO" = ["READ","DESCRIBE"] || co == "WO" = ["WRITE"] ) : {
Desired Result :
{
opic-name = "product1"
oper = "WRITE"
appid_lo = 6470
},
{
opic-name = "product1"
oper = "READ"
appid_lo = 6471
},
{
opic-name = "product1"
oper = "DESCRIBE"
appid_lo = 6471
}
and so on
This question was a fun one!
Check if it is null before running the next for
locals {
acl_out = flatten([
for opi, clsan in var.appr : [
for co, coo in clsan : [
coo == null ? [] : [
for applo in coo : [
for op in ( co == "RO" ? ["READ","DESCRIBE"] : ["WRITE"]) : {
oper = op
appid_lo = applo
opic-name = opi
process = co
}
]
]]
]
])
}
Output for acl_out
acl_out = [
+ {
+ appid_lo = "6471"
+ oper = "READ"
+ opic-name = "product1"
+ process = "RO"
},
+ {
+ appid_lo = "6471"
+ oper = "DESCRIBE"
+ opic-name = "product1"
+ process = "RO"
},
+ {
+ appid_lo = "5538"
+ oper = "READ"
+ opic-name = "product1"
+ process = "RO"
},
+ {
+ appid_lo = "5538"
+ oper = "DESCRIBE"
+ opic-name = "product1"
+ process = "RO"
},
+ {
+ appid_lo = "6470"
+ oper = "WRITE"
+ opic-name = "product1"
+ process = "WO"
},
+ {
+ appid_lo = "6472"
+ oper = "READ"
+ opic-name = "product2"
+ process = "RO"
},
+ {
+ appid_lo = "6472"
+ oper = "DESCRIBE"
+ opic-name = "product2"
+ process = "RO"
},
+ {
+ appid_lo = "6474"
+ oper = "READ"
+ opic-name = "product3"
+ process = "RO"
},
+ {
+ appid_lo = "6474"
+ oper = "DESCRIBE"
+ opic-name = "product3"
+ process = "RO"
},
+ {
+ appid_lo = "6473"
+ oper = "WRITE"
+ opic-name = "product3"
+ process = "WO"
},
]
Cheers!
I have three child modules and one parent module for ssm patching. One module in particular is different than the rest (RHEL) it will never need to be changed, so the child module was written differently.
I have my baseline approval rules written as a dynamic object and have prepared the variable for the object.
resource "aws_ssm_patch_baseline" "baseline" {
name = format("%s-%s-%s-baseline", var.patch_baseline_label, var.env, lower(local.operating_system))
description = var.description
operating_system = local.operating_system
approved_patches = var.approved_patches
rejected_patches = var.rejected_patches
approved_patches_compliance_level = var.compliance_level
dynamic "approval_rule" {
for_each = var.baseline_approval_rules
content {
approve_after_days = approval_rule.value.approve_after_days
compliance_level = approval_rule.value.compliance_level
enable_non_security = approval_rule.value.enable_non_security
# patch filter values : https://docs.aws.amazon.com/cli/latest/reference/ssm/describe-patch-properties.html
dynamic "patch_filter" {
for_each = approval_rule.value.patch_baseline_filters
content {
key = patch_filter.value.name
values = patch_filter.value.values
}
}
}
}
tags = merge(var.tags, { Name = format("%s-%s-%s", var.patch_baseline_label, var.env, lower(local.operating_system)) })
}
The variable for the approval rules is written as such:
variable "baseline_approval_rules" {
description = "list of approval rules defined in the patch baseline (Max 10 rules). For compliance_level, it means that if an approved patch is reported as missing, this is the severity of the compliance violation. Valid compliance levels include the following: CRITICAL, HIGH, MEDIUM, LOW, INFORMATIONAL, UNSPECIFIED. The default value is UNSPECIFIED."
type = list(object({
approve_after_days : number
compliance_level : string
enable_non_security : bool
patch_baseline_filters : list(object({
name : string
values : list(string)
}))
}))
default = [
{
approve_after_days = 0
// The compliance level of a patch will default to unspecified if a patch isn't applied
compliance_level = "CRITICAL"
enable_non_security = false
patch_baseline_filters = [
{
name = "PRODUCT"
values = ["RedhatEnterpriseLinux6.10", "RedhatEnterpriseLinux6.5", "RedhatEnterpriseLinux6.6", "RedhatEnterpriseLinux6.7", "RedhatEnterpriseLinux6.8", "RedhatEnterpriseLinux6.9", "RedhatEnterpriseLinux7", "RedhatEnterpriseLinux7.0", "RedhatEnterpriseLinux7.1", "RedhatEnterpriseLinux7.2", "RedhatEnterpriseLinux7.3", "RedhatEnterpriseLinux7.4", "RedhatEnterpriseLinux7.5", "RedhatEnterpriseLinux7.6", "RedhatEnterpriseLinux7.7", "RedhatEnterpriseLinux7.8", "RedhatEnterpriseLinux8", "RedhatEnterpriseLinux8.0", "RedhatEnterpriseLinux8.1", "RedhatEnterpriseLinux8.2"]
},
{
name = "CLASSIFICATION"
values = ["Security"]
},
{
name = "SEVERITY"
values = ["Critical"]
}
]
}
]
}
In the parent module, I would like an output that generates a map for the baseline approval rules.. something similar to
[
{
name = "product",
valueFrom = <VALUE FROM PRODUCT IN patch_baseline_filters >,
{
name = "severity",
valueFrom = <VALUE FROM SEVERITY IN patch_baseline_filters>,
{
name = <etc>,
valueFrom = <ETC>
}
]
I'm trying to use functions like zipmap and sort to output the values to a map, but I have had no success.
Thanks!
EDIT:
Entire RHEL resource output looks like this:
+ entire_rhel_resource = [
+ {
+ approval_rule = [
+ {
+ approve_after_days = 0
+ approve_until_date = null
+ compliance_level = "CRITICAL"
+ enable_non_security = false
+ patch_filter = [
+ {
+ key = "PRODUCT"
+ values = [
+ "RedhatEnterpriseLinux6.10",
+ "RedhatEnterpriseLinux6.5",
+ "RedhatEnterpriseLinux6.6",
+ "RedhatEnterpriseLinux6.7",
+ "RedhatEnterpriseLinux6.8",
+ "RedhatEnterpriseLinux6.9",
+ "RedhatEnterpriseLinux7",
+ "RedhatEnterpriseLinux7.0",
+ "RedhatEnterpriseLinux7.1",
+ "RedhatEnterpriseLinux7.2",
+ "RedhatEnterpriseLinux7.3",
+ "RedhatEnterpriseLinux7.4",
+ "RedhatEnterpriseLinux7.5",
+ "RedhatEnterpriseLinux7.6",
+ "RedhatEnterpriseLinux7.7",
+ "RedhatEnterpriseLinux7.8",
+ "RedhatEnterpriseLinux8",
+ "RedhatEnterpriseLinux8.0",
+ "RedhatEnterpriseLinux8.1",
+ "RedhatEnterpriseLinux8.2",
]
},
+ {
+ key = "CLASSIFICATION"
+ values = [
+ "Security",
]
},
+ {
+ key = "SEVERITY"
+ values = [
+ "Critical",
]
},
]
},
]
+ approved_patches = null
+ approved_patches_compliance_level = "UNSPECIFIED"
+ approved_patches_enable_non_security = null
+ arn = (known after apply)
+ description = "RedHat Enterprise Linux Default Patch Baseline"
+ global_filter = []
+ id = (known after apply)
+ name = "SENSITIVEredhat_enterprise_linux-baseline"
+ operating_system = "REDHAT_ENTERPRISE_LINUX"
+ rejected_patches = null
+ rejected_patches_action = (known after apply)
+ source = []
+ tags = {
+ "Name" = "SENSITIVEredhat_enterprise_linux"
+ "owner" = "SENSITIVE"
+ "team" = "SENSITIVE"
+ "terraform" = "true"
}
+ tags_all = {
+ "Name" = "SENSITIVEredhat_enterprise_linux"
+ "owner" = "SENSITIVE"
+ "team" = "SENSITIVE"
+ "terraform" = "true"
}
},
]
Here is the best I could come up with:
output "rhel_server_types" {
description = "types of patches applied for rhel systems"
value = [for i in aws_ssm_patch_baseline.baseline.approval_rule[0].patch_filter : {
name = lower(i.key)
valueFrom = i.values
}]
}
I have a powershell script that I am running through ExtendScript (Photoshop) in order to upload files to an s3 bucket.
I have this code to upload files to an aws s3 bucket.
However, it only works for smaller files (works on a 50mb file)
But does not work on a 140mb file. Shows no error but the file is not uploaded.
Any ideas?
$_rawfilename = 'C:/Users/DELL/AppData/Local/Temp/Filled_Albedo.exr'
$folder = 'seam-removal'
$filename = 'Filled_Albedo.exr'
$keyFile = ($folder+ '/' + $filename)
$service = 's3'
$bucket = '**'
$region = 'us-west-2'
$host1 = $bucket + '.s3' + '.amazonaws.com'
$access_key = '**'
$secret_key = '**'
$br = [regex]::Unescape('\u000a')
function HmacSHA256($message, $secret) {
$hmacsha = New-Object System.Security.Cryptography.HMACSHA256
$hmacsha.key = $secret
$signature = $hmacsha.ComputeHash([Text.Encoding]::ASCII.GetBytes($message))
return $signature
}
function getSignatureKey($key, $dateStamp, $regionName, $serviceName) {
$kSecret = [Text.Encoding]::UTF8.GetBytes(('AWS4' + $key).toCharArray())
$kDate = HmacSHA256 $dateStamp $kSecret
$kRegion = HmacSHA256 $regionName $kDate
$kService = HmacSHA256 $serviceName $kRegion
$kSigning = HmacSHA256 'aws4_request' $kService
return $kSigning
}
function hash($request) {
$hasher = [System.Security.Cryptography.SHA256]::Create()
$content = [Text.Encoding]::UTF8.GetBytes($request)
$bytes = $hasher.ComputeHash($content)
return ($bytes | ForEach-Object ToString x2) -join ''
}
function requestBuilder($method, $key) {
$now = [DateTime]::UtcNow
$amz_date = $now.ToString('yyyyMMddTHHmmssZ')
$datestamp = $now.ToString('yyyyMMdd')
$signed_headers = 'host'
$credential_scope = $datestamp + '/' + $region + '/' + $service + '/' + 'aws4_request'
$canonical_querystring = ''
$canonical_querystring = 'X-Amz-Algorithm=AWS4-HMAC-SHA256'
$canonical_querystring += '&X-Amz-Credential=' + [uri]::EscapeDataString(($access_key + '/' + $credential_scope))
$canonical_querystring += '&X-Amz-Date=' + $amz_date
$canonical_querystring += '&X-Amz-Expires=86400'
$canonical_querystring += '&X-Amz-SignedHeaders=' + $signed_headers
$canonical_headers = 'host:' + $host1 + $br
$canonical_request = $method + $br
$canonical_request += '/' + $key + $br
$canonical_request += $canonical_querystring + $br
$canonical_request += $canonical_headers + $br
$canonical_request += $signed_headers + $br
$canonical_request += 'UNSIGNED-PAYLOAD'
$algorithm = 'AWS4-HMAC-SHA256'
$canonical_request_hash = hash -request $canonical_request
$string_to_sign = $algorithm + $br
$string_to_sign += $amz_date + $br
$string_to_sign += $credential_scope + $br
$string_to_sign += $canonical_request_hash
$signing_key = getSignatureKey $secret_key $datestamp $region $service
$signature = HmacSHA256 -secret $signing_key -message $string_to_sign
$signature = ($signature|ForEach-Object ToString x2) -join ''
$canonical_querystring += '&X-Amz-Signature=' + $signature
$request_url = 'http://' + $host1 + '/' + $key + '?' + $canonical_querystring
Write-Host $request_url
return $request_url
}
#C# class to create callback
$code = #"
public class SSLHandler
{
public static System.Net.Security.RemoteCertificateValidationCallback GetSSLHandler()
{
return new System.Net.Security.RemoteCertificateValidationCallback((sender, certificate, chain, policyErrors) => { return true; });
}
}
"#
#compile the class
Add-Type -TypeDefinition $code
#disable checks using new class
[System.Net.ServicePointManager]::ServerCertificateValidationCallback = [SSLHandler]::GetSSLHandler()
#do the request
try
{
Invoke-RestMethod -Method PUT -Uri (requestBuilder 'PUT' $keyFile) -InFile $_rawfilename
} catch {
# do something
} finally {
#enable checks again
[System.Net.ServicePointManager]::ServerCertificateValidationCallback = {true}
}
Started working after making the changes suggested in the above comments (verbose and write host).
I want to upload a file to AWS S3 with AES256 encryption however I am not allowed to install the AWS CLI. I have the code below which allows me to upload files to S3 using my secret keys however this does not work then encryption is required for the S3 bucket. How do I perform something similar to: aws s3api put-object --server-side-encryption=AES256 --bucket=<bucket_name> --key=<name_of_object_when_uploaded> --body=/<path>/<object_to_upload> with my code below?
# Config Parts
$_rawfilename = 'C:/<NAME>/SSP00001_RITM1304145.csv'
$folder = 'TestResults'
$filename = $_rawfilename.Split('/')[2]
$keyFile = ($folder+ '/' + $filename)
$service = 's3'
$bucket = '<BUCKET NAME>'
$region = 'us-east-1'
$host1 = $bucket + '.s3' + '.amazonaws.com'
$access_key = ''
$secret_key = ''
$br = [regex]::Unescape('\u000a')
function HmacSHA256($message, $secret) {
$hmacsha = New-Object System.Security.Cryptography.HMACSHA256
$hmacsha.key = $secret
$signature = $hmacsha.ComputeHash([Text.Encoding]::ASCII.GetBytes($message))
return $signature
}
function getSignatureKey($key, $dateStamp, $regionName, $serviceName) {
$kSecret = [Text.Encoding]::UTF8.GetBytes(('AWS4' + $key).toCharArray())
$kDate = HmacSHA256 $dateStamp $kSecret
$kRegion = HmacSHA256 $regionName $kDate
$kService = HmacSHA256 $serviceName $kRegion
$kSigning = HmacSHA256 'aws4_request' $kService
return $kSigning
}
function hash($request) {
$hasher = [System.Security.Cryptography.SHA256]::Create()
$content = [Text.Encoding]::UTF8.GetBytes($request)
$bytes = $hasher.ComputeHash($content)
return ($bytes | ForEach-Object ToString x2) -join ''
}
function requestBuilder($method, $key) {
$now = [DateTime]::UtcNow
$amz_date = $now.ToString('yyyyMMddTHHmmssZ')
$datestamp = $now.ToString('yyyyMMdd')
$signed_headers = 'host'
$credential_scope = $datestamp + '/' + $region + '/' + $service + '/' + 'aws4_request'
$canonical_querystring = ''
$canonical_querystring = 'X-Amz-Algorithm=AWS4-HMAC-SHA256'
$canonical_querystring += '&X-Amz-Credential=' + [uri]::EscapeDataString(($access_key + '/' + $credential_scope))
$canonical_querystring += '&X-Amz-Date=' + $amz_date
$canonical_querystring += '&X-Amz-Expires=86400'
$canonical_querystring += '&X-Amz-SignedHeaders=' + $signed_headers
$canonical_headers = 'host:' + $host1 + $br
$canonical_request = $method + $br
$canonical_request += '/' + $key + $br
$canonical_request += $canonical_querystring + $br
$canonical_request += $canonical_headers + $br
$canonical_request += $signed_headers + $br
$canonical_request += 'UNSIGNED-PAYLOAD'
$algorithm = 'AWS4-HMAC-SHA256'
$canonical_request_hash = hash -request $canonical_request
$string_to_sign = $algorithm + $br
$string_to_sign += $amz_date + $br
$string_to_sign += $credential_scope + $br
$string_to_sign += $canonical_request_hash
$signing_key = getSignatureKey $secret_key $datestamp $region $service
$signature = HmacSHA256 -secret $signing_key -message $string_to_sign
$signature = ($signature|ForEach-Object ToString x2) -join ''
$canonical_querystring += '&X-Amz-Signature=' + $signature
$request_url = 'http://' + $host1 + '/' + $key + '?' + $canonical_querystring
Write-Host $request_url
return $request_url
}
# Where -InFile is Path/to/xlsx
Invoke-RestMethod -Method PUT -Uri (requestBuilder 'PUT' $keyFile) -InFile $_rawfilename
Start-Sleep -s 2
I tried adding $canonical_querystring += '&X-amz-server-side-encryption-customer-algorithm=AES256' to the code however it's still not working:
$canonical_querystring = ''
$canonical_querystring = 'X-Amz-Algorithm=AWS4-HMAC-SHA256'
$canonical_querystring += '&X-Amz-Credential=' + [uri]::EscapeDataString(($access_key + '/' + $credential_scope))
$canonical_querystring += '&X-Amz-Date=' + $amz_date
$canonical_querystring += '&X-Amz-Expires=86400'
**$canonical_querystring += '&X-amz-server-side-encryption-customer-algorithm=AES256'**
$canonical_querystring += '&X-Amz-SignedHeaders=' + $signed_headers
You have to add x-amz-server-side-encryption header to your request ($canonical_headers).
See:
https://docs.aws.amazon.com/AmazonS3/latest/userguide/specifying-s3-encryption.html
https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObject.html
I want to download a file from my AWS S3 bucket using Windows Powershell. I cannot install any AWS software and need to create an API to be able to access a file in AWS S3. I used Postman for testing that the file is accessible and it was successful.
Given this success I tried following AWS' guide which says that I need to create the following:
Create a canonical request.
Use the canonical request and additional metadata to create a string
for signing.
Derive a signing key from your AWS secret access key. Then use the
signing key, and the string from the previous step, to create a
signature.
Add the resulting signature to the HTTP request in a header or as a
query string parameter.
The closest I've seen is this example from https://forums.aws.amazon.com/thread.jspa?threadID=251722 by Abhaya however it is also unresolved. (The payload hash in this example is the payload hash for blank). I have gone through several AWS guides but these are very confusing when trying to apply them to powershell. https://docs.aws.amazon.com/general/latest/gr/sigv4-create-canonical-request.html
The url the code below generates a url that looks correct:http://SAMPLEBUCKETNAME HERE.s3-ap-southeast-1.amazonaws.com/test.xlsx?&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=%2F20190907%2Fap-southeast-1%2Fs3%2Faws4_request&X-Amz-Date=20190907T1644136560000Z&X-Amz-E0&X-Amz-SignedHeaders=host&X-Amz-Signature=HASH HERE
$method = 'GET'
$service = 's3'
$host1 = 'SAMPLES3BUCKETNAME.s3-ap-southeast-1.amazonaws.com'
$region = 'ap-southeast-1'
$endpoint = 'http://SAMPLES3BUCKETNAME.s3-ap-southeast-1.amazonaws.com/test.xlsx'
function HmacSHA256($message, $secret){
<#$hmacsha = New-Object System.Security.Cryptography.HMACSHA256
$hmacsha.key = [Text.Encoding]::UTF8.GetBytes($secret)
#$hmacsha.key = $secret
$signature = $hmacsha.ComputeHash([Text.Encoding]::UTF8.GetBytes($message))
$signature = [Convert]::ToBase64String($signature)
#>
$hmacsha = New-Object System.Security.Cryptography.HMACSHA256
$hmacsha.Key = #($secret -split '(?<=\G..)(?=.)'|ForEach-Object {[byte]::Parse($_,'HexNumber')})
$sign = [BitConverter]::ToString($hmacsha.ComputeHash([Text.Encoding]::UTF8.GetBytes($message))).Replace('-','').ToLower()
return $sign
}
function getSignatureKey($key, $dateStamp, $regionName, $serviceName)
{
$kSecret = [Text.Encoding]::UTF8.GetBytes(("AWS4" + $key).toCharArray())
$kDate = HmacSHA256 $dateStamp $kSecret;
$kRegion = HmacSHA256 $regionName $kDate ;
$kService = HmacSHA256 $serviceName $kRegion ;
$kSigning = HmacSHA256 "aws4_request" $kService ;
return $kSigning;
}
$access_key = 'SAMPLEACCESSKEY'
$secret_key = 'SAMPLESECRETKEY'
$amz_date = [DateTime]::UtcNow.ToString('yyyyMMddTHHmmssfffffffZ')
$datestamp = [DateTime]::UtcNow.ToString('yyyyMMdd')
$canonical_uri = '/'
$canonical_headers = 'host:' + $host1 + "`n"
$signed_headers = 'host'
$algorithm = 'AWS4-HMAC-SHA256'
$credential_scope = $datestamp + '/' + $region + '/' + $service + '/' + 'aws4_request'
$canonical_querystring = ''
$canonical_querystring += '&X-Amz-Algorithm=AWS4-HMAC-SHA256'
$canonical_querystring += '&X-Amz-Credential=' + [uri]::EscapeDataString(($access_key + '/' + $credential_scope))
$canonical_querystring += '&X-Amz-Date=' + $amz_date
$canonical_querystring += '&X-Amz-Expires=86400'
$canonical_querystring += '&X-Amz-SignedHeaders=' + $signed_headers
$payload_hash = 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855'
$canonical_request1 = $method + "`n" +$canonical_uri + "`n" + $canonical_querystring + "`n" + $canonical_headers + "`n" + $signed_headers + "`n" + $payload_hash
Write-Host $canonical_request1
function hash($request) {
$hasher = [System.Security.Cryptography.SHA256]::Create()
$content = [Text.Encoding]::UTF8.GetBytes($request)
$hash = [System.Convert]::ToBase64String($hasher.ComputeHash($content))
return $hash
}
$canonical_request = hash -request $canonical_request1
$string_to_sign = $algorithm + "`n" + $amz_date + "`n" + $credential_scope + "`n" + $canonical_request
$signing_key = getSignatureKey $secret_key $datestamp $region $service
$signature = HmacSHA256 -secret $signing_key -message $string_to_sign
$canonical_querystring += '&X-Amz-Signature=' + $signature
$request_url = $endpoint + "?" + $canonical_querystring
$request_url
I get the following error when I try accessing the url.
There were a few errors, notably how you were computing the signature, building the timestamp, and the error that you were seeing is because the parameters weren't properly being passed along.
Here's a version that corrects those issues:
$method = 'GET'
$service = 's3'
$bucket = "SAMPLES3BUCKETNAME"
$key = 'test.xlsx'
$region = 'ap-southeast-1'
$host1 = $bucket + '.s3-' + $region + '.amazonaws.com'
$access_key = 'SAMPLEACCESSKEY'
$secret_key = 'SAMPLESECRETKEY'
function HmacSHA256($message, $secret)
{
$hmacsha = New-Object System.Security.Cryptography.HMACSHA256
$hmacsha.key = $secret
$signature = $hmacsha.ComputeHash([Text.Encoding]::ASCII.GetBytes($message))
return $signature
}
function getSignatureKey($key, $dateStamp, $regionName, $serviceName)
{
$kSecret = [Text.Encoding]::UTF8.GetBytes(("AWS4" + $key).toCharArray())
$kDate = HmacSHA256 $dateStamp $kSecret;
$kRegion = HmacSHA256 $regionName $kDate;
$kService = HmacSHA256 $serviceName $kRegion;
$kSigning = HmacSHA256 "aws4_request" $kService;
return $kSigning
}
function hash($request)
{
$hasher = [System.Security.Cryptography.SHA256]::Create()
$content = [Text.Encoding]::UTF8.GetBytes($request)
$bytes = $hasher.ComputeHash($content)
return ($bytes|ForEach-Object ToString x2) -join ''
}
$now = [DateTime]::UtcNow
$amz_date = $now.ToString('yyyyMMddTHHmmssZ')
$datestamp = $now.ToString('yyyyMMdd')
$signed_headers = 'host'
$credential_scope = $datestamp + '/' + $region + '/' + $service + '/' + 'aws4_request'
$canonical_querystring = 'X-Amz-Algorithm=AWS4-HMAC-SHA256'
$canonical_querystring += '&X-Amz-Credential=' + [uri]::EscapeDataString(($access_key + '/' + $credential_scope))
$canonical_querystring += '&X-Amz-Date=' + $amz_date
$canonical_querystring += '&X-Amz-Expires=86400'
$canonical_querystring += '&X-Amz-SignedHeaders=' + $signed_headers
$canonical_headers = 'host:' + $host1 + "`n"
$canonical_request = $method + "`n"
$canonical_request += "/" + $key + "`n"
$canonical_request += $canonical_querystring + "`n"
$canonical_request += $canonical_headers + "`n"
$canonical_request += $signed_headers + "`n"
$canonical_request += "UNSIGNED-PAYLOAD"
$algorithm = 'AWS4-HMAC-SHA256'
$canonical_request_hash = hash -request $canonical_request
$string_to_sign = $algorithm + "`n"
$string_to_sign += $amz_date + "`n"
$string_to_sign += $credential_scope + "`n"
$string_to_sign += $canonical_request_hash
$signing_key = getSignatureKey $secret_key $datestamp $region $service
$signature = HmacSHA256 -secret $signing_key -message $string_to_sign
$signature = ($signature|ForEach-Object ToString x2) -join ''
$canonical_querystring += '&X-Amz-Signature=' + $signature
$request_url = "http://" + $host1 + "/" + $key + "?" + $canonical_querystring
Write-Host $request_url