承接 atldays/laravel-secrets 相关项目开发

从需求分析到上线部署,全程专人跟进,保证项目质量与交付效率

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

atldays/laravel-secrets

Composer 安装命令:

composer require atldays/laravel-secrets

包简介

Load secrets from external providers and apply them to Laravel from a cached payload.

README 文档

README

Latest Version on Packagist Total Downloads CI License: MIT

atldays/laravel-secrets lets Laravel applications load sensitive configuration from external secret providers without turning every request into a network call.

It gives you the same developer experience as regular environment variables, but the values come from a provider, are cached inside Laravel, and are applied during boot only from that cached payload.

That means:

  • no provider API calls during normal requests
  • no custom runtime lookup layer in your application code
  • no need to replace your config with package-specific accessors
  • one explicit refresh step when secrets change

This package is designed for teams that want a safer and more operationally friendly alternative to keeping production secrets directly in .env files.

Why Use It

Most Laravel applications still depend on environment variables for things like:

  • APP_KEY
  • database credentials
  • queue and mail credentials
  • API tokens
  • service-to-service authentication

That works well in local development, but in production it often means:

  • secrets are copied into files on disk
  • rotation becomes manual and error-prone
  • infrastructure and application config drift apart
  • secret storage is handled outside a dedicated secret manager

Laravel Secrets keeps the familiar Laravel config flow, but moves secret storage to a provider and uses Laravel cache as the runtime handoff.

How It Works

The package uses a simple two-step flow:

  1. php artisan secrets:cache fetches secrets from every configured driver, or from one driver when you pass --driver.
  2. The resulting payload is stored in the configured Laravel cache store.
  3. During application boot, the package reads only that cached payload.
  4. The package writes the resolved values into Laravel's env repository and into the config paths defined in config_variables.

No provider calls are made while handling a normal HTTP request, queue job, or console command unless you explicitly ask for fresh values.

Supported Drivers

Currently supported drivers:

  • AWS Secrets Manager

More drivers are welcome. See CONTRIBUTING.md for the driver contribution workflow.

Installation

composer require atldays/laravel-secrets

Compatibility

Current support matrix:

  • PHP 8.1+
  • Laravel 10, 11, 12, and 13
  • AWS Secrets Manager as the first built-in driver

The package is tested in CI across the supported Laravel versions, and the AWS driver also includes live integration coverage.

Publish the config when you want to customize the package:

php artisan vendor:publish --tag=secrets-config

Quick Start

Minimal setup:

<?php

use Atldays\Secrets\Drivers\AwsSecretManager;

return [
    'apply_secrets' => env('SECRETS_APPLY', true),

    'cache' => [
        'store' => env('SECRETS_CACHE_STORE', 'file'),
        'key' => env('SECRETS_CACHE_KEY', 'laravel-secrets'),
        'ttl' => env('SECRETS_CACHE_TTL', 43200),
    ],

    'config_variables' => [
        'app.key' => 'APP_KEY',
        'database.connections.pgsql.host' => 'DB_HOST',
        'database.connections.pgsql.database' => 'DB_DATABASE',
        'database.connections.pgsql.username' => 'DB_USERNAME',
        'database.connections.pgsql.password' => 'DB_PASSWORD',
    ],

    'drivers' => [
        AwsSecretManager::class => [
            'region' => env('AWS_DEFAULT_REGION', 'us-east-1'),
            'version' => env('AWS_SECRETS_MANAGER_VERSION', '2017-10-17'),
            'key_strategy' => env('AWS_SECRETS_MANAGER_KEY_STRATEGY', 'basename'),
            'filter' => \Atldays\Secrets\Filters\AwsSecretManagerFilter::class,
            'filter_mode' => env('AWS_SECRETS_MANAGER_FILTER_MODE', 'or'),
            'filter_options' => [
                'tags' => env('AWS_SECRETS_MANAGER_TAGS'),
                'prefixes' => env('AWS_SECRETS_MANAGER_PREFIXES'),
                'names' => env('AWS_SECRETS_MANAGER_NAMES'),
            ],
        ],
    ],
];

