CosmosDB UserPermission with ResourcePartitionKey not Enforced - azure-cosmosdb

I'm trying to implement the behaviour described in this CosmosDB document with the additional ResourcePartitionKey restrictions on the User Permissions to constrain a resource token to only accessing documents that belong to the specified partition key however I can't make it work.
With the SQL REST API, I receive no errors with the POST to create the UserPermission object with the resourcepartitionkey keypair and both the initial returned object as well as subsequent GET's also show the "resourcepartitionkey" present when fetching the resource token.
Using the resource token against the appropriate collection specified in the permission, I can list all documents in the collection. When using a "x-ms-documentdb-partitionkey" header, I can target any paritionkey I like. Without "x-ms-documentdb-partitionkey" header, it simply returns the whole collection.
The collection is a brand new, Unlimited, 1000 RU's with a partition key of '/rpk'. Post creation query of the collection shows the partition key configured as follows
"partitionKey": {
"paths": [
"\/rpk"
],
"kind": "Hash"
}
Below is the User Permission returned during creation showing the "resourcepartitionkey" present
{
"resource": "dbs/dbName/colls/collectionName/",
"id": "read-collection",
"resourcepartitionkey": "rpk1",
"permissionMode": "read",
"_rid": "lH9FACGGKwAhslfihB0pAA==",
"_self": "dbs\/lH9FAA==\/users\/lH9FACGGKwA=\/permissions\/lH9FACGGKwAhslfihB0pAA==\/",
"_etag": "\"0000ba07-0000-0000-0000-5b7418770000\"",
"_ts": 1534335095,
"_token": "type=resource&ver=1&sig=<resource token signature>"
}
The following is the request for documents using the resource token above. I would expect this to fail due to the missing "x-ms-documentdb-partitionkey" header against a partitioned collection but it both succeeds and proceeds to return records from all partition keys in the collection (only 2 in my test dataset)
GET https://accountname.documents.azure.com/dbs/dbName/colls/collectionName/docs HTTP/1.1
authorization: type%3dresource%26ver%3d1%26sig<resource token signature>
x-ms-version: 2017-02-22
x-ms-max-item-count: -1
x-ms-date: Wed, 15 Aug 2018 12:11:35 GMT
User-Agent: Mozilla/5.0 (Windows NT; Windows NT 10.0; en-AU) WindowsPowerShell/5.1.17134.165
Content-Type: application/json
Host: accountname.documents.azure.com
Response Body from request above showing documents from the partition keys rpk1 and rpk2 even though the user permission is configured to rpk1.
{
"_rid": "lH9FAKbDh4c=",
"Documents": [
{
"id": "blue",
"rpk": "rpk1",
"_rid": "lH9FAKbDh4cCAAAAAAAAAA==",
"_self": "dbs\/lH9FAA==\/colls\/lH9FAKbDh4c=\/docs\/lH9FAKbDh4cCAAAAAAAAAA==\/",
"_etag": "\"ec012ca1-0000-0000-0000-5b73ab440000\"",
"_attachments": "attachments\/",
"_ts": 1534307140
},
{
"id": "red",
"rpk": "rpk2",
"_rid": "lH9FAKbDh4cDAAAAAAAAAA==",
"_self": "dbs\/lH9FAA==\/colls\/lH9FAKbDh4c=\/docs\/lH9FAKbDh4cDAAAAAAAAAA==\/",
"_etag": "\"ec012da1-0000-0000-0000-5b73ab580000\"",
"_attachments": "attachments\/",
"_ts": 1534307160
}
],
"_count": 2
}
I'm assuming I've missed something obvious, or using an incorrect value for 'resourcepartitionkey' in the UserPermission but I can't determine what. Any thoughts greatly appreciated.

