@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

When an install is instanced, include the instance identifier in the URI for file data

Summary:
This allows us to CDN the cluster.

General problem is that we can't easily give each instance its own CDN URI (`giraffe.phcdn.net`) in Cloudfront, because it requires that you enumerate all aliases (and there's a limit of 100) and depends on SNI (a newish feature of SSL which allows one server to serve multiple certificates, but which doesn't have full support everywhere yet).

It's //possible// that we could eventually work around this, or use Cloudflare instead (which has a different model that seems like a slightly easier fit for CDN-domain-per-instance), but I don't want to sink a ton of work into this and want to keep things on AWS insofar as we reasonably can.

The easiest way to fix this is just to put the instance identity into URIs, then read it out when handling CDN requests. This has no effect on installs without cluster instance configuration, which is all of them except ours.

It's also slightly desirable to share this stuff, since we get to share the cache for static resources, which are always identical across instances.

So requests go from the Cloudfront gateway ("xyz.cloudfront.com") to the LB with a hard-coded instance name ("cdn.phacility.com"), which gets them routed to a balanced web machine. The web machine picks the correct instance name out of the URI, acts as that instance, and does the correct thing.

The messiest part of this is that we need "cdn.phacility.com" to be a real instance so it can serve static resources, but that's not a big deal. We have a few other hard-codes which have to be real resources for now, like we must have a merchant named "Phacility".

Test Plan:
- Viewed files with `security.alternate-file-domain` off (i.e., no file tokens).
- Viewed pages and files with `security.alternate-file-domain` on. Saw correct resource behavior, @isntance generation of URIs, and correct token redirect behavior for files.

Reviewers: btrahan

Reviewed By: btrahan

Subscribers: epriestley

Differential Revision: https://secure.phabricator.com/D11668

+47 -24
+6 -3
src/applications/files/application/PhabricatorFilesApplication.php
··· 76 76 'delete/(?P<id>[1-9]\d*)/' => 'PhabricatorFileDeleteController', 77 77 'edit/(?P<id>[1-9]\d*)/' => 'PhabricatorFileEditController', 78 78 'info/(?P<phid>[^/]+)/' => 'PhabricatorFileInfoController', 79 - 'data/(?P<key>[^/]+)/(?P<phid>[^/]+)/(?P<token>[^/]+)/.*' 80 - => 'PhabricatorFileDataController', 81 - 'data/(?P<key>[^/]+)/(?P<phid>[^/]+)/.*' 79 + 'data/'. 80 + '(?:@(?P<instance>[^/]+)/)?'. 81 + '(?P<key>[^/]+)/'. 82 + '(?P<phid>[^/]+)/'. 83 + '(?:(?P<token>[^/]+)/)?'. 84 + '.*' 82 85 => 'PhabricatorFileDataController', 83 86 'proxy/' => 'PhabricatorFileProxyController', 84 87 'xform/(?P<transform>[^/]+)/(?P<phid>[^/]+)/(?P<key>[^/]+)/'
+41 -21
src/applications/files/storage/PhabricatorFile.php
··· 556 556 'You must save a file before you can generate a view URI.'); 557 557 } 558 558 559 + return $this->getCDNURI(null); 560 + } 561 + 562 + private function getCDNURI($token) { 559 563 $name = phutil_escape_uri($this->getName()); 560 564 561 - $path = '/file/data/'.$this->getSecretKey().'/'.$this->getPHID().'/'.$name; 565 + $parts = array(); 566 + $parts[] = 'file'; 567 + $parts[] = 'data'; 568 + 569 + // If this is an instanced install, add the instance identifier to the URI. 570 + // Instanced configurations behind a CDN may not be able to control the 571 + // request domain used by the CDN (as with AWS CloudFront). Embedding the 572 + // instance identity in the path allows us to distinguish between requests 573 + // originating from different instances but served through the same CDN. 574 + $instance = PhabricatorEnv::getEnvConfig('cluster.instance'); 575 + if (strlen($instance)) { 576 + $parts[] = '@'.$instance; 577 + } 578 + 579 + $parts[] = $this->getSecretKey(); 580 + $parts[] = $this->getPHID(); 581 + if ($token) { 582 + $parts[] = $token; 583 + } 584 + $parts[] = $name; 585 + 586 + $path = implode('/', $parts); 587 + 562 588 return PhabricatorEnv::getCDNURI($path); 563 589 } 590 + 591 + /** 592 + * Get the CDN URI for this file, including a one-time-use security token. 593 + * 594 + */ 595 + public function getCDNURIWithToken() { 596 + if (!$this->getPHID()) { 597 + throw new Exception( 598 + 'You must save a file before you can generate a CDN URI.'); 599 + } 600 + 601 + return $this->getCDNURI($this->generateOneTimeToken()); 602 + } 603 + 564 604 565 605 public function getInfoURI() { 566 606 return '/'.$this->getMonogram(); ··· 962 1002 963 1003 return $token; 964 1004 } 965 - 966 - /** Get the CDN uri for this file 967 - * This will generate a one-time-use token if 968 - * security.alternate_file_domain is set in the config. 969 - */ 970 - public function getCDNURIWithToken() { 971 - if (!$this->getPHID()) { 972 - throw new Exception( 973 - 'You must save a file before you can generate a CDN URI.'); 974 - } 975 - $name = phutil_escape_uri($this->getName()); 976 - 977 - $path = '/file/data' 978 - .'/'.$this->getSecretKey() 979 - .'/'.$this->getPHID() 980 - .'/'.$this->generateOneTimeToken() 981 - .'/'.$name; 982 - return PhabricatorEnv::getCDNURI($path); 983 - } 984 - 985 1005 986 1006 987 1007 /**