You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Rails ActiveStorage连接GCS遭遇OpenSSL::PKey::RSAError问题求助

Rails ActiveStorage 连接 GCS 报 OpenSSL::PKey::RSAError 问题排查

问题场景

在Heroku部署的Rails应用中,配置ActiveStorage连接Google Cloud Storage(GCS),config/storage.yml按服务账号JSON密钥文件填写,服务账号拥有Owner权限,已验证环境变量和配置正确,手动执行OpenSSL::PKey::RSA.new(ENV['GOOGLE_SERVICE_ACCOUNT_PRIVATE_KEY'])可成功,但上传文件时触发以下错误:

2025-04-09T23:29:11.090818+00:00 app[web.1]: E, [2025-04-09T23:29:11.090754 #11] ERROR -- : [eeabb3d7-6d82-45ea-813a-716c33a5e1df]
2025-04-09T23:29:11.090819+00:00 app[web.1]: [eeabb3d7-6d82-45ea-813a-716c33a5e1df] OpenSSL::PKey::RSAError (Neither PUB key nor PRIV key):
2025-04-09T23:29:11.090819+00:00 app[web.1]: [eeabb3d7-6d82-45ea-813a-716c33a5e1df]
2025-04-09T23:29:11.090820+00:00 app[web.1]: [eeabb3d7-6d82-45ea-813a-716c33a5e1df] vendor/ruby-3.4.2/lib/ruby/3.4.0/openssl/pkey.rb:356:in 'OpenSSL::PKey::RSA#initialize'
2025-04-09T23:29:11.090820+00:00 app[web.1]: [eeabb3d7-6d82-45ea-813a-716c33a5e1df] vendor/ruby-3.4.2/lib/ruby/3.4.0/openssl/pkey.rb:356:in 'Class#new'
2025-04-09T23:29:11.090821+00:00 app[web.1]: [eeabb3d7-6d82-45ea-813a-716c33a5e1df] vendor/ruby-3.4.2/lib/ruby/3.4.0/openssl/pkey.rb:356:in 'OpenSSL::PKey::RSA.new'
2025-04-09T23:29:11.090821+00:00 app[web.1]: [eeabb3d7-6d82-45ea-813a-716c33a5e1df] googleauth (1.14.0) lib/googleauth/service_account.rb:79:in 'Google::Auth::ServiceAccountCredentials.make_creds'
...

当前使用的config/storage.yml配置:

google:
  service: GCS
  project: my-project
  bucket: my-project-<%= Rails.env %>
  credentials:
    type: service_account
    project_id: my-project
    private_key_id: "<%= ENV['GOOGLE_SERVICE_ACCOUNT_PRIVATE_KEY_ID'] %>"
    private_key: "<%= ENV['GOOGLE_SERVICE_ACCOUNT_PRIVATE_KEY'] %>"
    client_email: "my-project-service-account@my-project.iam.gserviceaccount.com"
    client_id: "<redacted>"
    auth_uri: "https://accounts.google.com/o/oauth2/auth"
    token_uri: "https://oauth2.googleapis.com/token"
    auth_provider_x509_cert_url: "https://www.googleapis.com/oauth2/v1/certs"
    client_x509_cert_url: "https://www.googleapis.com/robot/v1/metadata/x509/my-project-service-account%40my-project.iam.gserviceaccount.com"
    universe_domain: "googleapis.com"

问题原因

问题出在storage.yml中对private_key的包裹方式:当用ERB读取环境变量并添加双引号时,会导致私钥中的换行符被转义或丢失,googleauth库解析时无法识别正确的RSA密钥格式。

虽然手动执行OpenSSL::PKey::RSA.new(ENV['GOOGLE_SERVICE_ACCOUNT_PRIVATE_KEY'])能成功,但ERB渲染后传递给googleauth的私钥已经被篡改(比如换行符变成了\n字符串而非实际换行)。

解决步骤

方案1:移除private_key的双引号

修改config/storage.yml中private_key的配置,去掉外层的双引号:

private_key: <%= ENV['GOOGLE_SERVICE_ACCOUNT_PRIVATE_KEY'] %>

这样ERB会直接输出环境变量中的原始私钥内容,保留正确的换行符格式。

方案2:使用完整JSON凭证(推荐)

避免在配置中拆分凭证字段,将服务账号JSON文件内容直接设置为Heroku环境变量GOOGLE_APPLICATION_CREDENTIALS_JSON,然后修改storage.yml:

google:
  service: GCS
  project: my-project
  bucket: my-project-<%= Rails.env %>
  credentials: <%= JSON.parse(ENV['GOOGLE_APPLICATION_CREDENTIALS_JSON']) %>

这种方式更简洁,也避免了单个字段的格式问题。

方案3:使用Heroku Google Cloud Buildpack

通过Heroku官方buildpack简化凭证配置:

  1. 添加buildpack:
heroku buildpacks:add https://github.com/heroku/heroku-buildpack-google-cloud.git
  1. 设置环境变量(将服务账号JSON内容直接传入):
heroku config:set GOOGLE_APPLICATION_CREDENTIALS=path/to/your-keyfile.json
  1. 简化storage.yml:
google:
  service: GCS
  project: my-project
  bucket: my-project-<%= Rails.env %>

此时ActiveStorage会自动通过默认凭证链加载权限。

验证方法

修改配置后重新部署,执行以下命令测试密钥解析:

heroku run rails c
> OpenSSL::PKey::RSA.new(Rails.application.config.active_storage.service_configurations[:google][:credentials][:private_key])

如果能成功初始化RSA密钥,说明配置正确,再测试文件上传功能。

内容的提问来源于stack exchange,提问作者aec

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 12:19:51