R targets流水线中加密密钥被判定过期的问题及解决方法咨询
解决targets包中加密数据流水线的密钥过期与存储问题
问题核心
用targets构建流水线时,全局加载的cyphr密钥会被targets判定为“新对象”,导致所有依赖它的target每次都重跑;将密钥设为target时,又因targets不支持cyphr密钥对象的默认存储格式报错。
可行解决方案
方案1:在Target内部加载密钥,避免全局依赖追踪
直接在需要密钥的target代码块内加载密钥,让targets仅追踪密钥文件本身而非内存中的密钥对象,从根源避免过期误判。
修改后的_targets.R代码:
library(targets) library(tarchetypes) library(cyphr) library(here) redcap_data_path <- here("./data/redcap_data.RDS") key_dir <- here("./") list( tar_target(redcap_data, { # 仅在target运行时加载密钥,不暴露为全局对象 key <- cyphr::data_key(key_dir, path_user = key_dir) cyphr::decrypt(readRDS(redcap_data_path), key = key) }), tar_target(processed_data, some_function_to_process_data(redcap_data) ) ) |> tar_hook_outer(hook = encrypt_object(.x, key = cyphr::data_key(key_dir, path_user = key_dir))) |> tar_hook_inner(hook = decrypt_object(.x, key = cyphr::data_key(key_dir, path_user = key_dir)))
方案2:序列化密钥为RDS,指定Target存储格式
提前将密钥序列化保存为RDS文件,再在target中加载并指定format = "rds",解决targets无法存储cyphr密钥对象的问题。
- 先手动运行一次密钥序列化(仅需执行一次):
key <- cyphr::data_key(here("./"), path_user = here("./")) saveRDS(key, here("./key.rds"))
- 修改
_targets.R:
library(targets) library(tarchetypes) library(cyphr) library(here) redcap_data_path <- here("./data/redcap_data.RDS") list( tar_target(encryption_key, readRDS(here("./key.rds")), format = "rds" # 强制用RDS格式存储密钥对象 ), tar_target(redcap_data, cyphr::decrypt(readRDS(redcap_data_path), key = encryption_key), format = "rds" ), tar_target(processed_data, some_function_to_process_data(redcap_data) ) ) |> tar_hook_outer(hook = encrypt_object(.x, key = encryption_key)) |> tar_hook_inner(hook = decrypt_object(.x, key = encryption_key))
方案3:用环境变量传递密钥路径,简化钩子逻辑
将密钥路径存入环境变量,在钩子函数内部动态加载密钥,避免全局对象被targets追踪。
修改后的_targets.R代码:
library(targets) library(tarchetypes) library(cyphr) library(here) # 密钥路径存入环境变量,不生成全局密钥对象 Sys.setenv("ENCRYPTION_KEY_DIR" = here("./")) list( tar_target(redcap_data, readRDS(here("./data/redcap_data.RDS")) ), tar_target(processed_data, some_function_to_process_data(redcap_data) ) ) |> tar_hook_outer(hook = encrypt_object(.x, key = cyphr::data_key(Sys.getenv("ENCRYPTION_KEY_DIR"), path_user = Sys.getenv("ENCRYPTION_KEY_DIR")))) |> tar_hook_inner(hook = decrypt_object(.x, key = cyphr::data_key(Sys.getenv("ENCRYPTION_KEY_DIR"), path_user = Sys.getenv("ENCRYPTION_KEY_DIR"))))
内容的提问来源于stack exchange,提问作者fluxthis
相关产品推荐
相关产品推荐

