How to get the sasKey or connectionString when developing a module? - azure-iot-edge

I am attempting to write a module where I cannot use the current ModuleClient.CreateFromEnvironmentAsync() and would like to get the module connection string (or SASKey) so I can generate a SAS token and authenticate.
I know that at one time (and in the IoTEdgeDev container) the environment variable EdgeHubConnectionString existed and was later removed. How can I derive the sasKey in code in a module? Imaging if I needed/wanted to use Paho in the module instead of the MSFT provided SDK.
Update
So I guess I have to sign the URI to create a connection string, similar to manually creating a connection string.
I have tried the code below, but the signature does not match what I get with Azure IoT Explorer. Any help would be appreciated. Reference: https://github.com/Azure/iotedge/blob/d2c331d605a846911019364a31a7d098e1e2fc45/edgelet/workload/docs/WorkloadApi.md
# expecting curl, base64 and jq to be installed
epoch=$(printf '%(%s)T\n' -1)
epoch=$(($epoch+86400))
dataToSign=$IOTEDGE_IOTHUBHOSTNAME"%2Fdevices%2F"$IOTEDGE_DEVICEID"%2Fmodules%2F"$IOTEDGE_MODULEID
signedData=$(echo -n $dataToSign'\n'$epoch | base64 -w 0)
signature=$(curl --unix-socket /var/run/iotedge/workload.sock http://127.0.0.1/modules/$IOTEDGE_MODULEID/genid/$IOTEDGE_MODULEGENERATIONID/sign?api-version=$IOTEDGE_APIVERSION \
--header "Content-Type: application/json" --request POST --data '{"data": "'$signedData'", "keyId": "", "algo": "HMAC-SHA256"}' \
| jq -r ".digest")
SASToken="SharedAccessSignature=SharedAccessSignature sr=$dataToSign&sig=$signature&se=$epoch"
ConnectionString="HostName=$IOTEDGE_IOTHUBHOSTNAME;DeviceId=$IOTEDGE_DEVICEID;ModuleId=$IOTEDGE_MODULEID;$SASToken"

I took a look at the implementation of ModuleClient.CreateFromEnvironmentAsync() in the C# SDK. It uses the following environment variables to create the connection string:
- IOTEDGE_WORKLOADURI URI for iotedged's workload API
- IOTEDGE_DEVICEID Device identifier
- IOTEDGE_MODULEID Module identifier
- IOTEDGE_MODULEGENERATIONID Module generation identifier
- IOTEDGE_IOTHUBHOSTNAME IoT Hub host name
- IOTEDGE_AUTHSCHEME Authentication scheme to use; must be "sasToken"
It seems the SAS token is created in the ModuleAuthenticationWithHsm class, you might be able to base your code on this?

So after hours of iteration, here is how to call the sign API to get a SAS Token:
# expecting curl, base64 and jq to be installed in the Linux OS
epoch=$(printf '%(%s)T\n' -1)
epoch=$(($epoch+86400))
WORKLOADURI=$(echo $IOTEDGE_WORKLOADURI | sed "s|unix://|""|g")
uri=$(echo $IOTEDGE_IOTHUBHOSTNAME"/devices/"$IOTEDGE_DEVICEID"/modules/"$IOTEDGE_MODULEID | sed "s|/|%2F|g")
signedData=$(echo -n $uri$'\n'$epoch | base64 -w 0)
signature=$(curl --unix-socket $WORKLOADURI http://127.0.0.1/modules/$IOTEDGE_MODULEID/genid/$IOTEDGE_MODULEGENERATIONID/sign?api-version=$IOTEDGE_APIVERSION \
--request POST --data '{"data": "'$signedData'", "keyId": "", "algo": "HMAC-SHA256"}' \
| jq -r ".digest" | sed "s|=|%3D|g" | sed "s|+|%2B|g" | sed "s|/|%2F|g")
# here is our SAS Token
SASToken="SharedAccessSignature=SharedAccessSignature sr=$uri&sig=$signature&se=$epoch"
# here is a connection string with the SAS Token
ConnectionString="HostName=$IOTEDGE_IOTHUBHOSTNAME;DeviceId=$IOTEDGE_DEVICEID;ModuleId=$IOTEDGE_MODULEID;$SASToken"

Related

How to use simple hello world example on opa server

