Using AWS v4 Signatures on RestSharp requests? - aws-api-gateway

I am using RestSharp (via openapi-generator) for an API which is on AWS API Gateway and uses AWS IAM authentication. This requires me to create a signature of the request and include it as a header. The input to this signature is defined as:
CanonicalRequest =
HTTPRequestMethod + '\n' +
CanonicalURI + '\n' +
CanonicalQueryString + '\n' +
CanonicalHeaders + '\n' +
SignedHeaders + '\n' +
HexEncode(Hash(RequestPayload))
My issue is that it seems the IAuthenticator interface does not give access to the headers and I'm not even sure it is 'late enough' in the process to give the desired results.
The process is described here:
https://docs.aws.amazon.com/general/latest/gr/sigv4_signing.html
There is an existing library (Aws4RequestSigner # https://www.nuget.org/packages/Aws4RequestSigner/) which do this for you, but they are based on the HttpRequestMessage.
Any suggestions on how I might be able to implement AWS Requests with Signature v4 via RestSharp?

Related

Federate Existing Azure Custom Domains to use Google SSO

We run our domains via Google. We have those domains verified in Azure for various purposes.
What I'd like to accomplish is to allow my user that use O365 to be able sign in with their Google Credentials. As I understand it, this is done through federation, SAML, and SSO. I've followed Google's instruction on setting this up and have hit a snag.
Using PowerShell's Set-MsolDomainAuthentication command I get an error every time I try to change the Authentication method from Managed to Federated. I can confirm that I can see the domains and their managed status via PowerShell commands, so I am at least connected to our Azure.
Set-MsolDomainAuthentication : Unable to complete this action. Try again later.
At line:1 char:1
+ Set-MsolDomainAuthentication
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : OperationStopped: (:) [Set-MsolDomainAuthentication], MicrosoftOnlineException
+ FullyQualifiedErrorId : Microsoft.Online.Administration.Automation.InternalServiceException,Microsoft.Online.Adm
inistration.Automation.SetDomainAuthentication
Azure logs show the attempt as
DirectoryManagement
Set domain authentication
Failure
Microsoft.Online.Workflows.ValidationException
Any help and direction is welcome. I've been searching high and low for solutions.
Side note: I have tried the convert command as well, with no luck.
Found a solution using this method rather than googles prescribed method.
https://medium.com/#james.winegar/how-to-single-sign-on-sso-between-g-suite-and-office-365-with-g-suite-as-identity-provider-idp-5bf5031835a0
IMPORTANT SIDE NOTE: For some reason or another, you cannot federate multiple domains with the same entityID in Azure. The workaround is to add spaces to the end of the entityID and Location URLs.
In my instance, I edited the metadata.xml and added the space within the quotes. There are two Location URLs in the XML, make the same change in both of them.
IE entityID="https://accounts.google.com/o/saml2?idpid=yourGoogleId "
And Location="https://accounts.google.com/o/saml2/idp?idpid=yourGoogleId "
Repeat this process for each additional domain from the same entityID. Keep in mind this is NOT a supported workaround, so use with caution.
Solution:
Run the following command:
Set-MsolDomainAuthentication -Name <domainName> -Authentication Managed -ActiveLogOnUri <ActiveLogOnUri> -FederationBrandName <FederationBrandName> -PassiveLogOnUri <PassiveLogOnUri> -SigningCertificate <SigningCertificate> -IssuerUri <IssuerUri> -LogOffUri <LogOffUri> -MetadataExchangeUri <MetadataExchangeUri> -PreferredAuthenticationProtocol <PreferredAuthenticationProtocol>

How to send API request with "/" and "*" characters in endpoint

im using the github API via Python in order to create branch protection rules for a github repo. Im using the requests library
https://docs.github.com/rest/reference/repos#get-branch-protection
And one of the rules i have to do need the "/" and the "" characters in them, for example: "/test/" or "test/" and the API does not work and gives a message not found because it thinks that the "/" and the "*" characters are not part of the branch name, but part of the API endpoint itself.
https://api.github.com/repos/OWNER/REPO/branches/test/*/protection
https://i.stack.imgur.com/Qh4F8.png
I have tried to encode the "/" and "*" characters using requests.utils.quote(branch, safe='') but the result is the same either way
https://i.stack.imgur.com/ANOY1.png
How can i solve this or get around this issue? Thank you

Python flask: forward POST to external API

I am building a microservice for the Camunda rest API using python flask and flask_restplus, python 3.7.0. Camunda is running in a docker container, available via localhost, port 8080. All GET requests to my microservice are being forwarded to the Camunda API via redirect, which is working perfectly fine.
POST requests (tested via postman, as suggested in the official tutorial) are not being forwarded properly using
redirect(camunda_api_url)
or
request.post(camunda_api_url)
The POST request via postman is done using
Header: Content-Type: multipart/form-data
Body: upload File Object (somefile.bpmn)
When I do the POST to the Camunda REST-API directly, everything works just fine, but when I try to redirect my post via my microservice, I get status code 200, but the file isn't being uploaded.
Debugging at my endpoint I can see that the file is being received:
print(request.files['upload'])
<FileStorage: 'somefile.bpmn' ('application/octet-stream')>
Thus the file is being transmitted successfully, but the redirect doesn't work.
My endpoint method looks like this:
def post(self):
print(request.files['upload'])
test = requests.post(host_prefix + 'deployment/create', files=request.files)
print(test.status_code)
Modifying the request.post via
data=request.files
data=request.files['upload']
or omiting data completely
always results in the file not being uploaded.
Trying redirect via
redirect(host_prefix + 'deployment/create', code=307)
also results in the file not being uploaded.
How can I redirect this post request properly to the Camunda API ?
This is not a question about the Camunda API rather than how to redirect a POST request to a foreign endpoint properly.
P.S.: I created my api and endpoints like this:
app = Flask(__name__)
api = Api(app, version='0.1', title='BPMN-API', description='A BPMN-API for Camunda, implemented in python')
...
api.add_resource(CreateDeployment, api_prefix + 'deployment/create', methods=['POST'])
OK, I solved this problem by using:
requests.post(camunda_api_url, files={file_name:request.files['upload'].read()})
where camunda_api_url is the endpoint at the Camunda REST engine, file_name is the name of the file being uploaded, AND by adding a
get-method,using simply:
def get(self):
camunda_api_url = "http://localhost:8080/engine-rest/deployment/create"
return redirect(camunda_api_url)
Without the get method the post doesn't work.
-> setting topic to solved. :)
By using requests library it is very easy. The example shows multiple file uploads with same key and with other form data as well. The images are coming from a form with the key named 'images'
The example gets file list from a form with the key 'images' and forward that files to another URL or API.
images = request.files.getlist('images')
files = []
for image in images:
files.append(("images", (image.filename, image.read(), image.content_type)))
r = requests.post(url=api_urls.insert_face_data_url, data={"apikey": apikey, "faceid": faceid},
files=files)

