关于 matlab-secure-credentials
此 MATLAB 技能指导开发者使用 MATLAB Vault 安全存储、读取并传递 API 密钥、令牌和密码。它还说明了 CI 等无交互场景下的凭据加载方式,以及避免将秘密写入代码或配置的做法。
主要功能
- 01使用 MATLAB Vault 管理凭据
- 02通过 setSecret 与 getSecret 存取
- 03使用 secretID 传递凭据引用
- 04通过 importSecrets 批量导入
- 05区分 Vault 与环境变量的适用场景
适用场景
- 01为 REST API 调用保存令牌
- 02为数据库或 SFTP 连接提供凭据
- 03在 CI 或定时任务中加载秘密
- 04重构代码以避免硬编码凭据
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ matlab/ matlab-agentic-toolkit --skill matlab-secure-credentials安装后在 Claude Code 中输入/matlab-secure-credentials确认已加载。
附带文件manifest.yaml
详细介绍
在 MATLAB 中安全处理凭据
使用内置于 MATLAB 的加密存储 MATLAB Vault 来管理 API 密钥、令牌、密码和口令,而不要将它们硬编码。本技能涵盖凭据本身——存储、检索凭据,并将其传入与任何需要身份验证的服务建立的连接。
适用场景
- 从 MATLAB 连接任何需要身份验证的服务或连接,例如 REST API、数据库、云存储、SFTP/FTP 服务、消息队列或其他服务。
- 任何处理 API 密钥、Bearer 令牌、密码或 SSH 密钥口令的代码。
- 编写需要凭据、且运行时没有用户在场的 CI、批处理或定时 MATLAB 程序。
- 重构凭据处理代码,或持久化包含机密信息的配置。
- 用户要求“不要把凭据放进代码”“不要提交机密信息”或“用安全的方式处理”。
不适用场景
- 编写连接、查询或传输逻辑,但不涉及凭据(例如公共 API 或本地文件);或在数据进入表或时间表后清理、转换或聚合数据——请使用相关的数据导入技能(例如
matlab-analyze-data、matlab-use-database)。 - 集成第三方机密管理器(HashiCorp Vault、AWS Secrets Manager、Azure Key Vault)——不在本技能范围内。
- 操作系统级或非 MATLAB 的密钥管理。
决策指南:选择哪种机制
根据凭据的提供方式选择机制,不要凭习惯决定。
| 情况 | 使用 | 不要使用 |
|---|---|---|
| 凭据需要存储并在不同会话中重复使用 | 调用一次 setSecret,然后在使用时调用 getSecret | 硬编码;自行编写配置文件 |
| 需要一次加载一组凭据(交互式设置,或非交互式、CI、无头或定时运行) | 使用 importSecrets 从机密文件填充保管库,然后调用 getSecret;或者在 CI 中,使用 getenv 获取运行器注入的值 | 在无头作业中调用 setSecret——它仅支持交互式使用 |
| 函数接受调用方提供的凭据 | secretID(指向机密的引用,而不是机密值) | 将机密值存入结构体字段或参数 |
凭据本身就是进程环境变量,例如 CI 注入的机密,或 AWS_ACCESS_KEY_ID 这类云 SDK 约定变量 | getenv——这是正确的做法 | 无故将其复制到保管库中 |
原则是不要硬编码机密信息,而不是“绝不使用环境变量”。如果机密已经是进程环境变量,getenv 就是正确的工具;对于你自己存储的凭据,默认应使用保管库。
工作流
- 确定机制,使用上面的决策指南。
- 存储或填充凭据:
- 单个机密,交互式操作:
setSecret("MyApiToken")(MATLAB 会提示输入值——切勿将值作为参数传入;该函数只接受名称)。 - 一次加载一组机密:
importSecrets("secrets.env")会在没有提示的情况下将名称和值加载到保管库中——交互式设置和非交互式/CI 场景都适用。
- 单个机密,交互式操作:
- 在使用时检索:调用
getSecret("MyApiToken");也可以将secretID("MyApiToken")传给接受该参数的 API(这些 API 会在调用时解析它,因此机密值不会存入变量)。 - 将其接入连接——请参阅下方的模式。
- 验证:在读取或移除机密前,使用
isSecret("MyApiToken")检查,并确认脚本、日志或任何已保存文件中都没有出现机密值。
主要功能
| 功能 | 用途 | 起始版本 |
|---|---|---|
setSecret | 向保管库添加密钥;交互式——提示输入值,只接受名称(更新时设置 Overwrite=true) | R2024a |
getSecret | 检索密钥值(返回字符串标量) | R2024a |
isSecret | 检查是否存在指定名称的密钥 | R2024a |
listSecrets | 列出已存储密钥的名称 | R2024a |
removeSecret | 从保管库删除密钥(没有 deleteSecret) | R2024a |
setSecretMetadata | 为密钥附加元数据(例如过期日期、所有者) | R2024a |
getSecretMetadata | 将密钥的元数据读取为字典 | R2024a |
secretID | 携带密钥名称而非其值的引用对象;weboptions 和 matlab.net.http.Credentials 均接受此对象 | R2025a |
importSecrets | 将文件中的一组密钥加载到保管库(不提示) | R2026a |
使用模式
存储一次,使用时检索
% One-time, at the MATLAB prompt (prompts for the value — do NOT type the secret in code):
setSecret("MyApiToken");
% In your script, read it only where needed:
token = getSecret("MyApiToken");
也可以记录过期时间等元数据,以便调用方在使用前检查密钥是否仍然有效:
% Metadata values are stored in a dictionary; wrap each value in a cell:
setSecretMetadata("MyApiToken", dictionary("Expires", {datetime(2026,12,31)}));
md = getSecretMetadata("MyApiToken");
expiry = md{"Expires"}; % {} indexing returns the stored value
if expiry < datetime("today")
error("MyApiToken expired on %s — rotate it with setSecret(...,Overwrite=true).", expiry);
end
token = getSecret("MyApiToken");
轮换或更新密钥
setSecret(...,Overwrite=true) 会替换现有密钥的值,这是轮换凭据的常用方法(例如定期替换,或在过期后替换为新值)。如果不设置 Overwrite,setSecret 在名称已存在时会报错。
setSecret("MyApiToken", Overwrite=true); % prompts for the new value
使用 bearer token 进行 REST 调用
从保管库获取 token,并将其设置在 Authorization 标头中。
token = getSecret("MyApiToken");
opts = weboptions( ...
HeaderFields = ["Authorization", "Bearer " + token], ...
ContentType = "json");
data = webread("https://api.example.com/v1/data", opts);
对于基本身份验证,将 secretID 传给 weboptions,这样值会在请求时解析,不会存放在变量中:
username = getenv("API_USER"); % REPLACE: your service-account user name
opts = weboptions(Username=username, Password=secretID("MyApiPassword"));
data = webread("https://api.example.com/v1/data", opts);
对于更底层的请求,matlab.net.http.Credentials 也接受 secretID:
cred = matlab.net.http.Credentials(Password=secretID("MyApiPassword"));
使用受密码保护密钥的 SFTP
keyFile = fullfile(userpath, "id_rsa"); % REPLACE: path to your private key
s = sftp("sftp.example.com", "reportuser", ...
PrivateKeyFile = keyFile, ...
PrivateKeyPassphrase = getSecret("SftpKeyPassphrase"));
c = onCleanup(@() close(s));
localPaths = mget(s, "/reports/nightly.csv", tempdir);
reportTable = readtable(localPaths{1});
使用密码验证而非密钥:
s = sftp("sftp.example.com", "reportuser", Password=getSecret("SftpPassword"));
数据库连接
将密码存储在保管库中,并在连接时读取。将主机、端口和数据库保存在代码中;将凭据单独保管。
conn = postgresql("svc-account", getSecret("PgPassword"), ...
Server = "db-prod-01", ...
PortNumber = 5432, ...
DatabaseName = "analytics");
c = onCleanup(@() close(conn));
tables = sqlfind(conn, "");
若要创建可复用、可共享的设置,可通过 Database Explorer 应用或 databaseConnectionOptions + saveAsDataSource 一次性保存数据源,然后按名称连接,并从保管库提供密码:
conn = postgresql("analyticsDataSource", "svc-account", getSecret("PgPassword"));
云存储(S3 / Azure Blob / GCS)
MATLAB 的文件 I/O(readtable、datastore 等)可直接读取云 URI,并从 SDK 的环境变量中获取凭据。使用显式密钥时,应从保管库获取密钥并设置 SDK 所需的环境变量;在云基础设施上运行时,优先使用附加的 IAM 角色,不设置任何内容。
% Explicit keys held in the vault -> set the SDK env vars from getSecret:
setenv("AWS_ACCESS_KEY_ID", getSecret("AwsAccessKeyId"));
setenv("AWS_SECRET_ACCESS_KEY", getSecret("AwsSecretAccessKey"));
setenv("AWS_DEFAULT_REGION", "us-east-1"); % REPLACE: bucket region
T = readtable("s3://acme-data/prices/latest.csv");
如果代码在 EC2 实例或启用了角色的环境中运行,则完全跳过密钥——IAM 角色会提供凭据,无需将密钥存放在任何地方。
将凭据传入函数
函数接受调用方提供的凭据时,应传递 secretID(引用),而不是密钥值。只有在调用 getSecret 时,引用才会解析为密钥。
构建配置——其中携带的是引用,而非 token:
config = struct( ...
"BaseUrl", "https://api.example.com/v1", ...
"Token", secretID("MyApiToken"));
在函数内部使用配置——仅在实际使用时解析密钥:
function report = fetchReport(config)
arguments
config (1,1) struct
end
token = getSecret(config.Token.Name);
opts = weboptions(HeaderFields = ["Authorization", "Bearer " + token]);
report = webread(config.BaseUrl + "/report", opts);
end
一次加载一组密钥(设置或 CI)
importSecrets 无需提示,即可将密钥文件中的名称和对应值加载到保管库——既适用于一次性的交互式设置,也适用于无头作业(此类作业无法使用仅限交互式的 setSecret)。
% secrets.env — a dotenv file (e.g. from CI secret storage), never committed — with lines like:
% MyApiToken=abc123
% PgPassword=hunter2
importSecrets("secrets.env"); % FileType="auto" (default) detects the dotenv format
token = getSecret("MyApiToken");
如果运行器直接将凭据作为进程环境变量注入,而非通过文件注入,则应使用 getenv("MY_TOKEN") 读取,无需使用保管库。
约定
- 始终:默认使用保险库(
setSecret/getSecret)存储凭据;调用removeSecret前先检查isSecret。 - 始终:一次加载多个密钥,或在任何无头/CI 环境中加载密钥时,使用
importSecrets,而不是setSecret。 - 切勿:在
.m文件中硬编码密钥,或将密钥值写入结构体或日志中 — 应改为传递secretID引用。 - 优先:如果 API 接受引用,则向
weboptions/Credentials传递secretID(...),而不是通过getSecret获取密钥值。 - 如果凭据确实是进程环境变量(CI 密钥、云 SDK 惯例),使用环境变量没有问题 — 不要矫枉过正地改用保险库,因为这样并无益处。
常见错误
| 错误 | 错误原因 | 正确做法 |
|---|---|---|
在 .m 文件中硬编码令牌/密码 | 会泄露到版本控制中;轮换困难 | 从保险库调用 getSecret("Name") |
| 将密钥值写入结构体字段或函数传递的参数中 | 明文密钥会离开保险库 | 传递 secretID 引用;使用时通过 getSecret 获取密钥 |
在 CI/批处理/计划任务中调用 setSecret | 仅支持交互式使用 — 无法输入值 | 使用 importSecrets 以非交互方式填充保险库 |
调用 deleteSecret | 不存在此函数 | 调用 removeSecret("Name"),并先检查 isSecret |
使用 save() 将凭据保存到 .mat 文件,再使用 load() 读回 | 会将明文密钥写入磁盘,且不加密,往往还会提交到版本控制中 | 将密钥值保存在保险库中;仅持久化 secretID 引用,并在使用时通过 getSecret 获取密钥 |
错误及其含义
| 错误标识符 | 发生时机 | 修复方法 |
|---|---|---|
MATLAB:authnz:secretapis:KeyAlreadyExists — "名为 'X' 的密钥已存在。将 'Overwrite' 设置为 true…" | 当 X 已在保险库中时调用 setSecret("X") | 要轮换/更新密钥,请调用 setSecret("X", Overwrite=true);否则请使用新名称 |
MATLAB:authnz:secretapis:SecretValueNotFound — "未找到密钥名称 'X' 对应的密钥值…" | 调用 getSecret("X"),但从未存储过 X(或名称拼写错误/大小写错误) | 先存储密钥(setSecret/importSecrets);读取前使用 isSecret("X") 检查。密钥名称区分大小写 |
MATLAB:authnz:secretapis:RemoveSecretFailed — "…未找到密钥名称 'X' 对应的密钥。" | 当 X 不在保险库中时调用 removeSecret("X") | 使用 if isSecret("X"); removeSecret("X"); end 检查 |
版权所有 2026 The MathWorks, Inc.