2
2
3
3
namespace DotenvVault ;
4
4
use Dotenv \Dotenv ;
5
- use Dotenv \Exception \InvalidPathException ;
6
5
use Dotenv \Loader \Loader ;
7
6
use Dotenv \Loader \LoaderInterface ;
8
7
use Dotenv \Parser \Parser ;
9
8
use Dotenv \Parser \ParserInterface ;
10
- use Dotenv \Repository \Adapter \ArrayAdapter ;
11
- use Dotenv \Repository \Adapter \PutenvAdapter ;
12
9
use Dotenv \Repository \RepositoryBuilder ;
13
10
use Dotenv \Repository \RepositoryInterface ;
14
11
use Dotenv \Store \StoreBuilder ;
15
12
use Dotenv \Store \StoreInterface ;
16
- use Dotenv \Store \StringStore ;
13
+ use Exception ;
14
+
15
+ class DotEnvVaultError extends Exception { }
17
16
18
17
class DotEnvVault extends Dotenv
19
18
{
20
19
private $ store ;
21
20
private $ parser ;
22
21
private $ loader ;
23
22
private $ repository ;
23
+ private $ dotenv_key ;
24
24
public function __construct (
25
25
StoreInterface $ store ,
26
26
ParserInterface $ parser ,
@@ -32,22 +32,100 @@ public function __construct(
32
32
$ this ->parser = $ parser ;
33
33
$ this ->loader = $ loader ;
34
34
$ this ->repository = $ repository ;
35
- // parent::__construct($store, $parser, $loader, $repository);
35
+ }
36
+
37
+ public function load ()
38
+ {
39
+ $ this ->dotenv_key = getenv ("DOTENV_KEY " );
40
+ if ($ this ->dotenv_key !== false ){
41
+
42
+ $ entries = $ this ->parser ->parse ($ this ->store ->read ());
43
+ $ this ->loader ->load ($ this ->repository , $ entries );
44
+
45
+ $ plaintext = $ this ->parse_vault ();
36
46
47
+ // parsing plaintext and loading to $_ENV
48
+ $ test_entries = $ this ->parser ->parse ($ plaintext );
49
+ $ this ->loader ->load ($ this ->repository , $ test_entries );
50
+ }
51
+ else {
52
+ $ entries = $ this ->parser ->parse ($ this ->store ->read ());
53
+
54
+ var_dump ($ entries [0 ]->getName ());
55
+ var_dump ($ entries [0 ]->getValue ());
56
+
57
+ return $ this ->loader ->load ($ this ->repository , $ entries );
58
+ }
37
59
}
38
60
39
- public function load_vault ()
61
+ public function parse_vault ()
40
62
{
41
- echo "\n====LOAD FUNCTION==== \n" ;
42
- $ entries = $ this ->parser ->parse ($ this ->store ->read ());
63
+ $ dotenv_keys = explode (', ' , $ this ->dotenv_key );
64
+ $ keys = array ();
65
+ foreach ($ dotenv_keys as $ key )
66
+ {
67
+ // parse DOTENV_KEY, format is a URI.
68
+ $ uri = parse_url (trim ($ key ));
69
+
70
+ // get encrypted key
71
+ $ pass = $ uri ['pass ' ];
72
+
73
+ // Get environment from query params.
74
+ parse_str ($ uri ['query ' ], $ params );
75
+ $ vault_environment = $ params ['environment ' ] or throw new DotEnvVaultError ('INVALID_DOTENV_KEY: Missing environment part. ' );
43
76
44
- return $ this ->loader ->load ($ this ->repository , $ entries );
77
+ # Getting ciphertext from correct environment in .env.vault
78
+ $ vault_environment = strtoupper ($ vault_environment );
79
+ $ environment_key = "DOTENV_VAULT_ {$ vault_environment }" ;
45
80
81
+ $ ciphertext = $ _ENV ["{$ environment_key }" ] or throw new DotEnvVaultError ("NOT_FOUND_DOTENV_ENVIRONMENT: Cannot locate environment {$ environment_key } in your .env.vault file. Run 'npx dotenv-vault build' to include it. " );
82
+
83
+ array_push ($ keys , array ('encrypted_key ' => $ pass , 'ciphertext ' => $ ciphertext ));
84
+ }
85
+ return $ this ->key_rotation ($ keys );
46
86
}
47
87
48
- public static function createImmutable ($ paths , $ names = null , bool $ shortCircuit = true , string $ fileEncoding = null )
88
+ private function key_rotation ($ keys ){
89
+ $ count = count ($ keys );
90
+ foreach ($ keys as $ index =>$ value ) {
91
+ $ decrypt = $ this ->decrypt ($ value ['ciphertext ' ], $ value ['encrypted_key ' ]);
92
+
93
+ if ($ decrypt == false && $ index + 1 >= $ count ){
94
+ throw new DotEnvVaultError ('INVALID_DOTENV_KEY: Key must be valid. ' );
95
+ }
96
+ elseif ($ decrypt == false ){
97
+ continue ;
98
+ }
99
+ else {
100
+ return $ decrypt ;
101
+ }
102
+ }
103
+ }
104
+
105
+ private function decrypt ($ data , $ secret )
49
106
{
50
-
107
+ $ secret = hex2bin (substr ($ secret , 4 , strlen ($ secret )));
108
+ $ data = base64_decode ($ data , true );
109
+ $ nonce = substr ($ data , 0 , 12 );
110
+ $ tag = substr ($ data , -16 );
111
+ $ ciphertext = substr ($ data , 12 , -16 );
112
+
113
+ try {
114
+ return openssl_decrypt (
115
+ $ ciphertext ,
116
+ 'aes-256-gcm ' ,
117
+ $ secret ,
118
+ OPENSSL_RAW_DATA ,
119
+ $ nonce ,
120
+ $ tag
121
+ );
122
+ } catch (Exception $ e ) {
123
+ return false ;
124
+ }
125
+ }
126
+
127
+ public static function createImmutable ($ paths , $ names = null , bool $ shortCircuit = true , string $ fileEncoding = null )
128
+ {
51
129
$ repository = RepositoryBuilder::createWithDefaultAdapters ()->immutable ()->make ();
52
130
53
131
return self ::create ($ repository , $ paths , $ names , $ shortCircuit , $ fileEncoding );
0 commit comments