CouchDB and PouchDB plain users can create Databases - couchdb

I don't want normal users to be able to create Databases.
In the Futon Screen /_utils, when logged in as a plain user, everything functions as expected. Only Admins can create Databases.
But when I sync my pouchDB with couchDB, plain users can also create (replicate?) Database. I want the adding of new Databases only to be restricted to Admin users.
Also I just noticed that existing DB also get edited even when user is restricted.
How can I fix this?
var remoteCouch = http://testuser:testuser#{domain}.iriscouch.com/testdb;
PouchDB.debug.disable();
if (remoteCouch) {
sync();
} else {
console.log("No remote server.");
}
function sync() {
var opts = {live: true};
db.replicate.to(remoteCouch, opts, syncError);
db.replicate.from(remoteCouch, opts, syncError);
}
EDIT
Testuser is also not in /_config/admins
Testuser:
{
"_id": "org.couchdb.user:testuser",
"_rev": "1-7d28b3388a62cfca103cbe3642549bee",
"password_scheme": "pbkdf2",
"iterations": 10,
"type": "user",
"name": "testuser",
"roles": [
"testuser"
],
"derived_key": "2181a44141d6d6aa2061bb2c5c057451acc6461e",
"salt": "2184888b099f37605feca0a22e5b6bb9"
}

Is your CouchDB in admin party mode? If it's not, then only admins should be able to create databases, whether it's via Futon or PouchDB.
PouchDB isn't doing anything special; you can simulate what PouchDB is doing by using curl:
curl -X PUT http://someuser:somepassword#path.to.couchdb.com:5984/somedatabase
Are you sure your testuser isn't an admin? If the user that you give to PouchDB is an admin, then yes, users will be able to create their own databases.
More info on authentication can be found here: https://github.com/nolanlawson/pouchdb-authentication#couchdb-authentication-recipes

Related

How to do DynamoDB Fine-Grained Access Control?