Then refresh the cache:

php artisan secrets:cache

From that point on, the application boots with cached secrets applied to the env repository and to the config paths you mapped in config_variables.

Configuration

apply_secrets

Controls whether cached secrets should be applied during boot.

  • true: the package applies cached secrets
  • false: the package leaves the application config untouched

failure_mode

Controls what happens when applying cached secrets during boot fails.

Supported values:

  • throw
  • warn
  • ignore

This affects boot-time application of cached secrets, not the secrets:cache command itself. The cache command always reports its own execution errors directly.

cache

Controls where the secrets payload is stored after a successful refresh.

  • store: any Laravel cache store
  • key: the cache key that holds the payload
  • ttl: cache lifetime in minutes

The default ttl is 43200, which equals 30 days.

config_variables

This is the explicit bridge between your secret payload and Laravel config.

Laravel resolves many env() calls before package boot, so the package cannot rely on env mutation alone. That is why config_variables exists.

Example:

'config_variables' => [
    'app.key' => 'APP_KEY',
    'database.connections.pgsql.password' => 'DB_PASSWORD',
]

AWS Secret Manager

Driver Configuration

The AWS driver supports:

  • region
  • version
  • key_strategy
  • list_max_results
  • filter
  • filter_mode
  • filter_options

Example:

use Atldays\Secrets\Drivers\AwsSecretManager;
use Atldays\Secrets\Filters\AwsSecretManagerFilter;

'drivers' => [
    AwsSecretManager::class => [
        'region' => env('AWS_DEFAULT_REGION', 'eu-central-1'),
        'version' => env('AWS_SECRETS_MANAGER_VERSION', '2017-10-17'),
        'key_strategy' => env('AWS_SECRETS_MANAGER_KEY_STRATEGY', 'basename'),
        'list_max_results' => env('AWS_SECRETS_MANAGER_LIST_MAX_RESULTS'),
        'filter' => AwsSecretManagerFilter::class,
        'filter_mode' => env('AWS_SECRETS_MANAGER_FILTER_MODE', 'or'),
        'filter_options' => [
            'tags' => env('AWS_SECRETS_MANAGER_TAGS'),
            'prefixes' => env('AWS_SECRETS_MANAGER_PREFIXES'),
            'names' => env('AWS_SECRETS_MANAGER_NAMES'),
        ],
    ],
],

AWS Authentication Best Practices

If your application runs on AWS infrastructure, prefer IAM-based runtime credentials instead of hardcoding access keys.

Recommended:

  • EC2: attach an IAM role to the instance profile
  • ECS: use a task role
  • EKS: use IAM Roles for Service Accounts
  • Lambda: use the function execution role

This lets the AWS SDK resolve credentials automatically without storing long-lived secrets in your application environment.

If your application runs outside AWS, use standard AWS SDK credentials such as:

  • AWS_ACCESS_KEY_ID
  • AWS_SECRET_ACCESS_KEY
  • AWS_SESSION_TOKEN
  • shared credentials profiles

That works fine, but should usually be treated as the less preferred option compared to IAM-based runtime identity on AWS-managed infrastructure.

Pagination

The AWS driver supports provider pagination through NextToken.

If you set list_max_results, the package passes it to AWS as MaxResults and keeps requesting pages until the full result set is collected.

This is useful when you want explicit control over page size or when you want to verify pagination behavior in integration tests.

Secret Shapes

The AWS driver supports multiple secret shapes.

JSON object

If the secret value is a JSON object, every key becomes a secret entry.

Example:

{
  "DB_PASSWORD": "secret",
  "DB_PORT": 5432
}

Result:

[
    'DB_PASSWORD' => 'secret',
    'DB_PORT' => '5432',
]

name / value wrapper

If the secret value looks like this:

{
  "name": "APP_KEY",
  "value": "base64:..."
}