I have defined a file with name - play.rego
package play
default hello = false
hello {
m := input.message
m == "world"
}
I also have file called -input.json
{ "message": "world"}
I now want to use the policy to evaluate on input data using opa server -
opa run --server
I also then registered the policy using below command -
curl -X PUT http://localhost:8181/v1/policies/play --data-binary #play.rego
and then I run below command for evaluating policy on the query -
curl -X POST http://localhost:8181/v1/policies/v1/data/play --data-binary '{"message": "world"}'
But the server always responds with nothing.
I need help fixing the problem?
The URL of the second request is wrong (should not contain v1/policies), and the v1 API requires you to wrap the input document inside an input attribute. Try:
curl -X POST http://localhost:8181/v1/data/play --data-binary '{"input":{"message": "world"}}'

How to get the API token for Jenkins

I am trying to use the Jenkins REST API. In the instructions it says I need to have the API key. I have looked all over the configuration pages to find it. How do I get the API key for Jenkins?
Since Jenkins 2.129 the API token configuration has changed:
You can now have multiple tokens and name them. They can be revoked individually.
Log in to Jenkins.
Click you name (upper-right corner).
Click Configure (left-side menu).
Use "Add new Token" button to generate a new one then name it.
You must copy the token when you generate it as you cannot view the token afterwards.
Revoke old tokens when no longer needed.
Before Jenkins 2.129: Show the API token as follows:
Log in to Jenkins.
Click your name (upper-right corner).
Click Configure (left-side menu).
Click Show API Token.
The API token is revealed.
You can change the token by clicking the Change API Token button.
The non UI way to do this post Jenkins 2.129 is:
curl 'https://<jenkinsURL>/me/descriptorByName/jenkins.security.ApiTokenProperty/generateNewToken' \
--data 'newTokenName=foo' \
--user username:Password
which returns:
{
"status": "ok",
"data": {
"tokenName": "foo",
"tokenUuid": "<uuid>",
"tokenValue": "<redacted>"
}
}
Pre Jenkins 2.129
curl http://<username>:<password>#<jenkins-url>/me/configure
Tested in Jenkins 2.225
After making research for several hours I could find the answer:
The API token is used instead of the CSFR token. However, what happens if you want to make authentication from any other client (Postman, CLI, cURL, etc.)?
First you need to get a CSFR token and save the information in a cookie with --cookie-jar
Request
curl -s --cookie-jar /tmp/cookies -u username:password
http://localhost:8080/crumbIssuer/api/json
Response
{
"_class": "hudson.security.csrf.DefaultCrumbIssuer",
"crumb": "bc92944100d12780cfc251c9255f3f323a475562b4ee0d8b9cc6e4121f50a450",
"crumbRequestField": "Jenkins-Crumb" }
Then we can read the cookie with --cookie and generate the new token:
Request
curl -X POST -H
'Jenkins-Crumb:your_crumb_token_generated_above'
--cookie /tmp/cookies http://localhost:8080/me/descriptorByName/jenkins.security.ApiTokenProperty/generateNewToken?newTokenName=\your_token_name
-u username:password
Response
{
"status": "ok",
"data": {
"tokenName": "my android token",
"tokenUuid": "c510e26c-b2e8-4021-bf79-81d1e4c112af",
"tokenValue": "11a2a0c91913d1391d8e8cb155ca714581"
} }
How to a generate Jenkins API token
The following commands need curl and jq. Execute them in the same session.
# Change the following appropriately
JENKINS_URL="http://localhost:8080"
JENKINS_USER=admin
JENKINS_USER_PASS=admin
Get the Crumb
JENKINS_CRUMB=$(curl -u "$JENKINS_USER:$JENKINS_USER_PASS" -s --cookie-jar /tmp/cookies $JENKINS_URL'/crumbIssuer/api/xml?xpath=concat(//crumbRequestField,":",//crumb)')
Get the access token
ACCESS_TOKEN=$(curl -u "$JENKINS_USER:$JENKINS_USER_PASS" -H $JENKINS_CRUMB -s \
--cookie /tmp/cookies $JENKINS_URL'/me/descriptorByName/jenkins.security.ApiTokenProperty/generateNewToken' \
--data 'newTokenName=GlobalToken' | jq -r '.data.tokenValue')
Consecutive API calls
Instead of the password, you need to use the token with the username along with the crumb that was generated.
curl -u $JENKINS_USER:$ACCESS_TOKEN \
-H $JENKINS_CRUMB \ ..........

Using curl for lira API with a period in the fixVersion jql