First time posting a question so if I am not explaining properly please let me know. I am still very new to AWS and trying my best to learn.
MAIN QUESTION: What is the simplest way for me to test that the following setup is working as intended?
I was working with AWS DynamoDB trying to follow this idea:
https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/specifying-conditions.html
Where each UserId will be their partition key and they will only be able to read, write and delete information on their specific row/items.
I first create a table using the same name GameScores
dynamodb table image
I also create a user pool called "gamers" with all default setting.
enter image description here
I create a policy using the policy they have on the documention and call it "dynmodbgametable" the only thing I changed was the "Resource" to match the ARN of the dynamoDB "GameScores" I just created.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowAccessToOnlyItemsMatchingUserID",
"Effect": "Allow",
"Action": [
"dynamodb:GetItem",
"dynamodb:BatchGetItem",
"dynamodb:Query",
"dynamodb:PutItem",
"dynamodb:UpdateItem",
"dynamodb:DeleteItem",
"dynamodb:BatchWriteItem"
],
"Resource": [
"arn:aws:dynamodb:us-..rest of arn../GameScores"
],
"Condition": {
"ForAllValues:StringEquals": {
"dynamodb:LeadingKeys": [
"${www.amazon.com:user_id}"
],
"dynamodb:Attributes": [
"UserId",
"GameTitle",
"Wins",
"Losses",
"TopScore",
"TopScoreDateTime"
]
},
"StringEqualsIfExists": {
"dynamodb:Select": "SPECIFIC_ATTRIBUTES"
}
}
}
]
}
I create a role. clicking Web identity for type of trusted entity and for the Choose a web identity provider I select Amazon Cognito and Identity Pool ID as the pool id from user pool "gamers" Pool id and then attach the policy I just created called "dynmodbgametable". I call the role "GameRole"
enter image description here
I go ahead and create two users in the "gamer" user pool.
At this point I don't know what I am suppose to do to test it to see if I have even followed the intructions propertly. I started setting up this Nodejs script to test and it works of putting stuff and getting stuff from the database, but I know it is using my default root creditials that are saved on my local machine. I think I am suppose to setup the "AWS.config.credentials" to something that would include the userpool and put in one of the usernames with their associated password. But I haven't had much luck figuring out how exactly I am suppose to do that. Was it nesscessary to to create a client app for the "gamers" user pool as well before this will work?
Here is the little script I was trying if that somehow helps.
var AWS = require("aws-sdk");
AWS.config.update({ region: "us-east-2" });
var ddb = new AWS.DynamoDB({ apiVersion: "2012-08-10" });
var params = {
TableName: "GameScores",
Item: {
UserId: { S: "user id" },
GameTitle: { S: "hobo" },
},
};
ddb.putItem(params, function (err, data) {
if (err) {
console.log("Error", err);
} else {
console.log("Success", data);
}
});
I don't really know how to obtain "${www.amazon.com:user_id}" and where or how to pass it to and from. Is there some endpoint on the database itself? Am I suppose to create some kind of endpoint to point to? I just know that this is the variable that is suppose to determine the partition key.
If I can figure out how to test that it is working, I feel some of this will click for me. Right now I feel like I am not quite understanding what is going on conceptually. All the YouTube videos, documents and other Stack overflow posts I have read online only seem to talk about this on a higher level or are not within the scope of what I am trying to do.
Thanks for any help that can be provided! I will be sure to edit this if something is missing.
EXTRA INFO PROBABLY NOT NEEDED: I currently have an AWS Amplify web application that has a working interface that has working authentication with a user pool. I would like to add this ability of fine grained access control so that when a user logs in, they would have access to edit their profile information (name, age etc) and not be able to view other profiles information. If I can get a working prototype of this fine grained access control stuff, I should be able to figure out how to get it working for my Amplify application.
For anyone that happens to stumble onto my post, I ended up going a slightly different route. It may not be useful for you but it is what solved my problem.
Because I was using AWS Amplify, I reached out to their discord (shout out to undef_obj for answering me!) he said the following:
looking at your link, you're attempting to leverage the IAM policy variables for Cognito Identity and craft your own access control matrix solution. While this is possible, it's going to be a lot of effort and testing with potential for security issues if something is implemented wrong. Assistance with that is outside the scope of the Amplify framework. However, if you're looking for fine grained authorization with Amplify this is built into the GraphQL Transformer #auth directive and I'd recommend looking at that. There are plenty of examples showing how to setup a React app to an Amplify GraphQL endpoint which uses AWS AppSync and DynamoDB as the backing store.
So I looked into this and found that using AWS AppSync worked for me!
I went to THIS LINK and followed some of the instructions there. Specifically:
Amplify add api
selected: GraphQl
authroization type: Amazon Cognito User Pool
(I already had user pool added to the project so it skipped the process of making a new user pool)
I kept choosing the defaults until "Choose a schema template"
I picked "Objects with fine-grained access control (e.g., a proj
ect management app with owner-based authorization)"
From there it setup a sample project I could start learning GraphQL from and how to implement the fine-grained access control. Using the code from the getPrivateNote resolver was probably the most useful thing. I also used this appsync starter application to figure out how to interact with GraphQL from my react client. This whole process took me HOURS AND HOURS to figure out, and currently I am still trying to fully understand how it all works, but so far this AppSync GraphQL seems to be the best for my scenario. The built in query system that AppSync has made it easier to test access control (i.e login with one user and see if I only had access to my own items)
Here is what my reactjs code ended up looking like for the client side:
import { API, graphqlOperation } from 'aws-amplify';
import QueryUserInfo from './graphql/QueryUserInfo';
...
getRequest = (evt) => {
return new Promise((resolve, reject) =>
{
API.graphql(graphqlOperation(QueryUserInfo))
.then((data) => {
if(data) {
console.log(data);
resolve(data);
} else {
console.log(data);
resolve(null);
}
})
.catch((err) => {
console.log(err);
resolve(null);
});
});
}
This is what the actual QueryUserInfo.js file looked like:
import gql from "graphql-tag";
export default gql(`
query QueryName {
getUser(id: "c35...rest of cognito user id...69") {
id
email
name
}
}`);
The resolver code is too long to post, but I just used the template code from Amplify and I think I only had to change #set( $allowedOwners0 = $util.defaultIfNull($ctx.result.owner, []) )
to #set( $allowedOwners0 = $util.defaultIfNull($ctx.result.id, []) )
since "id" was what I was using on my dynamoDB table, not "owner". Good luck to anyone reading this!