After many more hours of trial and error, I have finally resolved my issue which is caused during the POST creation of the user permission.
Firstly, whilst the creation of the user permission will validate the name "resourcePartitionKey", it does not check case sensitivity. With the incorrect sensitivity, the returned UserPermission object has the value present but does not provide any security controls (dangerous situation #1)
Secondly, the input value is not validated for being of type array. Once again it is accepted and returned to you in the user permission object but again provides no security control (dangerous situation #2)
A full working example is below where the permission ID is called "read-collection" and the resourcePartitionKey is configured to 'rpk1' finally exhibits the expected behaviour of requiring "x-ms-documentdb-partitionkey" for the request and only returns values from the specified partition key.
POST https://accountname.documents.azure.com/dbs/dbName/users/userName/permissions HTTP/1.1
authorization: type%3dmaster%26ver%3d1.0%26sig<signature>
x-ms-version: 2017-02-22
x-ms-date: Thu, 16 Aug 2018 04:09:44 GMT
User-Agent: Mozilla/5.0 (Windows NT; Windows NT 10.0; en-AU) WindowsPowerShell/5.1.17134.165
Content-Type: application/json
Host: accountname.documents.azure.com
Content-Length: 215
{
"resource": "dbs/dbName/colls/collectionName/",
"id": "read-collection",
"resourcePartitionKey": [
"rpk1"
],
"permissionMode": "read"
}
If someone knows where to log a DCR or bug for the CosmosDB SQL Rest API, please let me know as without the proper validation during resource permission creation, resource tokens may be distributed to low trust clients that can gain unexpected full access to collection data.

Related

Authentication with Google Document AI (Form Parser API)

I have been trying to authenticate from the parser API without success.
I have set up the google service account and created two keys.I Have set up the owner role and downloaded the credential json file.
googleAuthR::gar_auth_service("D:/898 sample/document ai/form-898-scan-bd4b8b48b570.json")
library(daiR)
response1 <- dai_sync("D:/test file.pdf"
,
proj_id = get_project_id(path = "D:/crudentialabc123.json"),
proc_id = "e4xxxxxx",
loc = "us",
token = dai_token(
path = Sys.getenv("GSC_AUTH_FILE")
# scopes = "https://googleapis.com/auth/cloud-platform"
)
)
I keep getting the 403 permission denied error.
File submitted at 2022-04-10 05:17:57. HTTP status: 403 - unsuccessful.
Error: "Permission 'documentai.processors.processOnline' denied on resource '//documentai.googleapis.com/projects/projectname/locations/us/processors/e4xxxxxxx' (or it may not exist)."
Response [https://us-documentai.googleapis.com/v1/projects/projectname/locations/us/processors/e46888f802fea83d:process]
Date: 2022-04-10 05:17
Status: 403
Content-Type: application/json; charset=UTF-8
Size: 649 B
{
"error": {
"code": 403,
"message": "Permission 'documentai.processors.processOnline' denied on resource '//documentai.googleapis.com/projects/form-898-scan/locations/us/processors/e46...
"status": "PERMISSION_DENIED",
"details": [
{
"#type": "type.googleapis.com/google.rpc.ErrorInfo",
"reason": "IAM_PERMISSION_DENIED",
"domain": "documentai.googleapis.com",
...
Any help would be appreciated!
I would recommend reviewing this blog post about Google authentication using R.
https://cran.r-project.org/web/packages/googleAuthR/vignettes/google-authentication-types.html
Currently, Google Cloud doesn't have any client libraries for R, but the 3rd party packages listed should be able to provide a starting point.

Why "Invalid snak data" on updating wikibase?

I am trying to learn how to update values on Wikidata using the API. Login and csrf cookies work ok, but when I try to update a value I get an invalid-snak error.
The request body looks like this:
POST /w/api.php HTTP/1.1
Accept-Encoding: gzip
Content-Length: 178
User-Agent: Mojolicious (Perl)
Host: test.wikidata.org
Content-Type: application/x-www-form-urlencoded
Cookie: [omitted]
action=wbcreateclaim&bot=1&entity=Q3345&format=json&property=P9876&snaktype=value&token=[omitted]&value=%7B%22entity-type%22%3A%22Q1917%22%7D
and the response is:
{
"error": {
"code": "invalid-snak",
"info": "Invalid snak data.",
"messages": [
{
"name": "wikibase-api-invalid-snak",
"parameters": [],
"html": {
"*": "Invalid snak data."
}
}
],
"*": "See https://test.wikidata.org/w/api.php for API usage. Subscribe to the mediawiki-api-announce mailing list at <https://lists.wikimedia.org/mailman/listinfo/mediawiki-api-announce> for notice of API deprecations and breaking changes."
},
"servedby": "mw1386"
}
I've tried various ways to succeed with an update by changing the value - no results. The only update I succeeded with is one with snaktype=novalue - which would confirm that the issue is with the snak vaue alone.
So the question is, what's the right way to make an update to a snakvalue?
The problem is that you are stating value={"entity-type":"Q1917"}, but Q1917 is not an entity-type!
You should instead state value={"entity-type":"item","numeric-id":1917}.
For deepen the topic, see the Wikidata API's documentation.

Amazon Advertising API: ASINs report request returns “Missing campaign type”

Request to API-Endpoint:
POST https://advertising-api-eu.amazon.com/v2/asins/report
Official documentation:
https://advertising.amazon.com/API/docs/en-us/reference/sponsored-products/2/reports
Headers:
Authorization: Bearer Atza|xxxxxxxxxxxxxxxxxxxxx
Content-Type: application/json
Amazon-Advertising-API-ClientId: xxxxxxxxxxxxxxxxxxxxxxxxxx
Amazon-Advertising-API-SCOPE: xxxxxxxxxxxxxxxxxxxxxxx
Request:
{
"segment": "query",
"reportDate":"20200201",
"metrics": "campaignName,campaignId,adGroupName,adGroupId,keywordId,keywordText,asin,otherAsin,currency,matchType,attributedUnitsOrdered30d,attributedUnitsOrdered30dOtherSKU,attributedSales30dOtherSKU"
}
Response:
{
"code": "400",
"details": "Missing campaign type",
"requestId": "7Q8PMWM2618KAS0VEG87"
}
Question:
I think the error message is misleading (because i checked the documentation twice and because of my former experiences with the API).
But what is the real error? How can i get a ASINs report?
I asked Amazon Support and they replied:
"Asin report would need campaignType in the payload to succeed the operation. We have a documentation update pending on this. Please be noted that query segmentation is only allowed for keyword, target and productAds report. An example payload:-
GET https://advertising-api.amazon.com/v2/asins/report"
{
"reportDate":"20200201",
"campaignType": "sponsoredProducts",
"metrics":"campaignName,
campaignId,
adGroupName,
adGroupId,
keywordId,
keywordText,
asin,
otherAsin,
currency,
matchType,
attributedUnitsOrdered30d,
attributedUnitsOrdered30dOtherSKU,
attributedSales30dOtherSKU"
}

Integrating Contact Form 7 with third-party app

I am trying to send information from user submissions (Contact Form 7) to third-party app. I am using this plugin
https://wordpress.org/support/plugin/cf7-to-api/
The third-party app provided an access token and this example of creation request for me
curl -X "POST" "https://api.example.com/initial-params" \
-H 'Content-Type: application/json' \
-H 'X-Landing-Page-Access-Token: your-value-here ' \
-d $'{
"move": {
"date": "2018-09-01"
},
"consumer": {
"givenName": "Mike",
"phone": "234234242",
"email": "mike#example.com",
"familyName": "Simon"
},
"origin": {
"zip": 3245,
"beds": 8
},
"destination": {
"zip": 12342
}
}'
and this is their documentation
An end consumer enters details onto a landing page. Once all details have been entered, the landing page POSTs to our API's Initial Params endpoint. Our app stores the parameters and generates a unique identifier. Once the API call to create Initial Params succeeds, the landing page automatically redirects to the survey web app with the identifier set as a URL parameter (e.g., ?identifier=xxx... )
- Important : Our survey web app must have received this import in order for follow-up
messaging to work if the consumer drops off. As a result, it is recommended to automatically
redirect to our survey web app after the Initial Params have been created as opposed to
requiring a button click.
When our survey web app loads, it queries our API to retrieve the parameters. With the
parameter information, it then initializes the survey web app and API to the state specified in the
Initial Parameters. Each screen that has input completely satisfied is automatically skipped. The consumer finishes the process on our survey web app. One this identifier has been generated, the landing page can redirect to our survey web app. This identifier should be passed along to our survey web app via the identifier URL parameter, which will in turn allow the provided consumer details to be loaded inside our app. Example link: https://api.example.com/?identifier=xxx
This is a creation response example the third-party app also provided
HTTP/1.1 200 OK
Access-Control-Allow-Origin: *
Content-Type: application/json
Date: Wed, 18 Jul 2018 16:55:04 GMT
Server: nginx
Content-Length: 380
Connection: Close
{
"status": [
{
"type": "ok"
}
],
"identifier":
"some-unique-identifier",
"serverTime": "247.334 ms"
}
So, I used this https://api.example.com/initial-params as the URL to post to, added the access token using this piece of code in functions.php
add_filter( 'qs_cf7_api_get_args', 'add_http_header' );
function add_http_header( $args ) {
$args['headers']['X-Landing-Page-Access-Token'] = 'example-access-token';
return $args;
}
and I used this in the JSON template
-d $'{
"move": {
"date": "[date]"
},
"consumer": {
"givenName": "[givenName]",
"phone": "[phone]",
"email": "[email]",
"familyName": "[familyName]"
},
"origin": {
"zip": [zip1]
},
"destination": {
"zip": [zip2]
}
}'
My questions are:
How can I check the result I get from them, to see if they are receiving the info and generating the identifier?
How to redirect to their landing page with the identifier in the end when a form is submitted? That identifier is a variable and is unique each time, which means somehow I have to redirect to a variable after submission.
Any help is much appreciated.
Thank you!

PactNet Provider test fails because of 404 when running the test

I have a consumer that has successfully created a pact file:
{
"consumer": {
"name": "CakeService"
},
"provider": {
"name": "CoolPersonService"
},
"interactions": [
{
"description": "A GET request to get a person who is cool",
"providerState": "There is a person who has IsCool set to 'true'6",
"request": {
"method": "get",
"path": "/CoolPersonService/persons/e674a2d0-57e6-471d-96dd-a91c0077283a",
"headers": {
"X-Requested-With": "XMLHttpRequest",
"CallerName": "Pact_Test#Local"
}
},
"response": {
"status": 200,
"headers": {
"Content-Type": "application/json; charset=utf-8"
},
"body": {
"FirstName": "Some",
"LastName": "Name",
"IsCool": true
}
}
}
],
"metadata": {
"pactSpecification": {
"version": "2.0.0"
}
}
}
The problem is the test for the provider. It gets a 404 for
/CoolPersonService/persons/e674a2d0-57e6-471d-96dd-a91c0077283a
but if I send a GET to that route using an HTTP client, I get a 200 response and the expected data is returned.
Here's the output from the test run:
Test Name: EnsureSomethingApiHonoursPactwithConsumer
Test Outcome: Failed
Result Message:
Test method PactTests.PactTests.EnsureSomethingApiHonoursPactwithConsumer threw exception:
PactNet.PactFailureException: Pact verification failed. See output for details.
If the output is empty please provide a custom config.Outputters (IOutput) for your test framework, as we couldn't write to the console.
Result StandardOutput:
[2018-07-13 10:59:05] INFO WEBrick 1.3.1
[2018-07-13 10:59:05] INFO ruby 2.2.2 (2015-04-13) [i386-mingw32]
..........++++++
..........++++++
[2018-07-13 10:59:07] INFO
[2018-07-13 10:59:07] INFO WEBrick::HTTPServer#start: pid=109760 port=9222
[2018-07-13 10:59:07] ERROR Errno::ECONNRESET: An existing connection was forcibly closed by the remote host.
C:/redacted/PactTests/bin/Debug/pact-win32/lib/ruby/lib/ruby/2.2.0/openssl/buffering.rb:61:in `sysread'
C:/redacted/PactTests/bin/Debug/pact-win32/lib/ruby/lib/ruby/2.2.0/openssl/buffering.rb:61:in `fill_rbuff'
C:/redacted/PactTests/bin/Debug/pact-win32/lib/ruby/lib/ruby/2.2.0/openssl/buffering.rb:301:in `eof?'
C:/redacted/PactTests/bin/Debug/pact-win32/lib/vendor/ruby/2.2.0/gems/webrick-1.3.1/lib/webrick/httpserver.rb:80:in `run'
C:/redacted/PactTests/bin/Debug/pact-win32/lib/vendor/ruby/2.2.0/gems/webrick-1.3.1/lib/webrick/server.rb:191:in `block in start_thread'
INFO: Reading pact at C:/redacted/PactTests/Pacts/cakeservice-coolpersonservice.json
Verifying a pact between CakeService and CoolPersonService
Given There is a person who has IsCool set to 'true'6
A GET request to get a person who is cool
with GET /CoolPersonService/persons/e674a2d0-57e6-471d-96dd-a91c0077283a
returns a response which
DEBUG: Setting up provider state 'There is a person who has IsCool set to 'true'6' for consumer 'CakeService' using provider state server at https://localhost/CoolPersonService/provider-states
I, [2018-07-13T10:59:11.805597 #102868] INFO -- request: POST https://localhost/CoolPersonService/provider-states
D, [2018-07-13T10:59:11.805597 #102868] DEBUG -- request: User-Agent: "Faraday v0.15.0"
Content-Type: "application/json"
I, [2018-07-13T10:59:23.352124 #102868] INFO -- response: Status 200
D, [2018-07-13T10:59:23.352625 #102868] DEBUG -- response: content-type: "application/json; charset=utf-8"
server: "redacted"
x-powered-by: "redacted"
date: "Fri, 13 Jul 2018 08:59:23 GMT"
connection: "close"
content-length: "84"
has status code 200 (FAILED - 1)
has a matching body (FAILED - 2)
includes headers
"Content-Type" which equals "application/json; charset=utf-8" (FAILED - 3)
Failures:
1) Verifying a pact between CakeService and CoolPersonService Given There is a person who has IsCool set to 'true'6 A GET request to get a person who is cool with GET /CoolPersonService/persons/e674a2d0-57e6-471d-96dd-a91c0077283a returns a response which has status code 200
Failure/Error: expect(response_status).to eql expected_response_status
expected: 200
got: 404
(compared using eql?)
2) Verifying a pact between CakeService and CoolPersonService Given There
is a person who has IsCool set to 'true'6 A GET request to get a person who is cool with GET /CoolPersonService/persons/e674a2d0-57e6-471d-96dd-a91c0077283a returns a response which has a matching body
>Failure/Error: expect(response_body).to match_term expected_response_body, diff_options, example
Encoding::UndefinedConversionError:
"\xC3" from ASCII-8BIT to UTF-8
3) Verifying a pact between CakeService and CoolPersonService Given There is a person who has IsCool set to 'true'6 A GET request to get a person who is cool with GET /CoolPersonService/persons/e674a2d0-57e6-471d-96dd-a91c0077283a returns a response which includes headers "Content-Type" which equals "application/json; charset=utf-8"
Failure/Error: expect(header_value).to match_header(name, expected_header_value)
Expected header "Content-Type" to equal "application/json; charset=utf-8", but was "text/html; charset=utf-8"
1 interaction, 1 failure
Failed interactions:
To re-run just this failing interaction, change the verify method to '.Verify(description: "A GET request to get a person who is cool", providerState: "There is a person who has IsCool set to 'true'6")'. Please do not check in this change! # A GET request to get a person who is cool given There is a person who has IsCool set to 'true'6
Here's the test method for the provider:
[TestMethod]
[TestCategory("Pact")]
public void EnsureSomethingApiHonoursPactwithConsumer()
{
const string serviceUri = "https://localhost/CoolPersonService";
var config = new PactVerifierConfig
{
Verbose = true
};
IPactVerifier pactVerifier = new PactVerifier(config);
pactVerifier
//.ProviderState($"{serviceUri}/provider-states")
.ProviderState($"{serviceUri}/provider-states")
.ServiceProvider("CoolPersonService", serviceUri)
.HonoursPactWith("CakeService")
.PactUri(#"C:\repos\Pact\API_CoolPersonService\PactTests\Pacts\cakeservice-coolpersonservice.json")
.Verify();
}
If you do a GET to a resource, and you get a 404, to me it sounds like the expected data is not present on the server - and that implies that the provider state has not been set up correctly.
Please read about provider states here https://docs.pact.io/getting-started/provider-states and here https://docs.pact.io/implementation-guides/ruby/provider-states#non-ruby-applications
If you do a POST to the same route and receive the response you expected from a GET, it may be that you have just created a new resource, and it is returning the body of the newly created resource.
I see that you are also having some encoding issues (Encoding::UndefinedConversionError: "\xC3" from ASCII-8BIT to UTF-8) I believe this has been fixed in the latest version of the underlying library (called the "pact standalone") so please ensure you have the latest version of pact-net. If you already do have the latest version of pact-net, then please raise an issue for the standalone to be upgraded.
For those still stumped by the issue, the "\xC3" from ASCII-8BIT to UTF-8 error also happens because the response by your provider couldn't be encoded e.g. your provider returns a 500 with a text/html response.

Resources