the package produces exactly one secret entry:

[
    'APP_KEY' => 'base64:...',
]

Plain text

If the secret is plain text, the final key is derived from the secret name using key_strategy.

Given:

Name: /project/production/APP_KEY
Value: base64:...

With basename:

[
    'APP_KEY' => 'base64:...',
]

With name:

[
    '/project/production/APP_KEY' => 'base64:...',
]

SecretBinary

SecretBinary is supported. When AWS returns binary data in base64 form, the driver decodes it before building the final payload.

Filtering

Filtering is built around a driver-agnostic contract, so the same model can be reused by future drivers.

Built-in AWS Filter

The package ships with Atldays\Secrets\Filters\AwsSecretManagerFilter.

Its filter_options support:

  • tags
  • prefixes
  • names

Example:

'filter' => \Atldays\Secrets\Filters\AwsSecretManagerFilter::class,
'filter_mode' => 'or',
'filter_options' => [
    'tags' => 'application:api|admin,environment:production',
    'prefixes' => '/project/prod/,/project/shared/',
    'names' => '/project/exact/APP_KEY,/project/exact/DB_PASSWORD',
],

The built-in AWS filter treats tags, prefixes, and names as OR conditions inside the filter itself.

If all filter_options are empty, all available AWS secrets match.

Custom Filters

You can replace the built-in filter with your own class, or pass multiple filter classes.

Each filter must implement Atldays\Secrets\Contracts\SecretFilter.

Example:

namespace App\Secrets\Filters;

use Atldays\Secrets\Contracts\SecretFilter;
use Atldays\Secrets\Contracts\SecretReferenceContract;

class ProductionProjectFilter implements SecretFilter
{
    public function matches(SecretReferenceContract $secret): bool
    {
        return $secret->hasTag('environment', 'production')
            && $secret->nameStartsWith('/project/prod/');
    }
}

Use it like this:

'filter' => App\Secrets\Filters\ProductionProjectFilter::class,

Or combine multiple filters:

'filter' => [
    App\Secrets\Filters\EnvironmentFilter::class,
    App\Secrets\Filters\PrefixFilter::class,
],
'filter_mode' => 'and',

Supported filter_mode values:

  • or
  • and

Meaning:

  • or: at least one filter class must match
  • and: every filter class must match

Secret References

Filters receive a SecretReferenceContract, not the final secret value.

That is intentional.

It allows filters to decide whether a secret should be fetched without exposing the secret payload itself during the listing stage.

The current reference object includes:

  • driver name
  • secret name
  • provider identifier
  • tags
  • metadata returned by the provider's listing API

For AWS, metadata contains the raw ListSecrets entry, such as:

  • Name
  • ARN
  • Tags
  • KmsKeyId
  • creation and rotation metadata

It does not contain:

  • SecretString
  • SecretBinary
  • resolved secret values

Useful helper methods on the reference include:

  • tag()
  • hasTag()
  • hasTagIn()
  • hasName()
  • hasNameIn()
  • nameStartsWith()
  • nameEndsWith()
  • nameContains()
  • hasIdentifier()
  • hasMetadata()
  • meta()

Public API

Facade

The package exposes the Secrets facade as the main public entry point.

use Atldays\Secrets\Facades\Secrets;

$freshSecrets = Secrets::fetch(); // Read fresh secrets directly from the provider.
$freshAwsSecrets = Secrets::fetch(\Atldays\Secrets\Drivers\AwsSecretManager::class); // Read fresh secrets from one driver.

$payload = Secrets::cache(); // Fetch fresh secrets and store the payload in the configured cache.
$awsPayload = Secrets::cache(\Atldays\Secrets\Drivers\AwsSecretManager::class); // Refresh the cache for one driver only.

$cachedValues = Secrets::values(); // Read only the resolved KEY => VALUE pairs from the cached payload.
$storedPayload = Secrets::stored(); // Read the full cached payload DTO, including drivers and secrets.