One db per user and security

I'm trying to implement an app which uses couchdb as backend, But the problem is,
When installing couchdb , couchdb allows anyone to enter couchdb and create/delete/update databases, so we configure admin(super admin) for the couchdb server to prevent anonymous And if we configure superadmin while installing couchdb server, then normal users can't create databases, so userdb for the user isn't created. Only super admin has privilege to create database in couchdb. Even users with 'admins' role can't create db in couchdb.
I just dealt with all of this myself and couldn't find hardly anything about it...
From the documentation:
Users may only access (GET /_users/org.couchdb.user:Jan) or modify (PUT /_users/org.couchdb.user:Jan) documents that they own
This means that users can add themselves to the _users db. Thus, if you have couch_peruser turned on, running the following curl command will create the user jan along with the userdb-6a616e database.
curl -X PUT http://localhost:5984/_users/org.couchdb.user:jan \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{"name": "jan", "password": "apple", "roles": [], "type": "user"}'
You can use the db.signUp() function from the PouchDB Authentication plugin to effectively do the same thing. Also, I had to manually encode the username when initially creating my db var for the new remote PouchDB instance:
function encode (str) {
return unescape(encodeURIComponent(str))
.split('').map(function (v) {
return v.charCodeAt(0).toString(16)
}).join('')
}
var db = new PouchDB('http://localhost:5984/userdb-' + encode(username), {
auth: {
username: username,
password: username
},
skip_setup: true // Because the DB won't exist initially
})

Authentication always failing when connecting to MongoDB

I am using node/express
node_modules =
"mongodb": "2.0.33",
"mongoose": "3.8.15",
mongo shell version: 3.0, and mongo 3.0
I'm able to connect to my mongoDB just fine, but if I pass in any authentication parameters, it will fail:
connection error: { [MongoError: auth failed] name: 'MongoError', ok: 0, errmsg: 'auth failed', code: 18 }
The following shows up in the logs when this happens:
2015-06-13T15:10:09.863-0400 I ACCESS [conn8] authenticate db: mydatabase { authenticate: 1, user: "user", nonce: "xxx", key: "xxx" } 2015-06-13T15:10:09.863-0400 I ACCESS [conn8] Failed to authenticate user#mydatabase with mechanism MONGODB-CR: AuthenticationFailed UserNotFound Could not find user user#mydatabase
I've done quite a few patterns to try to get this to work.
Here's what happens when I do the show users command in the mongo shell while on the appropriate database:
{
"_id" : "mydatabase.user",
"user" : "user",
"db" : "mydatabase",
"roles" : [
{
"role" : "readWrite",
"db" : "mydatabase"
}
]
}
Here's my attempt to connect to this particular database while passing in the correct parameters:
mongoose.connect('mongodb://user:password#host:port/mydatabase');
For good measure I also tried passing in an options hash instead of passing the params via uri:
mongoose.connect('mongodb://host:port/mydatabase',{user: 'user',pass: 'password'});
Strangely enough, this works when done from the shell:
mongo mydatabase -u user -p password
so clearly, the credentials are right, and it's lining them up to the correct database, but something about the connection with Mongoose is not working...
Here is the shell command I passed in when creating that user:
db.createUser({
user: "user",
pwd: "password",
roles: [
{ role: "readWrite", db: "mydatabase" }
]
});
I got a success message with this, and I confirmed by calling the show users command when using the mydatabase set
I'm at a real loss here.... Here's some of the prior research I have done that hasn't yet given me success:
Cannot authenticate into mongo, "auth fails"
This answer suggests that it wouldn't be working because authentication happens at a database level, so I'm missing some sort of config option for my mongo instance, however the docs now say that such level authentication is disabled by default, and the docs the answer links to are since deprecated.
MongoDB & Mongoose accessing one database while authenticating against another (NodeJS, Mongoose)
uses older version of Mongo that still have addUser
On top of that, I don't see why that would work given it suggests I add a parameter to the 'auth' options that isn't listed in the documentation:
http://mongodb.github.io/node-mongodb-native/api-generated/db.html#authenticate
http://mongoosejs.com/docs/connections.html
Basically what I'm trying now, but isn't working.
authenticate user with mongoose + express.js
I've tried a number of answers that involved doing something of this sort, that gave me the same error. Also, I'd rather avoid these type of solutions that require +80 lines of code to authenticate for now. I just want to get basic authentication down first.
You mentioned that you are using MongoDB 3.0. In MongoDB 3.0, it now supports multiple authentication mechanisms.
MongoDB Challenge and Response (SCRAM-SHA-1) - default in 3.0
MongoDB Challenge and Response (MONGODB-CR) - previous default (< 3.0)
If you started with a new 3.0 database with new users created, they would have been created using SCRAM-SHA-1.
So you will need a driver capable of that authentication:
http://docs.mongodb.org/manual/release-notes/3.0-scram/#considerations-scram-sha-1-drivers
If you had a database upgraded from 2.x with existing user data, they would still be using MONGODB-CR, and the user authentication database would have to be upgraded:
http://docs.mongodb.org/manual/release-notes/3.0-scram/#upgrade-mongodb-cr-to-scram
Specific to your particular environment Mongoose compatibility for that version doesn't appear to support 3.0 due to the MongoDB Node.js driver that is in use (see the compatibility page on the Mongoose site--sorry, can't post more than 2 links currently).
I would suggest you update Mongoose.
Mongo v3.0+:
The db field (outside of the role object) matters here. That is not settable bby passing it into the createUser command afaict.
The way to set it is to type 'use ' before issuing the creatUser command.
Unless you do it that way, the db object inside role may have he correct and intended value, but the auth will still not work.

