I've been working hard to create a scalable Aegir cluster using docker-compose.yml.

For those of you that don't know, docker-compose allows you to specify "scale" of a service, meaning you send the command docker-compose scale hostmaster 2 and docker will automatically create a new container with all the links needed to scale...

Except it won't work, because Aegir explicitly grants permissions to the site's databases only to requests coming fro the site's chosen Web Servers.

So when we "Scale", meaning adding new web server containers, it fails, because those new web server containers are not allowed to access the specific database created for that site.

I've tracked this down to Provision project: /db/Provision/Service/db.php

By applying this patch, the database is accessible from any host using the generated username, password, and database name.

-    foreach ($this->grant_host_list() as $db_grant_host) {
+    $hosts = $this->grant_host_list();
+    $hosts[]  = '%';
+    foreach ($hosts as $db_grant_host) {

This is a total hack but it did allow me to get access.

Proposed solutions:

  1. Create a new Provision_Service_db_docker class with a replacement for grant_host_list() method. This seems like overkill and feels confusing, especially when thinking about how to use that on hostmaster install.
  2. Create a new property on site context: "db_grant_hosts". Instead of dynamically generating the hosts list in the Provision_Service_db class, we can write the list to the site context and then just read it back. This would allow the front-end to alter the list of db_grant_hosts using a simple node alter. Then, we can create a hosting_docker module with a service that inherits from Hosting_Service_mysql, and simply alters the db_grant_hosts property.
  3. ??

This one needs some thinking. As we start to use Docker/Kubernetes, we no longer need to set access controls in MySQL itself, but should control access via docker networking.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

Jon Pugh created an issue. See original summary.

ergonlogic’s picture

The database service already supports scaling web servers. Provision_Service_db::grant_host_list() doesn't return static values, but rather requests a list of servers from the HTTP service, thus allowing it to scale across web clusters and packs. So you might want to investigate adding something like adding Provision_Service_http_docker::grant_server_list() instead.

I think Provision_Service_db::grant() only gets called when creating the site database; so during install/migrate/clone tasks. We might want to consider also calling it during "verify" tasks, or the like, to allow us to pick up new hosts added to clusters and such.

Think of MySQL as using 2-factor authentication, checking both the user's hostname and password. Moving to a simple wildcard (%) would essentially reduce security to just the password. However, wildcards aren't all-or-nothing. We could, for example, open access to others hosts on the same subnet using: 192.168.10.% or 192.168.10.0/255.255.255.0 (ref.: MySQL Access Control docs).

Jon Pugh’s picture

Title: Refactor database permissions granting to allow scalable web servers. » Refactor database permissions granting to allow scalability to arbitrary web servers.
Issue summary: View changes

I'm not saying we should change the default behavior, I'm just pointing out we need an easier way to alter this.

I was actually looking at the Cluster/Pack classes as well when trying to figure out how I might be able to lead by their example, but in the end I realized this isn't something Aegir should even be worrying about.

What I am saying is that as we start using docker, we don't have to worry about the grant_host_list() thing at all. All of the access control between database and web servers can be handled "upstream" at the docker orchestration level.

Docker compose v2 creates a wholly separate network for each cluster. When using database containers, you typically don't worry about host restrictions in MySQL at all, as the restrictions are better handled by docker networking itself.

What I am looking for is a decent way for me to start getting this working now, without major changes to Provision.

I'll keep digging. I've updated the title and summary to be more specific.

Jon Pugh’s picture

So you might want to investigate adding something like adding Provision_Service_http_docker::grant_server_list()

This is the part I'm trying to avoid. Docker compose let's me scale up the web containers by number. Docker compose maintains a network layer so they already have access to the DB.

I'd much rather let docker links/networking decide who can access the database container then worry about aegir and MySQL itself keeping track. I have a feeling most users of Docker database containers no longer GRANT access by host?

Jon Pugh’s picture

Issue summary: View changes
ergonlogic’s picture

Can you point to where you're running docker and/or docker-compose from Aegir?

Jon Pugh’s picture

Sorry for the delay. I've got 2 really good excuses, at least.

https://www.drupal.org/project/hosting_docker

helmo’s picture

JamesK’s picture

I'm using web pack to manage a server cluster but I run into lots of issues with this stuff as well. My database is on AWS Aurora and only accessible on a private network, so the host-based access control is a huge frustration to me as well because every time the cluster changes I have to manually update the cluster config in Aegir and manually update the mysql.user/.db tables with a new user hostmasks.

Removing host restrictions would be a good step towards real cluster support.

Jon Pugh’s picture

JamesK see the patch in https://www.drupal.org/node/1392934.

That should actually work for you for the time being.

  • Jon Pugh committed ab2f03e on 2794915-grant-all-hosts
    Issue #2794915: Allow database servers to grant access to all hosts....
Jon Pugh’s picture

Status: Active » Needs review
FileSize
2.21 KB

Well, I was inspired.

The new branch and patch do the following:

  1. Adds a server property called "db_grant_all_hosts", defaults to FALSE.
  2. If set to true, the grant_host_list() method just returns '%'.
  3. Makes the log entry for granting database permission to a 'success' type, and only call it after it was successful.
Jon Pugh’s picture

I made the changes this way so it's the least disruptive to default aegir behavior: If the value is set to false or not there, it will do the usual.

Users must set the new property manually in the ~/.drush/server_NAME.alias.drushrc.php file.

Jon Pugh’s picture

Now I just need a way to set that in hostmaster-install, and we'll be good to go on Docker!

  • Jon Pugh committed 60ca1cf on 2794915-grant-all-hosts
    Issue #2794915: Add 'db_grant_all_hosts' option to hostmaster-install...
Jon Pugh’s picture

Done.

hostmaster-install now has an option --aegir_db_grant_all_hosts that passes to the created database server context.

Updated patch attached.

  • helmo committed 457bfb6 on 7.x-3.x authored by Jon Pugh
    Issue #2794915 by Jon Pugh: Refactor database permissions granting to...
helmo’s picture

Status: Needs review » Fixed

Committed, with only a false => FALSE style change.

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.