Skip to content

Commit 068121a

Browse files
committed
Refactor secrets management
1 parent c437893 commit 068121a

File tree

7 files changed

+31
-31
lines changed

7 files changed

+31
-31
lines changed

docs/api.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,7 @@ run(
234234
?string $cwd = null,
235235
?array $env = null,
236236
#[\SensitiveParameter]
237-
?string $secret = null,
237+
?array $secrets = null,
238238
?bool $nothrow = false,
239239
?bool $forceOutput = false,
240240
?int $timeout = null,
@@ -249,7 +249,7 @@ Examples:
249249
```php
250250
run('echo hello world');
251251
run('cd {{deploy_path}} && git status');
252-
run('password %secret%', secret: getenv('CI_SECRET'));
252+
run('password %my_secret%', secrets: ['my_secret' => getenv('SECRET')]);
253253
run('curl medv.io', timeout: 5);
254254
```
255255

@@ -266,7 +266,7 @@ run("echo $path");
266266
| `$cwd` | `string` or `null` | Sets the process working directory. If not set {{working_path}} will be used. |
267267
| `$timeout` | `int` or `null` | Sets the process timeout (max. runtime). The timeout in seconds (default: 300 sec; see {{default_timeout}}, `null` to disable). |
268268
| `$idleTimeout` | `int` or `null` | Sets the process idle timeout (max. time since last output) in seconds. |
269-
| `$secret` | `string` or `null` | Placeholder `%secret%` can be used in command. Placeholder will be replaced with this value and will not appear in any logs. |
269+
| `$secrets` | `array` or `null` | Placeholder `%secret%` for sensitive information. |
270270
| `$env` | `array` or `null` | Array of environment variables: `run('echo $KEY', env: ['key' => 'value']);` |
271271
| `$forceOutput` | `bool` or `null` | Print command output in real-time. |
272272
| `$nothrow` | `bool` or `null` | Don't throw an exception of non-zero exit code. |

recipe/provision/databases.php

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,8 @@
3939
desc('Provision MySQL');
4040
task('provision:mysql', function () {
4141
run('apt-get install -y mysql-server', env: ['DEBIAN_FRONTEND' => 'noninteractive'], timeout: 900);
42-
run("mysql --user=\"root\" -e \"CREATE USER IF NOT EXISTS '{{db_user}}'@'0.0.0.0' IDENTIFIED BY '%secret%';\"", secret: get('db_password'));
43-
run("mysql --user=\"root\" -e \"CREATE USER IF NOT EXISTS '{{db_user}}'@'%' IDENTIFIED BY '%secret%';\"", secret: get('db_password'));
42+
run("mysql --user=\"root\" -e \"CREATE USER IF NOT EXISTS '{{db_user}}'@'0.0.0.0' IDENTIFIED BY '%db_password%';\"", secrets: ['db_password' => get('db_password')]);
43+
run("mysql --user=\"root\" -e \"CREATE USER IF NOT EXISTS '{{db_user}}'@'%' IDENTIFIED BY '%db_password%';\"", secrets: ['db_password' => get('db_password')]);
4444
run("mysql --user=\"root\" -e \"GRANT ALL PRIVILEGES ON *.* TO '{{db_user}}'@'0.0.0.0' WITH GRANT OPTION;\"");
4545
run("mysql --user=\"root\" -e \"GRANT ALL PRIVILEGES ON *.* TO '{{db_user}}'@'%' WITH GRANT OPTION;\"");
4646
run("mysql --user=\"root\" -e \"FLUSH PRIVILEGES;\"");
@@ -50,8 +50,8 @@
5050
desc('Provision MariaDB');
5151
task('provision:mariadb', function () {
5252
run('apt-get install -y mariadb-server', env: ['DEBIAN_FRONTEND' => 'noninteractive'], timeout: 900);
53-
run("mysql --user=\"root\" -e \"CREATE USER IF NOT EXISTS '{{db_user}}'@'0.0.0.0' IDENTIFIED BY '%secret%';\"", secret: get('db_password'));
54-
run("mysql --user=\"root\" -e \"CREATE USER IF NOT EXISTS '{{db_user}}'@'%' IDENTIFIED BY '%secret%';\"", secret: get('db_password'));
53+
run("mysql --user=\"root\" -e \"CREATE USER IF NOT EXISTS '{{db_user}}'@'0.0.0.0' IDENTIFIED BY '%db_password%';\"", secrets: ['db_password' => get('db_password')]);
54+
run("mysql --user=\"root\" -e \"CREATE USER IF NOT EXISTS '{{db_user}}'@'%' IDENTIFIED BY '%db_password%';\"", secrets: ['db_password' => get('db_password')]);
5555
run("mysql --user=\"root\" -e \"GRANT ALL PRIVILEGES ON *.* TO '{{db_user}}'@'0.0.0.0' WITH GRANT OPTION;\"");
5656
run("mysql --user=\"root\" -e \"GRANT ALL PRIVILEGES ON *.* TO '{{db_user}}'@'%' WITH GRANT OPTION;\"");
5757
run("mysql --user=\"root\" -e \"FLUSH PRIVILEGES;\"");
@@ -62,6 +62,6 @@
6262
task('provision:postgresql', function () {
6363
run('apt-get install -y postgresql postgresql-contrib', env: ['DEBIAN_FRONTEND' => 'noninteractive'], timeout: 900);
6464
run("sudo -u postgres psql <<< $'CREATE DATABASE {{db_name}};'");
65-
run("sudo -u postgres psql <<< $'CREATE USER {{db_user}} WITH ENCRYPTED PASSWORD \'%secret%\';'", secret: get('db_password'));
65+
run("sudo -u postgres psql <<< $'CREATE USER {{db_user}} WITH ENCRYPTED PASSWORD \'%db_password%\';'", secrets: ['db_password' => get('db_password')]);
6666
run("sudo -u postgres psql <<< $'GRANT ALL PRIVILEGES ON DATABASE {{db_name}} TO {{db_user}};'");
6767
});

recipe/provision/user.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,8 @@
3232
// Make color prompt.
3333
run("sed -i 's/#force_color_prompt=yes/force_color_prompt=yes/' /home/deployer/.bashrc");
3434

35-
$password = run("mkpasswd -m sha-512 '%secret%'", secret: get('sudo_password'));
36-
run("usermod --password '%secret%' deployer", secret: $password);
35+
$password = run("mkpasswd -m sha-512 '%password%'", secrets: ['password' => get('sudo_password')]);
36+
run("usermod --password '%password%' deployer", secrets: ['password' => $password]);
3737

3838
// Copy root public key to deployer user so user can login without password.
3939
run('cp /root/.ssh/authorized_keys /home/deployer/.ssh/authorized_keys');

src/ProcessRunner/ProcessRunner.php

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
use function Deployer\Support\deployer_root;
2323
use function Deployer\Support\env_stringify;
24+
use function Deployer\Support\replace_secrets;
2425

2526
class ProcessRunner
2627
{
@@ -43,12 +44,6 @@ public function run(Host $host, string $command, RunParams $params): string
4344
$terminalOutput($type, $buffer);
4445
};
4546

46-
if (!empty($params->secrets)) {
47-
foreach ($params->secrets as $key => $value) {
48-
$command = str_replace('%' . $key . '%', $value, $command);
49-
}
50-
}
51-
5247
if (!empty($params->env)) {
5348
$env = env_stringify($params->env);
5449
$command = "export $env; $command";
@@ -59,7 +54,7 @@ public function run(Host $host, string $command, RunParams $params): string
5954
}
6055

6156
$process = Process::fromShellCommandline($params->shell)
62-
->setInput($command)
57+
->setInput(replace_secrets($command, $params->secrets))
6358
->setTimeout($params->timeout)
6459
->setIdleTimeout($params->idleTimeout)
6560
->setWorkingDirectory($params->cwd ?? deployer_root());

src/Ssh/SshClient.php

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
use Symfony\Component\Process\Process;
2121

2222
use function Deployer\Support\env_stringify;
23+
use function Deployer\Support\replace_secrets;
2324

2425
class SshClient
2526
{
@@ -62,19 +63,13 @@ public function run(Host $host, string $command, RunParams $params): string
6263
$command = "export $env; $command";
6364
}
6465

65-
if (!empty($params->secrets)) {
66-
foreach ($params->secrets as $key => $value) {
67-
$command = str_replace('%' . $key . '%', strval($value), $command);
68-
}
69-
}
70-
7166
$this->pop->command($host, 'run', $command);
7267
$this->logger->log("[{$host->getAlias()}] run $command");
7368

7469

7570
$process = new Process($ssh);
7671
$process
77-
->setInput($command)
72+
->setInput(replace_secrets($command, $params->secrets))
7873
->setTimeout($params->timeout)
7974
->setIdleTimeout($params->idleTimeout);
8075

src/Support/helpers.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,16 @@ function ($key, $value) {
6565
));
6666
}
6767

68+
function replace_secrets(string $command, ?array $secrets): string
69+
{
70+
if (!empty($secrets)) {
71+
foreach ($secrets as $key => $value) {
72+
$command = str_replace('%' . $key . '%', strval($value), $command);
73+
}
74+
}
75+
return $command;
76+
}
77+
6878
function is_closure(mixed $var): bool
6979
{
7080
return is_object($var) && ($var instanceof \Closure);

src/functions.php

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -367,7 +367,7 @@ function within(string $path, callable $callback): mixed
367367
* ```php
368368
* run('echo hello world');
369369
* run('cd {{deploy_path}} && git status');
370-
* run('password %secret%', secret: getenv('CI_SECRET'));
370+
* run('password %my_secret%', secrets: ['my_secret' => getenv('SECRET')]);
371371
* run('curl medv.io', timeout: 5);
372372
* ```
373373
*
@@ -380,7 +380,7 @@ function within(string $path, callable $callback): mixed
380380
* @param string|null $cwd Sets the process working directory. If not set {{working_path}} will be used.
381381
* @param int|null $timeout Sets the process timeout (max. runtime). The timeout in seconds (default: 300 sec; see {{default_timeout}}, `null` to disable).
382382
* @param int|null $idleTimeout Sets the process idle timeout (max. time since last output) in seconds.
383-
* @param string|null $secret Placeholder `%secret%` can be used in command. Placeholder will be replaced with this value and will not appear in any logs.
383+
* @param array|null $secrets Placeholder `%secret%` for sensitive information.
384384
* @param array|null $env Array of environment variables: `run('echo $KEY', env: ['key' => 'value']);`
385385
* @param bool|null $forceOutput Print command output in real-time.
386386
* @param bool|null $nothrow Don't throw an exception of non-zero exit code.
@@ -394,7 +394,7 @@ function run(
394394
?string $cwd = null,
395395
?array $env = null,
396396
#[\SensitiveParameter]
397-
?string $secret = null,
397+
?array $secrets = null,
398398
?bool $nothrow = false,
399399
?bool $forceOutput = false,
400400
?int $timeout = null,
@@ -408,7 +408,7 @@ function run(
408408
timeout: $timeout ?? get('default_timeout', 300),
409409
idleTimeout: $idleTimeout,
410410
forceOutput: $forceOutput,
411-
secrets: empty($secret) ? null : ['secret' => $secret],
411+
secrets: $secrets,
412412
);
413413

414414
$dotenv = get('dotenv', false);
@@ -469,7 +469,7 @@ function run(
469469
* @param string|null $cwd Sets the process working directory. If not set {{working_path}} will be used.
470470
* @param int|null $timeout Sets the process timeout (max. runtime). The timeout in seconds (default: 300 sec, `null` to disable).
471471
* @param int|null $idleTimeout Sets the process idle timeout (max. time since last output) in seconds.
472-
* @param string|null $secret Placeholder `%secret%` can be used in command. Placeholder will be replaced with this value and will not appear in any logs.
472+
* @param array|null $secrets Placeholder `%secret%` for sensitive information.
473473
* @param array|null $env Array of environment variables: `runLocally('echo $KEY', env: ['key' => 'value']);`
474474
* @param bool|null $forceOutput Print command output in real-time.
475475
* @param bool|null $nothrow Don't throw an exception of non-zero exit code.
@@ -485,7 +485,7 @@ function runLocally(
485485
?int $timeout = null,
486486
?int $idleTimeout = null,
487487
#[\SensitiveParameter]
488-
?string $secret = null,
488+
?array $secrets = null,
489489
?array $env = null,
490490
?bool $forceOutput = false,
491491
?bool $nothrow = false,
@@ -499,7 +499,7 @@ function runLocally(
499499
timeout: $timeout,
500500
idleTimeout: $idleTimeout,
501501
forceOutput: $forceOutput,
502-
secrets: empty($secret) ? null : ['secret' => $secret],
502+
secrets: $secrets,
503503
);
504504

505505
$process = Deployer::get()->processRunner;

0 commit comments

Comments
 (0)