Im trying to automate the configuration of an enterpise application via the Azure Graph API.
Specifically, its the Azure Palo Alto Admin UI - https://learn.microsoft.com/en-us/azure/active-directory/saas-apps/paloaltoadmin-tutorial#configure-azure-ad-sso
Ive managed to get this working via the frontend, but im having trouble configuring the custom claims via the Graph Api.
For now, i just want to use a string claim in the custom claim as the customadmin value with a hardcoded value for the admin role
When creating via the portal, you can easily enter a string value as the source type of the claim.
However, via the Graph API the source type must be user, resource, audience, company or transformation.
https://learn.microsoft.com/en-us/azure/active-directory/develop/active-directory-claims-mapping#claim-schema-entry-elements
It seems that you can create a string type of transformation and then link the transformation into the main ClaimsSchema.
There is a similar example documented here https://learn.microsoft.com/en-us/graph/api/resources/claimsmappingpolicy?view=graph-rest-1.0#example-definition-that-uses-a-claims-transformation
But I cannot get the example to work. Even with a bit of massaging, the example fails. This is what ive been trying:
cat <<- EOF > claims.json
{
"definition": [
"{\"ClaimsMappingPolicy\":{
\"Version\":1,
\"IncludeBasicClaimSet\":\"true\",
\"ClaimsSchema\":[
{\"Source\":\"user\",\"ID\":\"extensionattribute1\"},{\"Source\":\"transformation\",\"ID\":\"DataJoin\",\"TransformationId\":\"JoinTheData\",\"JwtClaimType\":\"JoinedData\"}
],
\"ClaimsTransformation\":[
{\"ID\":\"JoinTheData\",\"TransformationMethod\":\"Join\",\"InputClaims\":[{\"ClaimTypeReferenceId\":\"extensionattribute1\",\"TransformationClaimType\":\"string1\"}], \"InputParameters\": [{\"ID\":\"string2\",\"Value\":\"sandbox\"},{\"ID\":\"separator\",\"Value\":\".\"}],\"OutputClaims\":[{\"ClaimTypeReferenceId\":\"DataJoin\",\"TransformationClaimType\":\"outputClaim\"}]}
]
}}"
],
"displayName": "Azure Reference Claim",
"isOrganizationDefault": false
}
EOF
az rest --method post --headers Content-type="application/json" --url "https://graph.microsoft.com/v1.0/policies/claimsMappingPolicies" --body #claims.json
Ive tried both the v1.0 and beta APIs but they both have the same behaviour
Which returns with the following error:
Bad Request({
"error": {
"code": "Request_BadRequest",
"message": "Property has an invalid value.",
"innerError": {
"date": "2020-09-01T13:03:10",
"request-id": "bc7cf58e-fe6d-47d1-b1e5-cae43326864f"
}
}
})
I was able to get the rest of the Palo Alto claim working (excluding the custom string) with the following:
{
"definition": [
"{\"ClaimsMappingPolicy\":{
\"Version\":1,
\"IncludeBasicClaimSet\":\"true\",
\"ClaimsSchema\": [{\"Source\":\"user\",\"ID\":\"userprincipalname\",\"SamlClaimType\":\"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier\"},{\"Source\":\"user\",\"ID\":\"givenname\",\"SamlClaimType\":\"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname\"},{\"Source\":\"user\",\"ID\":\"displayname\",\"SamlClaimType\":\"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name\"},{\"Source\":\"user\",\"ID\":\"surname\",\"SamlClaimType\":\"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname\"},{\"Source\":\"user\",\"ID\":\"userprincipalname\",\"SamlClaimType\":\"username\"}]
}}"
],
"displayName": "Palo Alto Claims Policy",
"isOrganizationDefault": false
}
And i was able to create a CustomString transformation which isnt linked to anything with the following:
{
"definition": [
"{\"ClaimsMappingPolicy\":{
\"Version\":1,
\"IncludeBasicClaimSet\":\"true\",
\"ClaimsTransformation\":[{\"ID\":\"CreateTermsOfService\",\"TransformationMethod\":\"CreateStringClaim\",\"InputParameters\": [{\"ID\":\"value\",\"DataType\":\"string\", \"Value\":\"sandbox\"}],\"OutputClaims\":[{\"ClaimTypeReferenceId\":\"TOS\",\"TransformationClaimType\":\"createdClaim\"}]}]
}}",
],
"displayName": "sdfa",
"isOrganizationDefault": false
}
However, when i try them together in the format of the example I get an error.
{
"definition": [
"{\"ClaimsMappingPolicy\":{
\"Version\":1,
\"IncludeBasicClaimSet\":\"true\",
\"ClaimsSchema\": [
{\"Source\":\"user\",\"ID\":\"userprincipalname\",\"SamlClaimType\":\"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier\"},{\"Source\":\"user\",\"ID\":\"givenname\",\"SamlClaimType\":\"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname\"},{\"Source\":\"user\",\"ID\":\"displayname\",\"SamlClaimType\":\"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name\"},{\"Source\":\"user\",\"ID\":\"surname\",\"SamlClaimType\":\"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname\"},{\"Source\":\"user\",\"ID\":\"userprincipalname\",\"SamlClaimType\":\"username\"},{\"Source\":\"transformation\",\"TransformationID\":\"xxxxxxxxx\",\"ID\":\"DataJoin\",\"SamlClaimType\":\"test\"}
],
\"ClaimsTransformation\":[
{\"ID\":\"xxxxxxxxx\",\"TransformationMethod\":\"CreateStringClaim\",\"InputParameters\": [{\"ID\":\"value\",\"DataType\":\"string\", \"Value\":\"sandbox\"}],\"OutputClaims\":[{\"ClaimTypeReferenceId\":\"DataJoin\",\"TransformationClaimType\":\"createdClaim\"}]}
]
}}"
],
"displayName": "Palo Alto Claims Policy",
"isOrganizationDefault": false
}
Which returns the same unhelpful error:
Bad Request({
"error": {
"code": "Request_BadRequest",
"message": "Property has an invalid value.",
"innerError": {
"date": "2020-09-01T13:03:10",
"request-id": "bc7cf58e-fe6d-47d1-b1e5-cae43326864f"
}
}
})
Any ideas what i am doing wrong? Im trying to base off of the example, which i cant get working.
I do not want to use powershell, i want to be able to automate via my desktop terminal.
I imagine i can avoid this situation and get the PA to integrate with AAD without a hardcoded value, but i feel that i should be able to get this working this way.
The mandatory encoding of the ClaimMappingPolicy object makes it quite fiddely to develop, so its possible there is a problem there somewhere.
Ive also tried just creating the ClaimsSchema without the ClaimsTransformation and then running a PATCH to amend the object with the transformed object, but it just overwrites the whole ClaimsMappingPolicy object rather than adding just the extra field.
When I remove the transformation source from the ClaimsSchema the request succeeds.
cat <<- EOF > claims.json
{
"definition": [
"{\"ClaimsMappingPolicy\":{
\"Version\":1,
\"IncludeBasicClaimSet\":\"true\",
\"ClaimsSchema\": [
{\"Source\":\"user\",\"ID\":\"userprincipalname\",\"SamlClaimType\":\"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier\"},{\"Source\":\"user\",\"ID\":\"givenname\",\"SamlClaimType\":\"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname\"},{\"Source\":\"user\",\"ID\":\"displayname\",\"SamlClaimType\":\"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name\"},{\"Source\":\"user\",\"ID\":\"surname\",\"SamlClaimType\":\"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname\"},{\"Source\":\"user\",\"ID\":\"userprincipalname\",\"SamlClaimType\":\"username\"}
],
\"ClaimsTransformation\":[
{\"ID\":\"xxxxxxxxx\",\"TransformationMethod\":\"CreateStringClaim\",\"InputParameters\": [{\"ID\":\"value\",\"DataType\":\"string\", \"Value\":\"sandbox\"}],\"OutputClaims\":[{\"ClaimTypeReferenceId\":\"DataJoin\",\"TransformationClaimType\":\"createdClaim\"}]}
]
}}"
],
"displayName": "Palo Alto Claims Policy",
"isOrganizationDefault": false
}
EOF
But there isnt an association between the ClaimsSchema and the ClaimsTransformation. This hints at a problem with the ClaimsSchema object
{\"Source\":\"transformation\",\"TransformationID\":\"xxxxxxxxx\",\"ID\":\"DataJoin\",\"SamlClaimType\":\"test\"}
But this looks suitable when looking at the documentation and the (possibly broken) reference example.
Providing information in answer as its too long to comment it.Please try this below query in Graph explorer
Post https://graph.microsoft.com/beta/policies/claimsMappingPolicies
{"definition":["{\"ClaimsMappingPolicy\":{\"Version\":1,\"IncludeBasicClaimSet\":\"true\", \"ClaimsSchema\":[{\"Source\":\"user\",\"ID\":\"extensionattribute1\"},{\"Source\":\"transformation\",\"ID\":\"DataJoin\",\"TransformationId\":\"JoinTheData\",\"JwtClaimType\":\"JoinedData\"}],\"ClaimsTransformations\":[{\"ID\":\"JoinTheData\",\"TransformationMethod\":\"Join\",\"InputClaims\":[{\"ClaimTypeReferenceId\":\"extensionattribute1\",\"TransformationClaimType\":\"string1\"}], \"InputParameters\": [{\"ID\":\"string2\",\"Value\":\"sandbox\"},{\"ID\":\"separator\",\"Value\":\".\"}],\"OutputClaims\":[{\"ClaimTypeReferenceId\":\"DataJoin\",\"TransformationClaimType\":\"outputClaim\"}]}]}}"],"displayName":"TestclaimsPolicy","isOrganizationDefault":false}
Post https://graph.microsoft.com/beta/policies/claimsMappingPolicies
{"definition":["{\"ClaimsMappingPolicy\":{\"Version\":1,\"IncludeBasicClaimSet\":\"true\",\"ClaimsSchema\": [{\"Source\":\"user\",\"ID\":\"userprincipalname\",\"SamlClaimType\":\"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier\"},{\"Source\":\"user\",\"ID\":\"givenname\",\"SamlClaimType\":\"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname\"},{\"Source\":\"user\",\"ID\":\"displayname\",\"SamlClaimType\":\"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name\"},{\"Source\":\"user\",\"ID\":\"surname\",\"SamlClaimType\":\"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname\"},{\"Source\":\"user\",\"ID\":\"userprincipalname\",\"SamlClaimType\":\"username\"}],\"ClaimsTransformation\":[{\"ID\":\"CreateTermsOfService\",\"TransformationMethod\":\"CreateStringClaim\",\"InputParameters\": [{\"ID\":\"value\",\"DataType\":\"string\", \"Value\":\"sandbox\"}],\"OutputClaims\":[{\"ClaimTypeReferenceId\":\"TOS\",\"TransformationClaimType\":\"createdClaim\"}]}]}}"],"displayName":"Test1234","isOrganizationDefault":false}
for more information on CreateTermsOfService please refer to this document
I am using this tutorial to link Rekognition results to a DynamoDB table.
It is giving me this error:
{
"errorMessage": "Unable to get object metadata from S3. Check object key, region and/or access permissions.",
"errorType": "InvalidS3ObjectException",
"stackTrace": [
"Request.extractError (/var/runtime/node_modules/aws-sdk/lib/protocol/json.js:48:27)",
"Request.callListeners (/var/runtime/node_modules/aws-sdk/lib/sequential_executor.js:105:20)",
"Request.emit (/var/runtime/node_modules/aws-sdk/lib/sequential_executor.js:77:10)",
"Request.emit (/var/runtime/node_modules/aws-sdk/lib/request.js:683:14)",
"Request.transition (/var/runtime/node_modules/aws-sdk/lib/request.js:22:10)",
"AcceptorStateMachine.runTo (/var/runtime/node_modules/aws-sdk/lib/state_machine.js:14:12)",
"/var/runtime/node_modules/aws-sdk/lib/state_machine.js:26:10",
"Request.<anonymous> (/var/runtime/node_modules/aws-sdk/lib/request.js:38:9)",
"Request.<anonymous> (/var/runtime/node_modules/aws-sdk/lib/request.js:685:12)",
"Request.callListeners (/var/runtime/node_modules/aws-sdk/lib/sequential_executor.js:115:18)"
]
}
The code used from GitHub is this.
I made sure the region-name is the same for the lambda-bucket and the table.
I am a starter in this, so any help will be appreciated!
Thanks!
Edit:
I made some modifications and now it is giving me this:
{
"errorMessage": "Requested resource not found",
"errorType": "ResourceNotFoundException",
"stackTrace": [
"Request.extractError (/var/runtime/node_modules/aws-sdk/lib/protocol/json.js:48:27)",
"Request.callListeners (/var/runtime/node_modules/aws-sdk/lib/sequential_executor.js:105:20)",
"Request.emit (/var/runtime/node_modules/aws-sdk/lib/sequential_executor.js:77:10)",
"Request.emit (/var/runtime/node_modules/aws-sdk/lib/request.js:683:14)",
"Request.transition (/var/runtime/node_modules/aws-sdk/lib/request.js:22:10)",
"AcceptorStateMachine.runTo (/var/runtime/node_modules/aws-sdk/lib/state_machine.js:14:12)",
"/var/runtime/node_modules/aws-sdk/lib/state_machine.js:26:10",
"Request.<anonymous> (/var/runtime/node_modules/aws-sdk/lib/request.js:38:9)",
"Request.<anonymous> (/var/runtime/node_modules/aws-sdk/lib/request.js:685:12)",
"Request.callListeners (/var/runtime/node_modules/aws-sdk/lib/sequential_executor.js:115:18)"
]
}
The fact that you're seeing ResourceNotFoundException suggests a couple of potential causes:
the Lambda function could not find the DynamoDB table: make sure that you modified config,js to include the name of the DynamoDB table correctly, by setting config.dynamo.tableName = '<your table>'
Rekognition could not read the image from S3: make sure that the image filename is of the form faces.jpg rather than test faces.jpg (which gets escaped to test+faces.jpg)
There are a couple of reasons why this could be happening:
1) The resource definitely does not exist. Triple-check Bucket name, DynamoDB Table name, regions, etc.
2) It's very likely that your function lacks permissions. Check the IAM Role that your Lambda function is using and attach the right policies to it. On this case, your function needs access to S3, DynamoDB and Rekognition. Make sure all of these policies are attached to the IAM role.
I'm facing issue, my model named Provider and i called a GET method it shows :
{
"error": {
"name": "Error",
"status": 401,
"message": "Authorization Required",
"statusCode": 401,
"code": "AUTHORIZATION_REQUIRED",
"stack": "Error: Authorization Required\n at /home/developer/node_modules/loopback/lib/application.js:396:21\n at /home/developer/node_modules/loopback/lib/model.js:322:7\n at /home/developer/node_modules/loopback/common/models/acl.js:472:23\n at /home/developer/node_modules/async/dist/async.js:3679:13\n at /home/developer/node_modules/async/dist/async.js:952:25\n at iteratorCallback (/home/developer/node_modules/async/dist/async.js:997:17)\n at /home/developer/node_modules/async/dist/async.js:847:20\n at /home/developer/node_modules/async/dist/async.js:3676:17\n at /home/developer/node_modules/async/dist/async.js:339:31\n at /home/developer/node_modules/loopback/common/models/acl.js:454:17\n at /home/developer/node_modules/loopback/common/models/role.js:272:21\n at /home/developer/node_modules/async-listener/glue.js:188:31\n at _combinedTickCallback (internal/process/next_tick.js:67:7)\n at process._tickDomainCallback [as _tickCallback] (internal/process/next_tick.js:122:9)"
}
}
I'm dealing with a client whose project was abandoned by the developer . since i'm new to LOOPBACK i was confused totally and so need your HELP very badly ...
Thanks in advance ...
Check your model common/models/Provider.json file
Add the specific method permission:
"acls": [
{
"principalType": "ROLE",
"principalId": "$everyone",
"permission": "ALLOW"
}
]
This will make all your model methods public without any authentication, for more information about ACL, read the docs:
https://docs.strongloop.com/display/public/LB/Controlling+data+access