Skip to content

Commit

Permalink
Release v8.5.0 (#145)
Browse files Browse the repository at this point in the history
* [GOVCMS-4391]: Add scaffold-tooling to the base image. (#131)

* Add scaffold-tooling to the base image.

- Add the scaffold tooling repository to the base image. This will include the necessary deploy scripts to the images.

* Remove duplicate dependencies.

Scaffold-tooling lists the removed packages as dependencies. Removing these means we manage the version in a central location.

* Update to stable version of the tooling.

* Pin scaffold-tooling to atomic deploy process.

* [GOVCMS-4245] - Added support for COMPOSER_AUTH env variable. (#139)

* Fixes inability to disable dev mode outside of production. (#136)

* [GOVCMS-2677]: Nginx Security headers (#129)

* Add security header to the nginx response.

Add tests.

* Add missing ';'

* Update 207-seucirty-headers.conf

* Updated Nginx test helpers.

* Fixed coding standards.

* Updated GitLab CI nginx test job to be equivalent to the config in CircleCI.

* Added explicit non-tty flag.

* Removed pushing of Docker images from CircleCI as this is now handled in GitLab.

* Replaced CI runner image with govcms/govcms-ci.

* Fixed typos. (#141)

* Added override for temporary file deletion. (#135)

* [GOVCMS-4200]: Pin scaffold-tooling to ^1.0. (#134)

* Solr update (#142)

* Solr update

Signed-off-by: Karl Hepworth <[email protected]>

* Add event-dispatcher to govcms8lagoon

* Fix composer.json

* Update composer.json (revert merge conflict changes)

Co-authored-by: Steve Worley <[email protected]>

* Update Solr path regarding to #444 from GovCMS distro (#143)

* Update .env.default for release 8.5.0

* Update goss.solr.yaml for solr schema/version changes

* Update .env.default for release 8.5.0

* Update goss.solr.yaml for solr schema/version changes

* Update the site alias for scaffold-tooling. (#133)

Scaffold tooling uses `ci.prod` as the production site alias. This is to bring
the default site alias to the govcms8lagoon images.

Add deprecated site alias.

- Decouple the release process from scaffold-tooling a little further we should deprecate the @prod alias rather thaan removing.

* Update the site alias for scaffold-tooling. (#133)

Scaffold tooling uses `ci.prod` as the production site alias. This is to bring
the default site alias to the govcms8lagoon images.

Add deprecated site alias.

- Decouple the release process from scaffold-tooling a little further we should deprecate the @prod alias rather thaan removing.

* Fix permissions on config dir. (#147)

* Release/8.5.0 (#148)

* Update .env.default for release 8.5.0

* Update goss.solr.yaml for solr schema/version changes

* Update the site alias for scaffold-tooling. (#133)

Scaffold tooling uses `ci.prod` as the production site alias. This is to bring
the default site alias to the govcms8lagoon images.

Add deprecated site alias.

- Decouple the release process from scaffold-tooling a little further we should deprecate the @prod alias rather thaan removing.

Co-authored-by: Karl Hepworth <[email protected]>

* Missing commits (#149)

* Update the site alias for scaffold-tooling. (#133)

Scaffold tooling uses `ci.prod` as the production site alias. This is to bring
the default site alias to the govcms8lagoon images.

Add deprecated site alias.

- Decouple the release process from scaffold-tooling a little further we should deprecate the @prod alias rather thaan removing.

* Fix permissions on config dir. (#147)

* Release/8.5.0 (#148)

* Update .env.default for release 8.5.0

* Update goss.solr.yaml for solr schema/version changes

* Update the site alias for scaffold-tooling. (#133)

Scaffold tooling uses `ci.prod` as the production site alias. This is to bring
the default site alias to the govcms8lagoon images.

Add deprecated site alias.

- Decouple the release process from scaffold-tooling a little further we should deprecate the @prod alias rather thaan removing.

Co-authored-by: Karl Hepworth <[email protected]>

Co-authored-by: Steve <[email protected]>
Co-authored-by: Karl Hepworth <[email protected]>

* Adds hook_update support for the solr changes. (#150)

* Adds hook_update support for the solr changes.

- Adds hook_update to import configuration differences.
- Hard codes solr configuration overrides for lagoon_search.

*NB*: Update requires a cache clear afterwards for the configuration updates to be visible.

* Update modules/lagoon/lagoon_search/lagoon_search.install

Co-Authored-By: Toby Bellwood <[email protected]>

* Update modules/lagoon/lagoon_search/lagoon_search.install

Co-Authored-By: Toby Bellwood <[email protected]>

* Update modules/lagoon/lagoon_search/lagoon_search.install

Co-Authored-By: Stuart Rowlands <[email protected]>

* Update modules/lagoon/lagoon_search/lagoon_search.install

* Remove errors in favour of logging.

* Update lagoon_search.info.yml

* Update composer.json

- Pin to solr update release

Co-authored-by: Toby Bellwood <[email protected]>
Co-authored-by: Stuart Rowlands <[email protected]>

* Update version reference to 1.3.0

Co-authored-by: Steve <[email protected]>
Co-authored-by: Alex Skrypnyk <[email protected]>
Co-authored-by: Stuart Rowlands <[email protected]>
Co-authored-by: Alex Skrypnyk <[email protected]>
Co-authored-by: Joseph Z <[email protected]>
Co-authored-by: Toby Bellwood <[email protected]>
  • Loading branch information
7 people authored Apr 29, 2020
1 parent 2b77c5d commit c51944a
Show file tree
Hide file tree
Showing 25 changed files with 304 additions and 169 deletions.
42 changes: 16 additions & 26 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ jobs:
build:
working_directory: /app
docker:
- image: integratedexperts/circleci2-builder
- image: quay.io/govcms/govcms-ci
environment:
COMPOSER_ALLOW_SUPERUSER: 1
COMPOSE_PROJECT_NAME: govcms8lagoon
Expand Down Expand Up @@ -38,7 +38,7 @@ jobs:
- run:
name: Test that Redis is functional
command: |
# Set ENABLE_REDIS env var and warm cache with a bootstrap
# Set ENABLE_REDIS env var and warm cache with a bootstrap.
docker-compose exec -T --env ENABLE_REDIS=true cli drush status
redisKeys=$(docker-compose exec -T redis redis-cli KEYS '*' | wc -l)
if [[ $redisKeys -le 1 ]]; then
Expand All @@ -47,31 +47,21 @@ jobs:
else
echo "Redis success: Redis contains $redisKeys keys."
fi
- run:
name: Push Docker images to Dockerhub
command: |
if [ "${DEPLOY_ANY_BRANCH}" != "" ] || [ "${CIRCLE_BRANCH}" == "master" ] || [ ! -z ${CIRCLE_TAG} ]; then
echo "IMAGE_VERSION_TAG=$CIRCLE_TAG">>.env
docker login -u $DOCKER_USER -p $DOCKER_PASS
export $(grep -v '^#' .env | xargs)
ahoy push
else
echo "Skipping deployment"
fi
- run:
name: Test Nginx configuration
command: |
docker-compose exec nginx nginx -t
# Wait for nginx container.
docker-compose exec -T test dockerize -wait tcp://nginx:8080 -timeout 1m
# Validate nginx configuration.
docker-compose exec -T nginx nginx -t
# Validate composer.json and composer.lock configuration for tests.
composer validate --strict -d .docker/images/nginx/tests
# Install dependencies for tests.
composer install -d .docker/images/nginx/tests
.docker/images/nginx/tests/vendor/bin/phpunit -c .docker/images/nginx/tests/phpunit.xml
workflows:
version: 2
main:
jobs:
- build:
filters:
tags:
only: /.*/
branches:
only: /.*/
# Create artifact directory.
mkdir -p /tmp/artifacts/phpunit
# Run tests and store logs in artifacts directory.
.docker/images/nginx/tests/vendor/bin/phpunit -c .docker/images/nginx/tests/phpunit.xml --log-junit /tmp/artifacts/phpunit/nginx.xml
- store_test_results:
path: /tmp/artifacts/phpunit
when: always
2 changes: 2 additions & 0 deletions .docker/Dockerfile.govcms8
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ FROM amazeeio/php:${PHP_IMAGE_VERSION}-cli-drupal-${LAGOON_IMAGE_VERSION} as bui

ARG GOVCMS_PROJECT_VERSION
ARG DRUPAL_CORE_VERSION
ARG COMPOSER_AUTH

COPY composer.* /app/

Expand All @@ -31,6 +32,7 @@ COPY .docker/images/govcms8/mariadb-client.cnf /etc/my.cnf.d
RUN mkdir -p /app/web/sites/default/files/private \
&& fix-permissions /home/.drush \
&& fix-permissions /app/drush/sites \
&& fix-permissions /etc/my.cnf.d \
&& chmod +x /app/sanitize.sh \
&& /app/sanitize.sh \
&& rm -f /app/sanitize.sh
Expand Down
11 changes: 8 additions & 3 deletions .docker/Dockerfile.solr
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
ARG CLI_IMAGE
FROM ${CLI_IMAGE} as cli

FROM amazeeio/solr:6.6
COPY --from=cli /app/web/modules/contrib/search_api_solr/solr-conf/6.x/ /solr-conf/conf/
FROM amazeeio/solr:7.5-drupal
COPY --from=cli /app/web/modules/contrib/search_api_solr/solr-conf-templates/7.x/ /solr-conf/conf/

USER root
RUN sed -i -e "s#<dataDir>\${solr.data.dir:}#<dataDir>/var/solr/\${solr.core.name}#g" /solr-conf/conf/solrconfig.xml \
&& sed -i -e "s#solr.lock.type:native#solr.lock.type:none#g" /solr-conf/conf/solrconfig.xml \
&& sed -i -e "s#solr.install.dir=../../..#solr.install.dir=/opt/solr#g" /solr-conf/conf/solrcore.properties

RUN sed -i -e "s#SEARCH_API_SOLR_MIN_SCHEMA_VERSION#8.3.8#g" /solr-conf/conf/schema.xml \
&& sed -i -e "s#SEARCH_API_SOLR_MIN_SCHEMA_VERSION#8.3.8#g" /solr-conf/conf/solrconfig.xml \
&& sed -i -e "s#drupal-8.3.4#drupal-8.3.8#g" /opt/solr/server/solr/mycores/drupal/conf/schema.xml \
&& sed -i -e "s#drupal-8.3.4#drupal-8.3.8#g" /opt/solr/server/solr/mycores/drupal/conf/solrconfig.xml

USER solr
RUN precreate-core drupal /solr-conf
RUN precreate-core drupal /solr-conf/conf
CMD ["solr-foreground"]
1 change: 1 addition & 0 deletions .docker/Dockerfile.test
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
ARG CLI_IMAGE
ARG LAGOON_IMAGE_VERSION
ARG PHP_IMAGE_VERSION
ARG COMPOSER_AUTH
FROM ${CLI_IMAGE} as cli

FROM amazeeio/php:${PHP_IMAGE_VERSION}-cli-drupal-${LAGOON_IMAGE_VERSION}
Expand Down
11 changes: 11 additions & 0 deletions .docker/images/govcms8/govcms.site.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,21 @@
# It is not intended to be used by clients outside Lagoon and may change.
#

# Scaffold tooling moves the scripts to use the `ci.prod` alias. This is marked
# as deprecated and will be removed in an upcomming release.
# @deprecrated 8.2
prod:
root: /app
host: ssh.lagoon.svc
user: ${env.LAGOON_PROJECT}-master
uri: nginx-${env.LAGOON_PROJECT}-master.govcms.amazee.io
ssh:
options: -q -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -p 2020 -F /dev/null

ci.prod:
root: /app
host: ssh.lagoon.svc
user: ${env.LAGOON_PROJECT}-master
uri: nginx-${env.LAGOON_PROJECT}-master.govcms.amazee.io
ssh:
options: -q -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -p 2020 -F /dev/null
3 changes: 3 additions & 0 deletions .docker/images/govcms8/settings/production.settings.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,6 @@
$config['environment_indicator.indicator']['name'] = 'Edit Domain';
}
}

// Disable temporary file deletion (GOVCMSD8-576).
$config['system.file']['temporary_maximum_age'] = 0;
7 changes: 6 additions & 1 deletion .docker/images/govcms8/settings/settings.php
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,11 @@ public function __toString() {
}
}

// Enforce correct solr server configuration (GOVCMS-4634)
// Fix for 8.5.0 and the solr upgrade.
$config['search_api.server.lagoon_solr']['backend_config']['connector_config']['path'] = '/';
$config['search_api.server.lagoon_solr']['backend_config']['connector_config']['core'] = 'drupal';

// Hash Salt
if (getenv('LAGOON')) {
$settings['hash_salt'] = hash('sha256', getenv('LAGOON_PROJECT'));
Expand Down Expand Up @@ -278,7 +283,7 @@ public function __toString() {
$config['stage_file_proxy.settings']['origin'] = getenv('STAGE_FILE_PROXY_URL');
}

if (getenv('DEV_MODE')) {
if (getenv('DEV_MODE') && getenv('DEV_MODE') == 'true') {
if (!drupal_installation_attempted()) {
if (file_exists(__DIR__ . '/development.settings.php')) {
include __DIR__ . '/development.settings.php';
Expand Down
5 changes: 5 additions & 0 deletions .docker/images/nginx/helpers/207-security-headers.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Add additional security headers to each requeest served
# by nginx.

add_header X-XSS-Protection "${X_XSS_PROTECTION:-1; mode=block}";
add_header X-Content-Type-Options "${X_CONTENT_TYPE_OPTIONS:-nosniff}";
80 changes: 62 additions & 18 deletions .docker/images/nginx/tests/bootstrap.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,29 +6,48 @@

include_once __DIR__ . '/vendor/autoload.php';

function get_curl_headers($path = "/", $opts = NULL)
{
$uri = getenv('LOCALDEV_URL') ?: 'http://nginx:8080';

$response = null;
/**
* Execute CURL and get response headers.
*
* @param string $path
* (optional) URL path to get the headers for. Defaults to '/'.
* @param null|string $opts
* (optional) CURL-compatible string of headers. Defaults to NULL.
*
* @return array
* Array of returned headers.
*
* @throws \RuntimeException
* If CURL exited with an error.
*/
function get_curl_headers($path = '/', $opts = NULL) {
$uri = 'http://nginx:8080';
$uri = $uri . '/' . ltrim($path, '/');

$path = '/' . ltrim($path, '/');
$response = NULL;
exec("docker-compose exec -T test curl -s {$uri} -I {$opts} 2>&1", $response, $ret);

exec("docker-compose exec -T test curl {$uri}{$path} -I {$opts} 2>/dev/null", $response);
if (is_debug()) {
fwrite(STDERR, sprintf('CURL exit code : %s', $ret) . PHP_EOL);
fwrite(STDERR, sprintf('CURL URI : %s', $uri) . PHP_EOL);
fwrite(STDERR, sprintf('CURL response : %s', PHP_EOL . implode(PHP_EOL, $response)) . PHP_EOL);
}

if (empty($response)) {
return [];
if ($ret != 0) {
throw new \RuntimeException(sprintf('CURL exited with error code "%s" and response %s.', $ret, PHP_EOL . implode(PHP_EOL, $response)));
}

$response = array_map('trim', $response);

foreach ($response as $line) {
if (strpos($line, 'HTTP') !== false) {
if (strpos($line, 'HTTP') !== FALSE) {
$part = explode(' ', $line);
$headers['Status'] = trim($part[1]);
continue;
}

$part = explode(':', $line);

if (count($part) == 2) {
$headers[$part[0]] = trim($part[1]);
}
Expand All @@ -37,18 +56,43 @@ function get_curl_headers($path = "/", $opts = NULL)
return $headers;
}

function curl_get_content($path = "/", $opts = NULL)
{
$uri = getenv('LOCALDEV_URL') ?: 'http://nginx:8080';
/**
* Execute CURL and get response.
*
* @param string $path
* (optional) URL path to get the headers for. Defaults to '/'.
* @param null|string $opts
* (optional) String of CURL options. Defaults to NULL.
*
* @return string
* Response as a string.
*
* @throws \RuntimeException
* If CURL exited with an error.
*/
function curl_get_content($path = '/', $opts = NULL) {
$uri = 'http://nginx:8080';
$uri = $uri . '/' . ltrim($path, '/');

$response = null;
$path = '/' . ltrim($path, '/');
$response = NULL;
exec("docker-compose exec -T test curl -s {$uri} {$opts} 2>&1", $response, $ret);

exec("docker-compose exec -T test curl {$uri}{$path} {$opts} 2>/dev/null", $response);
if (is_debug()) {
fwrite(STDERR, sprintf('CURL exit code : %s', $ret) . PHP_EOL);
fwrite(STDERR, sprintf('CURL URI : %s', $uri) . PHP_EOL);
fwrite(STDERR, sprintf('CURL response : %s', PHP_EOL . implode(PHP_EOL, $response)) . PHP_EOL);
}

if (empty($response)) {
return FALSE;
if ($ret != 0) {
throw new \RuntimeException(sprintf('CURL exited with error code "%s" and response %s.', $ret, PHP_EOL . implode(PHP_EOL, $response)));
}

return $response;
}

/**
* Check if tests are running in debug mode.
*/
function is_debug() {
return in_array('--debug', $_SERVER['argv'], TRUE);
}
1 change: 1 addition & 0 deletions .docker/images/nginx/tests/composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
"name": "govcmstests/nginx",
"description": "Testing framework for the nginx image.",
"type": "project",
"license": "GPL-2.0-or-later",
"authors": [
{
"name": "Steve Worley",
Expand Down
39 changes: 15 additions & 24 deletions .docker/images/nginx/tests/src/BlocksTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,15 @@
/**
* Ensure that the blocks are respected by nginx.
*/
class BlocksTest extends TestCase
{
class BlocksTest extends TestCase {

/**
* Aggressive bots.
*
* @return array
* List of user agents.
*/
public function provideAggressiveAgents()
{
public function providerAggressiveAgents() {
return [
['8LEGS'],
// ['AhfresBot'], # This 500s?
Expand All @@ -39,8 +37,7 @@ public function provideAggressiveAgents()
* @return array
* List of user agents.
*/
public function provideMicrosoftAgents()
{
public function providerMicrosoftAgents() {
return [
['Skype.for.Business'],
['Microsoft.Office'],
Expand All @@ -53,8 +50,7 @@ public function provideMicrosoftAgents()
* @return array
* List of paths.
*/
public function provideWordpressPaths()
{
public function providerWordpressPaths() {
return [
['/wp-admin'],
// ['/wp-admin/index.php'], # 500s
Expand All @@ -75,8 +71,7 @@ public function provideWordpressPaths()
* @return array
* List of query strings.
*/
public function provideQueryStrings()
{
public function providerQueryStrings() {
return [
['?q=node/add'],
['?q=user/register'],
Expand All @@ -86,53 +81,49 @@ public function provideQueryStrings()
/**
* Ensure that aggressive bots are blocked.
*
* @dataProvider provideAggressiveAgents
* @dataProvider providerAggressiveAgents
*/
public function testAggressiveCrawlerBlock($ua)
{
public function testAggressiveCrawlerBlock($ua) {
$headers = \get_curl_headers("/", "--user-agent '{$ua}'");
$this->assertEquals(403, $headers['Status']);
}

/**
* Ensure that Microsofts home check is prevented.
*
* @dataProvider provideMicrosoftAgents
* @dataProvider providerMicrosoftAgents
*/
public function testMicrosoftHomeCall($ua)
{
public function testMicrosoftHomeCall($ua) {
$headers = \get_curl_headers("/", "--user-agent '{$ua}'");
$this->assertEquals(403, $headers['Status']);
}

/**
* Ensure the autodiscover.xml files are restricted.
*/
public function testAutodiscover()
{
public function testAutodiscover() {
$headers = \get_curl_headers("/autodiscover.xml");
$this->assertEquals(403, $headers['Status']);
}

/**
* Ensure that wordpress-like paths are blocked.
*
* @dataProvider provideWordpressPaths
* @dataProvider providerWordpressPaths
*/
public function testWordpressAttacks($path)
{
public function testWordpressAttacks($path) {
$headers = \get_curl_headers($path);
$this->assertEquals(403, $headers['Status']);
}

/**
* Ensure common query strings vectors are restricted.
*
* @dataProvider provideQueryStrings
* @dataProvider providerQueryStrings
*/
public function testQueryStringBlock($query)
{
public function testQueryStringBlock($query) {
$headers = \get_curl_headers($query);
$this->assertEquals(403, $headers['Status']);
}

}
Loading

0 comments on commit c51944a

Please sign in to comment.