Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 0 additions & 32 deletions .github/workflows/dependabot-auto-merge.yml

This file was deleted.

23 changes: 0 additions & 23 deletions .github/workflows/php-cs-fixer.yml

This file was deleted.

26 changes: 0 additions & 26 deletions .github/workflows/phpstan.yml

This file was deleted.

81 changes: 47 additions & 34 deletions .github/workflows/run-tests.yml
Original file line number Diff line number Diff line change
@@ -1,47 +1,60 @@
name: run-tests

name: Tests
on:
push:
branches: [main]
branches:
- main
pull_request:
branches: [main]

branches:
- main
workflow_dispatch:
jobs:
test:
runs-on: ${{ matrix.os }}
# Unit tests back (phpunit)
laravel-tests:
runs-on: ubuntu-latest
strategy:
fail-fast: true
matrix:
os: [ubuntu-latest, windows-latest]
php: [8.1]
laravel: [9.*]
stability: [prefer-lowest, prefer-stable]
include:
- laravel: 9.*
testbench: 7.*

name: P${{ matrix.php }} - L${{ matrix.laravel }} - ${{ matrix.stability }} - ${{ matrix.os }}

- php: 8.3
env:
LARAVEL: 11.*
TESTBENCH: 9.*
- php: 8.4
env:
LARAVEL: 11.*
TESTBENCH: 9.*
- php: 8.4
env:
LARAVEL: 12.*
TESTBENCH: 10.*
env: ${{ matrix.env }}
name: P${{ matrix.php }} - L${{ matrix.env.LARAVEL }} - TB${{ matrix.env.TESTBENCH }}
steps:
- name: Checkout code
uses: actions/checkout@v3

- uses: actions/checkout@v4
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}
extensions: dom, curl, libxml, mbstring, zip, pcntl, pdo, sqlite, pdo_sqlite, bcmath, soap, intl, gd, exif, iconv, imagick, fileinfo
coverage: none

- name: Setup problem matchers
run: |
echo "::add-matcher::${{ runner.tool_cache }}/php.json"
echo "::add-matcher::${{ runner.tool_cache }}/phpunit.json"

- name: Install dependencies
extensions: mbstring, dom, fileinfo, mysql
- name: Get composer cache directory
id: composer-cache
run: echo "::set-output name=dir::$(composer config cache-files-dir)"
- name: Cache composer dependencies
uses: actions/cache@v4
with:
path: ${{ steps.composer-cache.outputs.dir }}
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
restore-keys: ${{ runner.os }}-composer-
- name: Install Composer dependencies
run: |
composer require "laravel/framework:${{ matrix.laravel }}" "orchestra/testbench:${{ matrix.testbench }}" --no-interaction --no-update
composer update --${{ matrix.stability }} --prefer-dist --no-interaction

- name: Execute tests
run: vendor/bin/pest
composer require "laravel/framework:${LARAVEL}" "orchestra/testbench:${TESTBENCH}" --no-interaction --no-update --prefer-dist
composer update --prefer-stable --prefer-dist --no-interaction
- name: Execute tests (Unit and Feature tests) via PHPUnit
run: ./vendor/bin/pest
- uses: 8398a7/action-slack@v3
if: failure() && (github.base_ref == 'main' || inputs.is-package)
with:
status: ${{ job.status }}
fields: job, message, author, repo
env:
MATRIX_CONTEXT: ${{ toJson(matrix) }}
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
28 changes: 0 additions & 28 deletions .github/workflows/update-changelog.yml

This file was deleted.

1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,4 @@ testbench.yaml
vendor
node_modules
.php-cs-fixer.cache
.phpunit.cache/
66 changes: 56 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,17 @@
# Occulta

## Purpose
Save a versioned and encrypted copy of .env on a storage disk (eg: S3)