How to create a HTTP Request in Telnet

I am interested in scripting a HTTP Request to a listening web service I wrote (for testing purposes). I want to do this in Powershell. Initiating a HTTP Request through telnet is easy enough.
telnet google.com 80
Then, after a socket is established I can type in the following HTTP Verb and file:
GET /search?q=test
This is equivalent to performing a google search for the word "test". Great! However, I need to provide a more detailed HTTP Request Header if I want to do something more interesting. I'm trying to do something very similar to the example found here: http://blog.tonycode.com/tech-stuff/http-notes/making-http-requests-via-telnet
Following the author's example from the previous site, I created a local file with the following contents:
echo "open $1 $2"
sleep 2
echo "GET $4 HTTP/1.0"
echo "User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.4) Gecko/20070515 Firefox/2.0.0.4"
echo "Host: $3"
echo
echo
sleep 2
(This is similar to the custom HTTP Request Header I'd like to use for testing my own web services)
I then save this file as "getpage" (I also tried saving it as "getpage.sh"). I continue following the author's example and attempt to pipe the previous file into telnet from Powershell:
./getpage tonycode.com 80 tonycode.com /| telnet
However, Powershell is returning the following error:
Cannot run a document in the middle of a pipeline: ~\Desktop\getpage.
At line:1 char:1
+ ./getpage tonycode.com 80 tonycode.com /| telnet
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (~....Desktop\getpage:String) [], RuntimeException
+ FullyQualifiedErrorId : CantActivateDocumentInPipeline
I typed $PSVersionTable in Powershell and verified I'm using Powershell version 4.0. I'm starting to run out of ideas. I looked through the StackOverflow forums regarding http requests through telnet but I haven't found a good way to send a custom HTTP Request Header through telnet by passing in a pre-formated http header via a shell pipe. I can't really type the entire Http Request in telnet because 1) that defeats the purpose of scripting these kinds of things and 2) pressing the Enter key from telnet submits the current request before I can finishing typing the full Http Header. Does anyone have any suggestions how I can accomplish this in PowerShell? I can already write and send custom Http Headers in Firefox and it makes life way easier. I would just like to script this in Powershell if possible. Thanks in advance.
I am interested in scripting a HTTP Request to a listening web service I wrote (for testing purposes). I want to do this in Powershell.
then leave telnet alone :)
PowerShell(v3+) has built-in cmdlets:
Invoke-WebReques
Invoke-RestMethod
Or you can use System.Net.Sockets.TcpClient
Replacing Telnet.exe (now removed from Vista)
Scripting Network / TCP Connections in PowerShell
Or System.Net.WebClient
More advanced HTTP scripting: Facebook Photo Album Downloader
PS:
Using telnet to talk HTTP might have been "cool" in the past. But no one should be doing it nowadays. Especially when anything more than a trivial GET is required.
You should be using a real library for this like libcurl or whatever is available in your development environment.
Notes:
HTTP/1.0 is blocked by many sites nowadays. You should probably use HTTP/1.1.
HTTP/2 is a binary protocol. Using telnet or whatever "text" method you might have read about is just not possible with this protocol.

How to extract certificate from SAML Identity provider Metadata

I am using websphere's AdminTask.importSAMLIdpMetadata() function to import SAML IdP metadata into my server.
AdminTask.importSAMLIdpMetadata('-idpId 1 -ssoId 1 -idpMetadataFileName ' + idpMetaDataFile + ' -signingCertAlias ' + idpCertificateAlias + securityDomainParam);
It is working fine.
Problem is that if same certificates is already imported under some other alias then, it does not create new alias for same certificate.
To achieve this I need to write custom logic that will do all tasks of importSAMLIdpMetadata() and in always create alias
My questions:
How to extract certificate from IdP Metadata. ( In Java, Jython or Ant )
How to check if this certificate is already present in Websphere "signer certificates". ( In Java, Jython or Ant )
I tried doing above task myself
1) certificate can be extracted from IdP Metadata in java, like normal XML pasring and reading
2) To check if certificate is already present in Websphere "signer certificates" :-
Use jython to get all the certificates
AdminTask.listSignerCertificates('[-keyStoreName NodeDefaultTrustStore -keyStoreScope (cell):cell_name:(node):node_name ]')
It will give you a big string with each key value pair in square brackets []
Pass it to java and parse it as required.