Enabling authentication on MongoDB

When I first installed MongoDB on my OpenBSD box I didn’t care about authentication, it was behind the firewall, purely for testing purposes. I first wanted to have some fun with it. But now I became curious and wanted to things right, so I enabled authentication.

In order to do so we first need to create an admin user:

$ mongo
> use admin
> db.createUser({ user: "admin", pwd: passwordPrompt(), roles: [ { role: "userAdminAnyDatabase", db: "admin" }, "readWriteAnyDatabase" ] });
> exit

After that enable authentication in /etc/mongodb.conf by adding:

security:
  authorization: enabled

Restart mongod

$ doas rcctl restart mongod

After that you can connect to mongo with:

$ mongo --authenticationDatabase "admin" -u "admin" -p

And now we can create additional users for our applications:

> use my_db
> db.createUser({ "user": "db_user", "pwd": passwordPrompt(), roles: [{ role: "readWrite", db: "my_db" }]})

And lastly we implement the credentials in our php-project:

<?php

$mongo = new MongoDB\Driver\Manager("mongodb://db_user:password@localhost:27017/my_db");

And we are set to go!

MongoDB on OpenBSD6.6 with PHP-FPM…

Okay, for a new project I want to try and move to MongoDB, I am really looking forward to a schema free database where I can simply just store my ‘documents’ and do with them what I want!

So let’s log into our server and get some stuff installed:

$ doas pkg_add mongodb
$ doas rcctl enable mongod
$ doas rcctl start mongod
$ mongo
MongoDB shell version: 3.2.22
connecting to: test
Welcome to the MongoDB shell.
For interactive help, type "help".
For more comprehensive documentation, see
	http://docs.mongodb.org/
Questions? Try the support group
	http://groups.google.com/group/mongodb-user
Server has startup warnings: 
2020-03-20T23:01:00.737+0100 I CONTROL  [initandlisten] 
2020-03-20T23:01:00.737+0100 I CONTROL  [initandlisten] ** NOTE: your operating system version does not support the method that MongoDB
2020-03-20T23:01:00.737+0100 I CONTROL  [initandlisten] **       uses to detect impending page faults.
2020-03-20T23:01:00.737+0100 I CONTROL  [initandlisten] **       This may result in slower performance for certain use cases
2020-03-20T23:01:00.737+0100 I CONTROL  [initandlisten] 
2020-03-20T23:01:00.737+0100 I CONTROL  [initandlisten] ** WARNING: soft rlimits too low. Number of files is 128, should be at least 1000
2020-03-20T23:01:00.737+0100 I CONTROL  [initandlisten] 

For what it’s worth Mongo is showing some startup warnings, I’m going to ignore these for now. Let’s first insert some data so we can test our db connection later when we are in PHP:

$ mongo testdb
> db.users.insert({ 'name': 'Remy Blom', 'email': 'r@aodw.nl' })

Thing is we have a working MongoDB, kinda cool, but I want to be able to talk to it from PHP (or do I? I might have to rethink that… PHP is waaaay old and stuff?)

First we have to prepare our OpenBSD to be able to run the manual installation. (I still think this should also be able to work in such a way that you could just use the pecl install method, but I kept running into the error mentioning AUTOCONF_VERSION was not set…)

In order to get phpize running I had to do:

$ doas pkg_add pear autoconf
$ cd /usr/local/bin
$ ln -s phpize-7.3 phpize
$ ln -s php-config-7.3 php-config

Furthermore I had to add to my ./profile:

export AUTOCONF_VERSION=2.69

Then I had to re-login for the profile to take effect and then I could run:

$ git clone https://github.com/mongodb/mongo-php-driver.git
$ cd mongo-php-driver
$ git submodule update --init
$ phpize
$ ./configure
$ make all
$ sudo make install

Restart php-fpm and ready to go:

$ doas rcctl restart php73_fpm

Let’s write a little program that returns that user we inserted in the beginning:

<?php

    $m = new MongoDB\Driver\Manager("mongodb://localhost:27017");
    $query = new MongoDB\Driver\Query([]); 
     
    $results = $m->executeQuery("testdb.users", $query);
    echo $results;

    foreach ($results as $result) {
        print_r($result);
    }

Running this code will print:

stdClass Object
(
    [_id] => MongoDB\BSON\ObjectId Object
        (
            [oid] => 5e79c3a3c7f38ba9c7943ffd
        )

    [name] => Remy Blom
    [email] => r@aodw.nl
)

Please note that in the $results object you don’t see any of your results, that had me looking puzzled and scratching my head for a while….

SimpleSAMLphp as a Service Provider with Nginx!

On a server with nginx already setup, I wanted to write a php-application that needed SAML-authentication. So let’s install SimpleSAMLphp and configure it and nginx to have the magic going. I presume you have a user with sudo privileges that is also member of the www-data group.

$ cd /var/www
$ sudo chown root:www-data .
$ sudo chmod 775 .
$ wget -O simplesaml.tar.gz https://simplesamlphp.org/download?latest
$ tar xzf simplesaml.tar.gz
$ ln -sf simplesamlphp-1.18.x/ simplesamlphp

Now that we have a simpleSAMLphp installation let’s configure it, edit config/config.php

// I like short baseurlpaths:
'baseurlpath' => 'https://application.example.org/saml/',

// I always fill in the technical contact information:
'technicalcontact_name' => 'Remy Blom',
'technicalcontact_email' => 'na@example.org',

'timezone' => 'Europe/Amsterdam',

// https://passwordsgenerator.net/ 
// length = 32, include numbers and lowercase characters
'secretsalt' => 'ner9iuf8vu3fqkgawqchu7bcp4ihn221',
   
// you might want to change this one: 
'auth.adminpassword' => '123',
 
'admin.protectindexpage' => true,

Now let’s setup nginx to serve simpleSAMLphp from the /saml url: in /var/www/html/ I create a symlink:

$ sudo ln -sf /var/www/simplesamlphp/www /var/www/html/saml

And presuming you already have a serverblock setup that is serving /var/www/html we can add this location-block:

location /saml {
  location ~ ^(?<prefix>/saml)(?<phpfile>.+?\.php)(?<pathinfo>/.*)?$ {
    include snippets/fastcgi-php.conf;
    fastcgi_pass     unix:/var/run/php/php7.2-fpm.sock;
    fastcgi_split_path_info ^((?U).+\.php)(/?.+)$; 
  }
}

Reload nginx:

$ sudo nginx -t && sudo service nginx reload

In /config/authsources.php we put:

<?php

$config = [
  // This is a authentication source which handles admin authentication.
  'admin' => [
    // The default is to use core:AdminPassword, but it can be replaced with
    // any authentication source.
    'core:AdminPassword',
  ],

  // An authentication source which can authenticate against both SAML 2.0
  // and Shibboleth 1.3 IdPs.
  'application.example.org' => [
    'saml:SP',
    'entityID' => 'https://application.example.org',
    'idp' => 'https://idp.example.org',
  ],
];

Then we exchange the metadata with the IdP and we have a testable setup. You can use https://application.example.org/saml/module.php/core/authenticate.php to test the application as an authentication source. You should be able to login via your IdP

If so, writing a simple php program that needs authentication is peanuts:

<?php

require_once('/var/www/simplesamlphp/lib/_autoload.php');

$as = new \SimpleSAML\Auth\Simple('application.example.org');
$as->requireAuth();
$attr = $as->getAttributes();

print_r($attr);