How to set the access control for microservices - javascript

I use Loopback Framework to create several services and I use an api gateway (tyk) to manage them.
Unfortunately I do not see how to set the access control for each of them.
I do not want a user to access data that does not belong to him.
Many thanks,

you can easily use two methods to secure your model.
1.From model.json file
inside your model model.json you can include ACL objects.
"acls": [{
"accessType": "EXECUTE",
"principalType": "ROLE",
"principalId": "$authenticated",
"permission": "ALLOW"
}, {
"accessType": "*",
"principalType": "ROLE",
"principalId": "$everyone",
"permission": "DENY"
}]
2.Using operational hooks in model.js file
you can use operational hooks to manipulate security.
example
Template.observe('access', function (ctx, next) {
if(ctx.options.team){
var teamId = ctx.options.team.teamId;
ctx.query.where= ctx.query.where || {or :[ {user_created : 0},{teamId : teamId}]} ;
next();
}
});
hope this will be helpful.

Related

How do I find out what is actually set to "${ ... }" in AWS IAM policy?

I'm trying to limit access to items in Dynamo DB tables based on Cognito User Pool using Lambda IAM role policy.
In the process, I'm struggling to find what is actually set to "${cognito-identity.amazonaws.com:aud}" in the Lambda IAM policy below.
{
"Effect": "Allow",
"Action": [
"dynamodb:Scan",
"dynamodb:Query",
"dynamodb:GetItem",
"dynamodb:PutItem",
"dynamodb:UpdateItem",
"dynamodb:DeleteItem",
"dynamodb:DescribeTable"
],
"Condition": {
"ForAllValues:StringEquals": {
"dynamodb:LeadingKeys": "${cognito-identity.amazonaws.com:aud}"
}
},
"Resource": "arn:aws:dynamodb:ap-southeast-2:*:*"
}
I'm assuming it is either Application Client ID or Identity Pool ID like "ap-southeast-2:xxxxxxxx-aaaa-bbbb-cccc-123456789012", but is there a way to output what is actually set to "${cognito-identity.amazonaws.com:aud}" on runtime to confirm?
I am relatively new to AWS.
Updated - Additional Information
Just before calling the Lambda via API Gateway, I can see something like "xxxxxxxxnv0ff03e9joqh3om3h" (my App Client ID) using below:
const session = await Auth.currentSession();
alert(session.idToken.payload.aud); //something like "xxxxxxxxnv0ff03e9joqh3om3h"
However, I get AccessDeniedException in Lambda DynamoDB query with the App Client ID.
ExpressionAttributeValues: {
":partitionkey": "xxxxxxxxnv0ff03e9joqh3om3h",
},
I can avoid AccessDeniedException error by changing the IAM Policy to:
"Condition": {
"ForAllValues:StringEquals": {
"dynamodb:LeadingKeys": "123abc"
}
},
and my Lambda DynamoDB query to:
ExpressionAttributeValues: {
":partitionkey": "123abc",
},
I've tried Cognito Identity Pool ID too, but no luck.
The mapped values for aud and sub are provider specific and outlined in the documentation.
In the case of Cognito Userpool federation it will be set to the client ID.

How to access oauthIdToken returned from Firebase?

