Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Added HashiCorp vault key provider #4

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 13 commits into from
Jan 20, 2025
35 changes: 32 additions & 3 deletions .github/workflows/pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
php-versions: [ '8.1' ]
php-versions: [ '8.3' ]
dependency-version: [ prefer-lowest, prefer-stable ]
steps:
- uses: actions/checkout@master
Expand Down Expand Up @@ -58,7 +58,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
php-versions: [ '8.1' ]
php-versions: [ '8.3' ]
steps:
- uses: actions/checkout@master
- name: Setup PHP, with composer and extensions
Expand Down Expand Up @@ -90,7 +90,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
php-versions: [ '8.1' ]
php-versions: [ '8.3' ]
steps:
- uses: actions/checkout@master
- name: Setup PHP, with composer and extensions
Expand All @@ -114,6 +114,35 @@ jobs:
run: |
./scripts/code-analysis

php-unit-tests:
name: PHP unit tests
runs-on: ubuntu-latest
strategy:
matrix:
php-versions: [ '8.3' ]
steps:
- uses: actions/checkout@master
- name: Setup PHP, with composer and extensions
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php-versions }}
extensions: json
coverage: none
tools: composer:v2
# https://github.com/shivammathur/setup-php#cache-composer-dependencies
- name: Get composer cache directory
id: composer-cache
run: echo "::set-output name=dir::$(composer config cache-files-dir)"
- name: Cache dependencies
uses: actions/cache@v2
with:
path: ${{ steps.composer-cache.outputs.dir }}
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
restore-keys: ${{ runner.os }}-composer-
- name: Unit tests
run: |
./scripts/unit-tests

coding-standards-markdown:
name: Markdown coding standards
runs-on: ubuntu-latest
Expand Down
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

