os2web / os2web_key
OS2Web key
Installs: 323
Dependents: 0
Suggesters: 0
Security: 0
Stars: 0
Watchers: 3
Forks: 1
Open Issues: 0
Type:drupal-module
Requires
- php: ^8.1
- ext-openssl: *
- drupal/core: ^9 || ^10
- drupal/key: ^1.17
- itk-dev/serviceplatformen: ^1.6
- itk-dev/vault: ^0.1
Requires (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
- phpunit/phpunit: ^9.6
README
Key types and providers for OS2Web built on the Key module.
The OS2Web key module provides two key types, Certificate and OpenID Connect (OIDC). It also comes with two key providers, Azure Key Vault and HashiCorp Vault.
See the Key Developer Guide for details in how to use keys in Drupal.
Installation
composer require os2web/os2web_key drush pm:install os2web_key
Keys are managed on /admin/config/system/keys
.
Key types
Certificate
This key type handles PKCS 12 or Privacy-Enhanced Mail (PEM) certificate with an optional password (passphrase).
Managing the key:
Use in a form:
$form['key'] => [ '#type' => 'key_select', '#key_filters' => [ 'type' => 'os2web_key_certificate', ], ];
The KeyHelper
can be used to get
the actual certificates (parts):
<?php use Drupal\os2web_key\KeyHelper; use Drupal\key\KeyRepositoryInterface; // Use dependency injection for this. /** @var KeyRepositoryInterface $repository */ $repository = \Drupal::service('key.repository'); /** @var KeyHelper $helper */ $helper = \Drupal::service(KeyHelper::class); // Use `drush key:list` to list your keys. $key = $repository->getKey('my_key'); [ // Passwordless certificate. CertificateKeyType::CERT => $certificate, CertificateKeyType::PKEY => $privateKey, ] = $helper->getCertificates($key);
Note: The parsed certificate has no password.
OpenID Connect (OIDC)
Managing the key:
Example use in a form:
$form['key'] => [ '#type' => 'key_select', '#key_filters' => [ 'type' => 'os2web_key_oidc, ], ];
Get the OIDC config:
<?php use Drupal\key\KeyRepositoryInterface; use Drupal\os2web_key\Plugin\KeyType\OidcKeyType; // Use dependency injection for this. /** @var KeyRepositoryInterface $repository */ $repository = \Drupal::service('key.repository'); $key = $repository->getKey('openid_connect_ad'); [ OidcKeyType::DISCOVERY_URL => $discoveryUrl, OidcKeyType::CLIENT_ID => $clientId, OidcKeyType::CLIENT_SECRET => $clientSecret, ] = $helper->getOidcValues($key);
Providers
The module comes with two key providers.
Azure Key Vault
Used for fetching certificate from Azure Key vault.
HashiCorp Vault
Used to fetch any sort of secret string from HashiCorp vault. Note that this can only provide string values, i.e. no binary files.
To use this provider you must configure the following in settings.local.php
:
$settings['os2web_vault_role_id'] = '{ROLE_ID}'; $settings['os2web_vault_secret_id'] = '{SECRET_ID}'; $settings['os2web_vault_url'] = '{VAULT_URL}';
Coding standards
Our coding are checked by GitHub Actions (cf. .github/workflows/pr.yml). Use the commands below to run the checks locally.
PHP
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.3-fpm composer coding-standards-apply # Check that code adheres to the coding standards docker run --rm --volume ${PWD}:/app --workdir /app itkdev/php8.3-fpm composer coding-standards-check
Markdown
docker run --rm --volume $PWD:/md peterdavehello/markdownlint markdownlint --ignore vendor --ignore LICENSE.md '**/*.md' --fix docker run --rm --volume $PWD:/md peterdavehello/markdownlint markdownlint --ignore vendor --ignore LICENSE.md '**/*.md'
Code analysis
We use PHPStan for static code analysis.
Running static code analysis on a standalone Drupal module is a bit tricky, so we use a helper script to run the analysis:
docker run --rm --volume ${PWD}:/app --workdir /app itkdev/php8.3-fpm ./scripts/code-analysis
Unit tests
We use PHPUnit 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 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:
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
# 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
# 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