Setting up user_ctx field on CouchDB Replicator

"user_ctx": {
"name": "adminuser",
"role": "[\"_admin\"]"
},
"_replication_state": "error",
"_replication_state_time": "2011-08-30T15:09:03+00:00",
"_replication_id": "08fd9d6dcc5a0882fc9fd0d971b05938"
}
For some reason, I can't get my replicator to work. The log continues to show "unauthorized to access database", referring to my localhost. I know I need to have user_ctx set, but for some reason it just doesn't like to work. I copied the info out of my source. I even created new admin users to try and fix the problem, none worked. Do I need to specify more roles for the user?
The other has a good resource https://gist.github.com/832610, but the user_ctx he set's in the example isn't the admin user, the appear to just be random roles.
Anyone have any experience with the CouchDB replicating to the localhost?
If you create the document as the server admin, then you do not need this field. I think omitting it completely will work.
If you create the document as a normal user, then it should match your name and roles which you can get by querying /_session. In fact, I think you can copy the userCtx field from the session response directly into the user_ctx field of the replication document.
Found out what I did thanks to the CouchDB Apache Mailing Lists. Should have had "roles" instead of "role".

Creating regular users in CouchDB

How can I create regular, non-admin users in CouchDB?
First you put the user in _users database. The ID of the document must be org.couchdb.user:username, e.g.
With CouchDB 1.2.0 or later use this:
{
"_id": "org.couchdb.user:dbreader",
"name": "dbreader",
"type": "user",
"roles": [],
"password": "plaintext_password"
}
CouchDB will hash & salt the password for you on the server side and save the values in the fields password_sha and salt (see below).
With CouchDB < 1.2.0 the user document needs to look like this:
{
"_id": "org.couchdb.user:dbreader",
"name": "dbreader",
"type": "user",
"roles": [],
"salt": "54935938852dd34f92c672ab31e397cedaf0946d",
"password_sha": "42253ea4461a604f967813aaff90b139d7018806"
}
Note that CouchDB 1.3.0 and later will use PBKDF2 instead of aha & salt for hashing the password.
Then you can create per database authentication by creating document with id _security in specific database which is not versioned, e.g.
{
"admins": {
"names": ["dbadmin"],
"roles": ["editor"]
},
"readers": {
"names": ["dbreader"],
"roles": ["reader"]
}
}
This means that there are 2 users in _users besides the admin dbadmin and dbreader. That should do in case you are too lazy to read the document that has already been suggested.
The CouchDB documentation has a short article about the security features of CouchDB, and it includes a section on how to create a new user.
I think you have to put a web framework in front to do this the way many sites do. Couchdb admin roles do not work on a record by record basis, so if you create a reader who can read the profiles or account table they can read record.

Resources