Save a versioned and encrypted copy of .env on aws s3
## How it works
Occulta uses [AWS KMS](https://aws.amazon.com/kms/) and [Envelope encryption strategy](https://docs.aws.amazon.com/kms/latest/developerguide/kms-cryptography.html#enveloping) to encrypt your `.env` file and store it on a given laravel disk (eg: S3).
It also keeps a versioned history of your encrypted `.env` files, so you can restore previous versions if needed.
<br>
Occulta will create an archive containing your encrypted environment file and an encrypted key file, which will be used by occulta to decrypt your env when needed.

## Installation

This package requires Laravel 8.x or higher.
## Installation
This package requires Laravel 11.x or higher, php's extensions openssl and zip.

You can install the package via composer:

Expand All @@ -15,17 +22,26 @@ composer require code16/occulta
Next you should publish the config file :

```bash
php artisan vendor:publish --provider="Code16\Occulta\OccultaServiceProvider"
php artisan vendor:publish --tag=occulta-config
```

and setup your values (especially the kms `key_id` and `destination disk`) in your `config/occulta.php` file :

```php

'key_id' => '0904c439-ff1f-4e9d-8a26-4e32ced6fe0x',

'destination_disk' => 's3_backup',
];
return [
// kms key id as seen in aws's kms dashboard (usually it looks like an uuid)
'key_id' => '0904c439-ff1f-4e9d-8a26-4e32ced6fe0x',

[...]

'destination_disk' => 's3_backup',
'destination_path' => null, // defaults to 'dotenv/'

// If you want to backup an env file with a suffix such as .env.production, you can set this to your desired suffix
'env_suffix' => null, // eg: 'production'

[...]
];
```

Then, you should setup credentials to the proper aws user [allowed](https://docs.aws.amazon.com/kms/latest/developerguide/key-policies.html#key-policy-default-allow-users) to "use" the given kms key, by adding a kms section in your `config/services.php` file :
Expand All @@ -38,7 +54,7 @@ Then, you should setup credentials to the proper aws user [allowed](https://docs
],
```

Nom you should schedule tasks for backup and cleanup in `app/Console/Kernel.php` :
Now you should schedule tasks for backup and cleanup in `app/Console/Kernel.php` (`bootstrap/app.php` since Laravel 11) :

```php
protected function schedule(Schedule $schedule)
Expand All @@ -47,3 +63,33 @@ Nom you should schedule tasks for backup and cleanup in `app/Console/Kernel.php`
$schedule->command('occulta:clean')->dailyAt('02:00');
}
```

### Decrypting an encrypted env archive
If you need to decrypt an encrypted env archive, you can use the `occulta:decrypt` command:

```bash
php artisan occulta:decrypt path/to/encrypted/archive.zip
```

Occulta will use your KMS configuration and AWS access and secret keys to decrypt your env file.
<br>
> [!IMPORTANT]
> It is likely that these credentials where in your lost .env, then, you can follow the [recovery procedure](docs/RECOVERY.md) to restore your environment.


## Testing

The package comes with a comprehensive test suite. To run the tests, you can use the following command:

```bash
composer test
```

The tests cover:

- The main `Occulta` class functionality for encrypting and decrypting values and files
- The `EncryptFileWithKmsCommand` for encrypting .env files and storing them
- The `DecryptFileWithKmsCommand` for extracting and decrypting .env files from zip archives
- The `CleanupEncryptedDotenvsCommand` for managing the history of encrypted .env files

The tests use mocks for AWS KMS to avoid actual AWS calls during testing.
27 changes: 18 additions & 9 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,21 +13,30 @@
"name": "Arnaud Becher",
"email": "[email protected]",
"role": "Developer"
},
{
"name": "Lucien Puget",
"email": "[email protected]",
"role": "Developer"
}
],
"require": {
"php": "^8.1",
"spatie/laravel-package-tools": "^1.9.2",
"php": "^8.3",
"ext-openssl": "*",
"ext-zip": "*",
"ext-zlib": "*",
"aws/aws-sdk-php": "^3.222",
"illuminate/contracts": "^9.0|^10.0|^11.0|^12.0",
"ext-zlib": "*"
"illuminate/contracts": "^11.0|^12.0",
"laravel/prompts": "^0.3.5",
"spatie/laravel-package-tools": "^1.9.2"
},
"require-dev": {
"nunomaduro/collision": "^6.0|^7.0|^8.0",
"orchestra/testbench": "^7.0|^8.0|^9.0|^10.0",
"pestphp/pest": "^1.21|^3.0",
"pestphp/pest-plugin-laravel": "^1.1|^3.0",
"phpunit/phpunit": "^9.5|^10.0|^11.0",
"code16/pint-config": "^1.2",
"nunomaduro/collision": "^8.0",
"orchestra/testbench": "^9.0|^10.0",
"pestphp/pest": "^3.0",
"pestphp/pest-plugin-laravel": "^3.0",
"phpunit/phpunit": "^10.0|^11.0",
"spatie/laravel-ray": "^1.26"
},
"autoload": {
Expand Down
9 changes: 6 additions & 3 deletions config/occulta.php
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
<?php

// config for Code16/Occulta
return [
// kms key id as seen in aws's kms dashboard (usually it looks like uuid)
// kms key id as seen in aws's kms dashboard (usually it looks like an uuid)
'key_id' => '',

// Associative array of custom encryption's context
Expand All @@ -10,9 +11,11 @@
// 'my_secret_key' => 'my_secret_value'
],

'should_compress' => env('OCCULTA_SHOULD_COMPRESS', false),

'destination_disk' => '',
'destination_path' => 'dotenv/',

// If you want to backup an env file with a suffix such as .env.production, you can set this to your desired suffix
'env_suffix' => null, // eg: 'production'

'number_of_encrypted_dotenv_to_keep_when_cleaning_up' => env('NUMBER_OF_ENCRYPTED_DOTENV_TO_KEEP_WHEN_CLEANING_UP', 7),

Expand Down
Loading
Loading