Each server can have multiple IP addresses associated with it. Each web pack can have multiple servers associated with it. When making a new cert, its supposed to pick an unused IP from those that are available on the server to associate with it. However, if you enable SSL on a site on a platform on a webpack with 2 servers, it grabs the first available IP from the first server and deploys that configuration to both servers in the webpack. This has the effect where SSL will only work when accessing the site from the first server, and then doesn't work when it gets served up from the second server.

CommentFileSizeAuthor
#5 2071317_05-touchups.patch859 bytescweagans
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

anarcat’s picture

Priority: Normal » Major
anarcat’s picture

i confirm this is totally broken, even conceptually in code (ie. it's not a bug as much as the implementation is simply incomplete).

the problem is in hosting_ssl_get_ip() which returns a single IP instead of a server_name => ip_address mapping, or at least a list of IPs.

so that should be a simple fix... untested patch...

diff --git a/web_server/nginx/ssl/hosting_nginx_ssl.drush.inc b/web_server/nginx/ssl/hosting_nginx_ssl.drush.inc
index eb8c9cf..7371753 100644
--- a/web_server/nginx/ssl/hosting_nginx_ssl.drush.inc
+++ b/web_server/nginx/ssl/hosting_nginx_ssl.drush.inc
@@ -13,6 +13,6 @@ function hosting_nginx_ssl_hosting_site_context_options(&$task) {
     else {
       $task->context_options['ssl_key'] = 'null';
     }
-    $task->context_options['ip_address'] = hosting_ssl_get_ip($node->ssl_key);
+    $task->context_options['ip_addresses'] = hosting_ssl_get_ip($node->ssl_key);
   }
 }
diff --git a/web_server/ssl/hosting_ssl.drush.inc b/web_server/ssl/hosting_ssl.drush.inc
index a7494bd..254a313 100644
--- a/web_server/ssl/hosting_ssl.drush.inc
+++ b/web_server/ssl/hosting_ssl.drush.inc
@@ -13,6 +13,6 @@ function hosting_ssl_hosting_site_context_options(&$task) {
     else {
       $task->context_options['ssl_key'] = 'null';
     }
-    $task->context_options['ip_address'] = hosting_ssl_get_ip($node->ssl_key);
+    $task->context_options['ip_addresses'] = hosting_ssl_get_ip($node->ssl_key);
   }
 }
diff --git a/web_server/ssl/hosting_ssl.nodeapi.inc b/web_server/ssl/hosting_ssl.nodeapi.inc
index bc7bb82..d2a5dc2 100644
--- a/web_server/ssl/hosting_ssl.nodeapi.inc
+++ b/web_server/ssl/hosting_ssl.nodeapi.inc
@@ -118,7 +118,12 @@ function hosting_ssl_get_key($cid) {
 }

 function hosting_ssl_get_ip($cid) {
-  return db_result(db_query("SELECT ips.ip_address FROM {hosting_ssl_cert_ips} cert INNER JOIN {hosting_ip_addresses} ips ON cert.ip_address = ips.id WHERE cid=%d", $cid));
+  $result = db_query("SELECT h.name AS server_name, ips.ip_address FROM {hosting_ssl_cert_ips} cert INNER JOIN {hosting_ip_addresses} ips ON cert.ip_address = ips.id INNER JOIN {hosting_context} h ON h.nid = ips.nid WHERE cid=%d", $cid);
+  $ip_addresses = array();
+  while ($row = db_fetch_object($result)) {
+    $ip_addresses[$row->server_name] = $row->ip_address;
+  }
+  return $ip_addresses;
 }

 function hosting_ssl_output_key($cid) {
diff --git a/http/Provision/Service/http/ssl.php b/http/Provision/Service/http/ssl.php
index 1096912..0a67ccd 100644
--- a/http/Provision/Service/http/ssl.php
+++ b/http/Provision/Service/http/ssl.php
@@ -38,7 +38,7 @@ class Provision_Service_http_ssl extends Provision_Service_http_public {

     $this->context->setProperty('ssl_enabled', 0);
     $this->context->setProperty('ssl_key', NULL);
-    $this->context->setProperty('ip_address', '*');
+    $this->context->setProperty('ip_addresses', array());
   }


@@ -47,7 +47,15 @@ class Provision_Service_http_ssl extends Provision_Service_http_public {
     $data['http_ssl_port'] = $this->server->http_ssl_port;

     if ($config == 'site' && $this->context->ssl_enabled) {
-      $data['ip_address'] = $this->context->ip_address;
+      foreach ($this->context->ip_addresses as $server => $ip_address) {
+        if ($this->server->name == $server) {
+          $data['ip_address'] = $ip_address;
+          break;
+        }
+      }
+      if (!$data['ip_address']) {
+        drush_set_error('SSL_IP_MISSING', dt('no proper IP provided by the frontend for server %servername', array('%servername' => $this->server->name)));
+      }
       if ($this->context->ssl_enabled == 2) {
         $data['ssl_redirection'] = TRUE;
         $data['redirect_url'] = "https://{$this->context->uri}";

i am probably missing something, but it's a start!

anarcat’s picture

Status: Active » Needs review

i've re-opened the dev-ssl-ip-allocation-refactor branch on both hosting (new) and provision for those patches, that would welcome some testing.

the provision patch is slightly different: we use a wildcard if no IP is found in the array, which seems like a better failure mode... plus it will make SNI possible to implement simply in the frontend, by not passing the address to the backend at all.

see also #1926520: Support Server Name Indication (SNI) for SSL.

anarcat’s picture

note that this patch will change the API, so http://community.aegirproject.org/upgrading/path needs to be updated.

cweagans’s picture

Status: Needs review » Reviewed & tested by the community
FileSize
859 bytes

This works very well. I've attached a couple of touchups to the frontend (fixes a notice and capitalizes a status message). Other than that, I think this is ready to go in 6.x-2.x.

cweagans’s picture

One other thing:


+      foreach ($this->context->ip_addresses as $server => $ip_address) {
+        if ($this->server->name == $server) {
+          $data['ip_address'] = $ip_address;
+          break;
+        }
+      }

needs to read:


+      foreach ($this->context->ip_addresses as $server => $ip_address) {
+        if ($this->server->name == '@' . $server) {
+          $data['ip_address'] = $ip_address;
+          break;
+        }
+      }

(The @ before $server in the if needs to be there to get things to match properly.)

anarcat’s picture

Status: Reviewed & tested by the community » Fixed

alright, i commited your toutchup and pushed everything to 2.x. thanks for the testing!

Status: Fixed » Closed (fixed)

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

  • Commit 02c2983 on 6.x-2.x, dev-ssl-ip-allocation-refactor, 7.x-3.x, 6.x-2.x-backports, dev-helmo-3.x by anarcat:
    expect ip_addresses as an array instead of a single entry, as we support...