I'm trying to get the oauthIdToken of the result fetched from signing with firebase using signInWithCredential. I get the following back upon a successful login:
user Object {
"additionalUserInfo": bg {
"isNewUser": false,
"profile": Object {
"at_hash": "aWhmsdfeef32388EYD8YA",
"aud": "100423452193-gvmasfasdfasdfasfda7ee0.apps.googleusercontent.com",
"azp": "100406623293-gvmt0erkkob6asdfadfi7ee0.apps.googleusercontent.com",
"email": "fake#gmail.com",
"email_verified": true,
"exp": 1579142529,
"family_name": "last name",
"given_name": "first name",
"iat": 1579138929,
"iss": "https://accounts.google.com",
"locale": "en",
"name": "first last name",
"nonce": "Ow_sVcasdf50LdbHdTaro",
"picture": "https://lsfasfa.googleusercontent.com/-iKnasfasdf34/AAAAAAAAAAI/AAAAAAAAAAA/ACHi3re9asdfas7_Erg/s96-c/photo.jpg",
"sub": "100824234342680931658",
},
"providerId": "google.com",
},
"credential": Object {
"oauthAccessToken": "ya29.Il-5B47AOKYEQ5NYikv93gYyyhWu_2FEHEaadfaasfasdfasdfBVJCDXG3HJ9MdqalyyxvZ-6jMoqRsaGzhPUg6Cg862vF25xocHR6rnbh_-HuP2MMey4s59Gx8fXLwgQ99dQ",
"oauthIdToken": "eyJhbGciOiJSUzsdfagyZDgyMDQwM2VlODUxOGM0YWFiYjJiOWZlMzEwY2FjMTIiLCJ0eXAiOiJKV1QifQ.eyJpc3MiOiJodHRwczovL2FjY291joiZW4iLCJpYXQiOjE1NzkxMzg5MjksImV4cCI6MTU3OTE0MjUyOX0.i-YiWbokasfiP_-xWCHJUyT_aLWp7eb3YCE6mzRUbbuKsdfsdfHptczrMXB5vMZY_5JFp8ZD2zxoNlvhTpuMY3B_zw_5Irk6HzuHGHXyAgzNJjh5n6cYR8gOiOsfsdfcKATpHcG7H_gOCwns_fI44I820qcmrogaEXuW-i3u9X5aXbTYqW5EaZQvQzuHkYHO2VWoktOTZsfsdfsfOaYYGU-tqW-ygAB_aWD7VPjIuUY4ySPF4k6IRR1x3ZysfdsdfdGGarX3isPGxMrDMtbRtsfsdfVaKsZdRtCpbfNUbFO8NR6x-pIvKsdfA",
"stsTokenManager": Object {
"accessToken": "eyJhbGciOiJSUzI1NiIsASDAFASFVmZTJlZDQyOWI3MzY0M2Y2NTEiLCJ0eXAiOiJKV1QifQ.eyJuYW1lIjoicmVudGVyaWkgcmVudGVyaGUuY29tIn19.n7z7HlL9lU7VEOA4fGIHvE9UMLSu5uo1rpfTm6m-N5A8CaKQaDu96sAvsG8iOVx8PYnytadffsafSRHyJoS0bzZbpQS6-YItdM5bIPxLMTFYEb0-Ho-tPnhRBSfWfPqJnK0c18YBFtHTG-0TvLNppmuZFG9AJjZZr0ASIkoOWmkI0gdOUAKBkutwMb3oitxeorT-pUdtKB5Rk23ekewz05oi7R5TI4xpBX5LsPvqaCqI4S5wxHe_BilRiiMhxd_lINdWftEkpctKSApJubML7mB9A",
"apiKey": "AIzaSysdfsdfsiWO7_2buk",
"expirationTime": 1579142530341,
"refreshToken": "AEu4IL01n_G6c4_Wg6fzseXRGPJHEAJnhzw7GLZVTS4RICikJ8PUgmmtNWXjcttOSbmYVCJDzGluUvTNKPHa4aS8gG0R3ijmrvPpcyJFPWZ5dRRDIlzxuoSyt70mewdRYgK4Eao7W21550slj7qHu8ZT_1bACJb31e_y7UnL2QjJEuvKwcWII8v8mgMPpYC2RH6fKg0Xrv9XLBgTxso25KfDrlfHBfYp4t35CzcVqODl71663_xV0WHhQ5gpv1hW0N39MMU5S0UEbQ_FnMmcJUFygaRvHndj2yNVhGwv_Re0uut3hUanPO_bo6OT4VEgIEEZ6cuiq8jzpH_T7d6bwI9eLZNS6IC1Fu8EJFmUWAtsdyBErq0s39gj2uta0uqLIGP_wlP5F_eDiw",
},
"tenantId": null,
"uid": "KlGB4adfadfn9ktr1",
},
Trying to access oauthIdToken with console.log(result.credential.oauthIdToken) inevitably provides null even though the variable is clearly present. I'm assuming this is similar to getting the accessToken within stsTokenManager where you can only get it using the method getIdToken() and credential.stsTokenManager.accessToken provides null.
How do I access oauthIdToken?
It took me a day to sort this one out. I was looking at using promises and found the answer by logging the parts of the object.
The output of printing out the result object is very confusing. The issue is that the JSON object representation has keys which don't correspond to the variables on the object. If you use console.log(JSON.stringify(result.credential)) rather than
console.log(JSON.stringify(result)) you will see the different variable names.
To see the OAuth Identity Token use console.log(console.log(result.credential.idToken)) without the oauth prefix. Likewise the access token doesn't have the oauth prefix.
It is important to know that in the Google/Firebase world there are two different types of identity token. The Firebase identity token is obtained from user.getIdToken(). It is sent to the server to allow the client to be verified. Its audience in the project identifier. The other type, which is the subject of the question, is the identity token generated by the Auth provider. If the Auth Provider is Google then this is the token you have to use to authenticate against Cloud Functions and Cloud Run services. The token needs to be sent in a Authorization: Bearer idtoken header on the request.

Access denied when uploading S3 Objects

I'm following this tutorial of adding/listing objects from S3.
At first, I had problem to list objects because of Access Denied error, so I found that I have to to add additional permission s3:ListBucket and resource arn:aws:s3:::my-bucket to the role created by cognito to unauth user:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:PutObject",
"s3:GetObject",
"s3:ListBucket",
"s3:DeleteObject"
],
"Resource": [
"arn:aws:s3:::my-bucket",
"arn:aws:s3:::my-bucket/*"
]
}
]
}
Now, when I try to upload a file, I'm getting another Access Denied.
Am I doing something wrong or this tutorial has so many errors?
Additional Checks:
bucket has CORS
I didn't change any permissions of bucket after creating it (everything default)
I'm using proper Cognito Identity Pool ID ( I can list albmus )
I can delete album
After Access Denied error I can see that there is new identity in cognito unauth, so script works properly.
Owner of the bucket (me) has read/write access to the bucket
I'm not sure how cognito works internally and it might be playing with the ACL of the s3 object. So, adding s3:PutObjectAcl and s3:GetObjectAcl operations access might help. Additionally, if your code is doing multipart uploads to S3, you should consider adding s3:ListBucketMultipartUploads operation access. s3:PutObject operation already adds the permissions for Initiate Multipart Upload, Upload Part, Complete Multipart Upload.
Add IAM role with the policy, this will enable the user to upload any file with API or by the console.
{
"Version": "2012-10-17",
"Id": "1",
"Statement": [
{
"Sid": "1",
"Effect": "Allow",
"Principal": {
"AWS": [
"arn:aws:iam::777777:user/myuser"
]
},
"Action": [
"s3:ListBucket",
"s3:PutObject",
"s3:PutObjectAcl",
"s3:GetObject",
"s3:DeleteObject",
"s3:GetObjectAcl"
],
"Resource": [
"arn:aws:s3:::bucketname/*",
"arn:aws:s3::: bucketname"
]
}
}

Firehose is unable to assume role

I'm trying to use Firehose API (JS) and I keep getting the following error:
"InvalidArgumentException: Firehose is unable to assume role
arn:aws:iam::XXXXXXXXXX:role/NAME. Please check the role provided.
I check the role and I have set my custom policy to include all resources for STS and Firehose action. I have no clue why this error exists if I'm allowing AssumeRole under STS.
Method Calling
The method I'm using is createDeliveryStream(params = {}, callback) with S3DestinationConfiguration.
Policy JSON
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": [
"iam:*",
"kinesisvideo:*",
"s3:PutAccountPublicAccessBlock",
"s3:GetAccountPublicAccessBlock",
"s3:ListAllMyBuckets",
"s3:*",
"firehose:*",
"sts:*",
"s3:HeadBucket"
],
"Resource": "*"
}
]
}
Please check the trust relationship defined in the IAM role and verify that it is set to firehose.amazonaws.com. Policy defined in Trust relationship enables services to assume the role. For Kinesis Firehose, refer this document which contains details about IAM roles for Firehose. Refer "Grant Kinesis Data Firehose Access to an Amazon S3 Destination" section in the document which mentions about trust policy.

Cannot Send Mandrill Handlebars Template API

I am trying to access a Mandrill template which I made using their template builder in the Mandrill app (mandrillapp.com/templates).
As I read their documentation I am led to make an Ajax call as such:
{
"key": "<my api key>",
"template_name": "<my template name as defined in Mandrill templates>",
"template_content":[],
"message": {
"from_email": "<my from email>",
"to": <[an array of emails defined above]>,
"subject": "<my subject>",
"merge":true,
"global_merge_vars":[
{
"name": "visitorFirst",
"content": visitorFirst
},
"name": "visitorLast",
"content": visitorLast
},
{
"name": "visitorEmail",
"content": visitorEmail
}
]
}
This returns a 500 error. When I put the content inside "template_content" (which documentation says not to do for handlebars, it at least sends, but does not fill any of the merge variables. I have already set Mandrill to expect Handlebars, not Mailchimp variables.
What am I doing wrong?
Change
"template_content":[]
To
"template_content":null
Problem solved.

Categories

Resources