I've tried various iterations of using either ", ' and ` to enclose a curl query to an instance of jira in order to get all issues for a particular fix Version.
curl -D- -u username:password -X POST -H "Content-Type: application/json" -d '{"jql":"project = PROJ AND fixVersion=Version-1.2.3"}' "https://thejirainstall.com/jira/rest/api/2/search"
However, using this and a couple of other change on fixVersion such as:
fixVersion="Version-1.2.3"
or
fixVersion=\"Version-1.2.3\"
or
fixVersion=Version-1\u002e2\u002e3
Add and remove quotes at will.
The ones that don't fail outright return:
{"errorMessages":["Error in the JQL Query: '\\.' is an illegal JQL escape sequence. The valid escape sequences are \\', \\\", \\t, \\n, \\r, \\\\, '\\ ' and \\uXXXX. (line 1, character 38)"],"errors":{}}
How do I either escape periods . or add another set of quotes?
Ok, so it turns out that Jira doesn't permit version names in jql syntax. The version id must be used instead.
And, in order to get the version id you must parse the result from https://thejirainstall.com/jira/rest/api/2/project/ON/versions?
This now means that I have to use a JSON parser anyway. So, now I'm using jq via homebrew install jq
My current solution is to write a bash script as below:
JIRA_FIXVERSION
fixVersionQuery='https://thejirainstall.com/jira/rest/api/2/project/ON/versions?';
myJSONResponse=`curl -u username:password -X GET -H "Content-Type: application/json" --insecure --silent $fixVersionQuery |jq '.[] | {id,name} | select(.name=="Version-1.2.3" | .["id"]'`;
echo $myJSONResponse;

How to send file contents as body entity using cURL

I am using cURL command line utility to send HTTP POST to a web service. I want to include a file's contents as the body entity of the POST. I have tried using -d </path/to/filename> as well as other variants with type info like --data </path/to/filename> --data-urlencode </path/to/filename> etc... the file is always attached. I need it as the body entity.
I believe you're looking for the #filename syntax, e.g.:
strip new lines
curl --data "#/path/to/filename" http://...
keep new lines
curl --data-binary "#/path/to/filename" http://...
curl will strip all newlines from the file. If you want to send the file with newlines intact, use --data-binary in place of --data
I know the question has been answered, but in my case I was trying to send the content of a text file to the Slack Webhook api and for some reason the above answer did not work. Anywho, this is what finally did the trick for me:
curl -X POST -H --silent --data-urlencode "payload={\"text\": \"$(cat file.txt | sed "s/\"/'/g")\"}" https://hooks.slack.com/services/XXX
In my case, # caused some sort of encoding problem, I still prefer my old way:
curl -d "$(cat /path/to/file)" https://example.com
curl https://upload.box.com/api/2.0/files/3300/content -H "Authorization: Bearer $access_token" -F file=#"C:\Crystal Reports\Crystal Reports\mysales.pdf"

Upload file contents using cURL

I have a script with which I POST data to a server using cURL. When I use an HTML form to POST the same data, the POST looks something like this and all is well:
description=Something&name=aName&xml=wholeBiunchOfData&xslt=moreData
The XML and XSLT are large and change; I would prefer to maintain them in external files. However, the following does not work as I expect;
curl --cookie cjar --cookie-jar cjar --location --output NUL ^
--data "name=aName&description=Something" ^
--data "xml=#localFile.xml" ^
--data "xslt=#localFile.xslt" ^
http://someUrl.html
I have tried various combinations of the # and local files without success. How do I POST the contents of a file?
Looking at the man page it looks like the --data #file syntax does not permit for a variable name, it must be in the file. http://paulstimesink.com/2005/06/29/http-post-with-curl/. You could also try using a backtick
curl --cookie cjar --cookie-jar cjar --location --output NUL ^
--data "name=aName&description=Something" ^
--data "xml=`cat localFile.xml`" ^
--data "xslt=`cat someFile.xml`" ^
http://someUrl.html
I'd recommend trying the following:
curl --cookie cjar --cookie-jar cjar --location --output NUL ^
--data "name=aName&description=Something" ^
--data-urlencode "xml#localFile.xml" ^
--data-urlencode "xslt#localFile.xslt" ^
http://someUrl.html
XML (including stylesheets) will need to be URL-encoded before being made part of a URL.
You can also use --trace-ascii - as an additional parameter to dump the input and output to standard out for further debugging, and you can find more information on the main man page.
Hope this helps!

Resources