* [PR-4](https://github.com/OS2web/os2web_key/pull/4)
Added HashiCorp Vault key provider
* [PR-2](https://github.com/OS2web/os2web_key/pull/2)
Updated documentation
* [PR-1](https://github.com/OS2web/os2web_key/pull/1)
Expand Down
91 changes: 81 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
Key types and providers for OS2Web built on the [Key module](https://www.drupal.org/project/key).

The OS2Web key module provides two _key types_, [Certificate](#certificate) and [OpenID Connect
(OIDC)](#openid-connect-oidc). Two _key providers_, [Azure Key Vault](#azure-key-vault) and [Infisical](#infisical), are
planned, but not yet implemented.
(OIDC)](#openid-connect-oidc). It also comes with two _key providers_,
[Azure Key Vault](#azure-key-vault) and [HashiCorp Vault](#hashicorp-vault).

See [the Key Developer Guide](https://www.drupal.org/docs/contributed-modules/key/developer-guide) for details in how to
use keys in Drupal.
Expand Down Expand Up @@ -106,13 +106,24 @@ $key = $repository->getKey('openid_connect_ad');

## Providers

The module comes with two key providers.

### Azure Key Vault

`@todo` <https://azure.microsoft.com/en-us/products/key-vault>
Used for fetching certificate from Azure Key vault.

### HashiCorp Vault

### Infisical
Used to fetch any sort of secret string from HashiCorp vault. Note that
this can only provide string values, i.e. no binary files.

`@todo` <https://infisical.com/>
To use this provider you must configure the following in `settings.local.php`:

``` php
$settings['os2web_vault_role_id'] = '{ROLE_ID}';
$settings['os2web_vault_secret_id'] = '{SECRET_ID}';
$settings['os2web_vault_url'] = '{VAULT_URL}';
```

## Coding standards

Expand All @@ -122,11 +133,11 @@ below to run the checks locally.
### PHP

```shell
docker run --rm --volume ${PWD}:/app --workdir /app itkdev/php8.1-fpm composer install
docker run --rm --volume ${PWD}:/app --workdir /app itkdev/php8.3-fpm composer install
# Fix (some) coding standards issues
docker run --rm --volume ${PWD}:/app --workdir /app itkdev/php8.1-fpm composer coding-standards-apply
docker run --rm --volume ${PWD}:/app --workdir /app itkdev/php8.3-fpm composer coding-standards-apply
# Check that code adheres to the coding standards
docker run --rm --volume ${PWD}:/app --workdir /app itkdev/php8.1-fpm composer coding-standards-check
docker run --rm --volume ${PWD}:/app --workdir /app itkdev/php8.3-fpm composer coding-standards-check
```

### Markdown
Expand All @@ -140,9 +151,69 @@ docker run --rm --volume $PWD:/md peterdavehello/markdownlint markdownlint --ign

We use [PHPStan](https://phpstan.org/) for static code analysis.

Running statis code analysis on a standalone Drupal module is a bit tricky, so we use a helper script to run the
Running static code analysis on a standalone Drupal module is a bit tricky, so we use a helper script to run the
analysis:

```shell
docker run --rm --volume ${PWD}:/app --workdir /app itkdev/php8.3-fpm ./scripts/code-analysis
```

## Unit tests

We use [PHPUnit](https://phpunit.de/documentation.html) for unit testing.

Testing mostly centers around the conversion and parsing of certificates. For this purpose a bunch of test
certificates has been generated. See [Test certificates](#test-certificates) for how this is done.

Running PHPUnit tests in a standalone Drupal module is a bit tricky, so we use a helper script to run the
analysis:

```shell
docker run --rm --volume ${PWD}:/app --workdir /app itkdev/php8.1-fpm ./scripts/code-analysis
docker run --rm --volume ${PWD}:/app --workdir /app itkdev/php8.3-fpm ./scripts/unit-tests
```

### Test certificates

Certificates have been generated in the follow way

```shell
# p12 with password
openssl req -x509 -newkey rsa:4096 -days 365 -subj "/CN=example.com" -passout pass:test -keyout test.key -out test.crt
openssl pkcs12 -export -out test_with_passphrase.p12 -passin pass:test -passout pass:test -inkey test.key -in test.crt
openssl pkcs12 -in test_with_passphrase.p12 -passin pass:test -noenc

# p12 without password
openssl req -x509 -newkey rsa:4096 -days 365 -subj "/CN=example.com" -passout pass:'' -keyout test_without_passphrase.key -out test_without_passphrase.crt
openssl pkcs12 -export -out test_without_passphrase.p12 -passin pass:'' -passout pass:'' -inkey test_without_passphrase.key -in test_without_passphrase.crt
openssl pkcs12 -in test_without_passphrase.p12 -passin pass:'' -noenc

# PEM with password
openssl req -x509 -newkey rsa:4096 -days 365 -subj "/CN=example.com" -passout pass:test -keyout test.key -out test.crt
cat test.crt test.key > test_with_passphrase.pem
openssl x509 -in test_with_passphrase.pem

# PEM without password
openssl req -x509 -newkey rsa:4096 -days 365 -subj "/CN=example.com" -passout pass:'' -keyout test_without_passphrase.key -out test_without_passphrase.crt -noenc
cat test_without_passphrase.crt test_without_passphrase.key > test_without_passphrase.pem
openssl x509 -in test_without_passphrase.pem
```

Extraction of certificate and private key parts in the following way

```shell
# P12 with passphrase
openssl pkcs12 -in test_with_passphrase.p12 -passin pass:test -clcerts -nokeys | sed -ne '/-----BEGIN CERTIFICATE-----/,/-----END CERTIFICATE-----/p' > p12_with_passphrase_cert.txt
openssl pkcs12 -in test_with_passphrase.p12 -passin pass:test -nocerts -nodes | sed -ne '/-----BEGIN PRIVATE KEY-----/,/-----END PRIVATE KEY-----/p' > p12_with_passphrase_pkey.txt

# P12 without passphrase
openssl pkcs12 -in test_without_passphrase.p12 -passin pass: -clcerts -nokeys | sed -ne '/-----BEGIN CERTIFICATE-----/,/-----END CERTIFICATE-----/p' > p12_without_passphrase_cert.txt
openssl pkcs12 -in test_without_passphrase.p12 -passin pass: -nocerts -nodes | sed -ne '/-----BEGIN PRIVATE KEY-----/,/-----END PRIVATE KEY-----/p' > p12_without_passphrase_pkey.txt

# PEM with passphrase
openssl x509 -in test_with_passphrase.pem -passin pass:test -out pem_with_passphrase_cert.txt
openssl pkey -in test_with_passphrase.pem -passin pass:test -out pem_with_passphrase_pkey.txt

# PEM without passphrase
openssl x509 -in test_without_passphrase.pem -passin pass: -out pem_without_passphrase_cert.txt
openssl pkey -in test_without_passphrase.pem -passin pass: -out pem_without_passphrase_pkey.txt
```
13 changes: 11 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,22 +13,31 @@
"php": "^8.1",
"ext-openssl": "*",
"drupal/core": "^9 || ^10",
"drupal/key": "^1.17"
"drupal/key": "^1.17",
"itk-dev/serviceplatformen": "^1.6",
"itk-dev/vault": "^0.1"
},
"require-dev": {
"dealerdirect/phpcodesniffer-composer-installer": "^1.0",
"drupal/coder": "^8.3",
"drupal/core-dev": "^9 || ^10",
"ergebnis/composer-normalize": "^2.42",
"mglaman/phpstan-drupal": "^1.2",
"phpstan/extension-installer": "^1.3",
"phpstan/phpstan-deprecation-rules": "^1.1"
"phpstan/phpstan-deprecation-rules": "^1.1",
"phpunit/phpunit": "^9.6"
},
"repositories": [
{
"type": "composer",
"url": "https://packages.drupal.org/8"
}
],
"autoload-dev": {
"psr-4": {
"Drupal\\Tests\\os2web_key\\": "tests/src/"
}
},
"config": {
"allow-plugins": {
"dealerdirect/phpcodesniffer-composer-installer": true,
Expand Down
8 changes: 7 additions & 1 deletion os2web_key.services.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,11 @@ services:
arguments: [ 'os2web_key' ]

Drupal\os2web_key\KeyHelper:
autowire: true
arguments:
- '@logger.channel.os2web_key'
$logger: '@logger.channel.os2web_key'

Drupal\os2web_key\Services\Psr16CacheAdapter:
autowire: true
arguments:
$cacheBackend: '@cache.default'
29 changes: 13 additions & 16 deletions scripts/code-analysis
Original file line number Diff line number Diff line change
Expand Up @@ -11,37 +11,34 @@ drupal_composer() {
composer --working-dir="$drupal_dir" --no-interaction "$@"
}

# Create new Drupal 9 project
# Create new Drupal 10 project
if [ ! -f "$drupal_dir/composer.json" ]; then
composer --no-interaction create-project drupal/recommended-project:^9 "$drupal_dir"
composer --no-interaction create-project drupal/recommended-project:^10 "$drupal_dir"
fi
# Copy our code into the modules folder

# Clean up
rm -fr "${drupal_dir:?}/$module_path"

mkdir -p "$drupal_dir/$module_path"
# https://stackoverflow.com/a/15373763
# rsync --archive --compress . --filter=':- .gitignore' --exclude "$drupal_dir" --exclude .git "$drupal_dir/$module_path"

# The rsync command in not available in itkdev/php8.1-fpm

git config --global --add safe.directory /app
# Copy module files into module path
for f in $(git ls-files); do
mkdir -p "$drupal_dir/$module_path/$(dirname "$f")"
cp "$f" "$drupal_dir/$module_path/$f"
done
rsync --archive --compress . --filter=':- .gitignore' --exclude "$drupal_dir" --exclude .git "$drupal_dir/$module_path"

drupal_composer config minimum-stability dev

drupal_composer --append repositories.os2web/os2web_key path "$module_path"

# Allow ALL plugins
# https://getcomposer.org/doc/06-config.md#allow-plugins
drupal_composer config --no-plugins allow-plugins true

# Making Drupal 10 compatible
drupal_composer require psr/http-message:^1.0
drupal_composer require mglaman/composer-drupal-lenient
drupal_composer config --merge --json extra.drupal-lenient.allowed-list '["drupal/coc_forms_auto_export", "drupal/webform_node_element"]'

drupal_composer require wikimedia/composer-merge-plugin
drupal_composer config extra.merge-plugin.include "$module_path/composer.json"
# https://www.drupal.org/project/drupal/issues/3220043#comment-14845434
drupal_composer require --dev symfony/phpunit-bridge
drupal_composer --no-interaction install


# Run PHPStan
(cd "$drupal_dir/$module_path" && ../../../../vendor/bin/phpstan)
43 changes: 43 additions & 0 deletions scripts/unit-tests
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#!/usr/bin/env bash
script_dir=$(pwd)
module_name=$(basename "$script_dir")
drupal_dir=vendor/drupal-module-unit-tests-analysis
# Relative to $drupal_dir
module_path=web/modules/contrib/$module_name

cd "$script_dir" || exit

drupal_composer() {
composer --working-dir="$drupal_dir" --no-interaction "$@"
}

# Create new Drupal 10 project
if [ ! -f "$drupal_dir/composer.json" ]; then
composer --no-interaction create-project drupal/recommended-project:^10 "$drupal_dir"
fi
# Copy our code into the modules folder
mkdir -p "$drupal_dir/$module_path"
# https://stackoverflow.com/a/15373763
rsync --archive --compress . --filter=':- .gitignore' --exclude "$drupal_dir" --exclude .git "$drupal_dir/$module_path"

drupal_composer config minimum-stability dev

drupal_composer --append repositories.os2web/os2web_key path "$module_path"

# Allow ALL plugins
# https://getcomposer.org/doc/06-config.md#allow-plugins
drupal_composer config --no-plugins allow-plugins true

# Making Drupal 10 compatible
drupal_composer require psr/http-message:^1.0
drupal_composer require mglaman/composer-drupal-lenient
drupal_composer config --merge --json extra.drupal-lenient.allowed-list '["drupal/coc_forms_auto_export", "drupal/webform_node_element"]'

drupal_composer require wikimedia/composer-merge-plugin
drupal_composer config extra.merge-plugin.include "$module_path/composer.json"
# https://www.drupal.org/project/drupal/issues/3220043#comment-14845434
drupal_composer require --dev symfony/phpunit-bridge
drupal_composer --no-interaction install

# Run PHPUnit
(cd "$drupal_dir" && vendor/bin/phpunit --configuration web/core/phpunit.xml.dist "$module_path/tests/src/Unit/KeyHelperUnitTest.php")
10 changes: 10 additions & 0 deletions src/Exception/Exception.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

namespace Drupal\os2web_key\Exception;

/**
* OS2Web key base exception.
*/
class Exception extends \Exception {

}
10 changes: 10 additions & 0 deletions src/Exception/FileException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

namespace Drupal\os2web_key\Exception;

/**
* File exception.
*/
class FileException extends Exception {

}
Loading
Loading