$appliedCount = Secrets::apply(); // Apply cached secrets to Laravel env/config and get the number of applied secrets.
$cleared = Secrets::clear(); // Remove the cached payload from the configured cache store.

Commands

secrets:cache

Fetches fresh secrets from the provider and stores them in the configured cache.

Use it when:

  • you deploy a new release
  • secrets were rotated in the provider
  • you want to refresh the cached payload before the application starts serving traffic

Optional flags:

  • --driver=... Refresh secrets from one specific driver only

Example:

php artisan secrets:cache
php artisan secrets:cache --driver="App\\Secrets\\CustomDriver"

secrets:clear

Removes the cached payload from the configured cache store.

Use it when:

  • you want to force a completely fresh refresh cycle
  • you are debugging stale secret payloads
  • you want to invalidate the current cache before a deployment step

Example:

php artisan secrets:clear

secrets:list

Reads secrets from the configured cache and lists the resolved secret names.

By default, values are masked.

Use it when:

  • you want to confirm that the cache was successfully warmed
  • you want to inspect which keys are currently available
  • you want a safe operator-friendly validation step during deployment

Optional flags:

  • --fresh Read directly from the provider instead of the cached payload
  • --driver=... Limit fresh reads to one driver
  • --reveal Show full values instead of masked values
  • --force Required in production when revealing secret values

Examples:

php artisan secrets:list
php artisan secrets:list --fresh
php artisan secrets:list --reveal

secrets:get

Reads one named secret from the configured cache.

Use it when:

  • you want to verify one specific secret
  • you want to compare cached values with provider values
  • you need one shell-friendly value during CI or deployment scripts

Optional flags:

  • --fresh Read directly from the provider instead of the cached payload
  • --driver=... Limit fresh reads to one driver
  • --reveal Show the full value
  • --raw Print only the value, without extra console formatting
  • --force Required in production when revealing values

Examples:

php artisan secrets:get APP_KEY
php artisan secrets:get APP_KEY --fresh
php artisan secrets:get APP_KEY --reveal
php artisan secrets:get APP_KEY --raw

Deployment Example

A typical deployment flow looks like this:

php artisan secrets:clear
php artisan secrets:cache
php artisan config:cache
php artisan route:cache
php artisan event:cache

This ensures the provider API is contacted during the deployment phase, not during normal request handling.

When APP_ENV=production, revealing values requires --force.

Security Notes

  • The package does not fetch provider secrets during normal request handling.
  • Filters operate on secret references, not on secret values.
  • Real values are fetched only after a secret has matched the configured filters.
  • Cached secrets should be stored in a cache backend appropriate for your environment.
  • config_variables should be treated as an explicit allowlist of Laravel config values that may be overwritten by secrets.

Testing Status

The package currently includes:

  • local adapter-level tests
  • manager and command tests
  • DTO and helper-method tests
  • live AWS integration tests for:
    • prefixes
    • names
    • tags
    • custom filters
    • SecretBinary
    • KMS-encrypted secrets
    • forced pagination

atldays/laravel-secrets 适用场景与选型建议

atldays/laravel-secrets 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 0 次下载、GitHub Stars 达 0, 最近一次更新时间为 2026 年 04 月 23 日, 在 PHP 生态内属于活跃度较高的组件。

它主要适用于以下技术方向: 「config」 「aws」 「laravel」 「environment」 「credentials」 「secrets」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。

我们在过去多个企业项目中使用过 atldays/laravel-secrets 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。

围绕 atldays/laravel-secrets 我们能提供哪些服务?
定制开发 / 二次开发

基于 atldays/laravel-secrets 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。

BUG 修复 & 性能优化

线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。

项目外包 & 长期维护

承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。

yvsm@zunyunkeji.com QQ:316430983 微信:yvsm316 西安尊云信息科技 · 专注 PHP / Go / 分布式系统研发

统计信息

  • 总下载量: 0
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 0
  • 点击次数: 44
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 0
  • Watchers: 0
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2026-04-23