我有开源的spring boot应用程序,我想使用github action CI将其部署到Google Cloud App Engine。
我的问题是,如何在不对生产环境进行硬编码/公开属性(例如:
)的情况下完成所有操作?spring.cloud.gcp.sql.database-name
spring.cloud.gcp.sql.instance-connection-name
spring.datasource.password
spring.datasource.username
google-project-id
google cloud project service account key
我的想法是将所有这些值放入github机密,在CI中检索它们,使CI打包具有给定属性的应用程序并部署它。
我的问题是,我可以打包应用程序以替换application-prod.properties
中的给定属性吗?
我的另一个想法只是为给定属性定义环境变量,并让应用程序在运行时检索它们,但是我不确定应用引擎是否支持设置环境变量。
答案 0 :(得分:1)
我建议使用Secret Manager documentation将环境变量安全地存储在GAE中:
秘密是一个项目全局对象,其中包含 元数据和秘密版本。元数据可以包括复制 位置,标签和权限。秘密版本存储 实际的机密数据,例如API密钥或凭据。
Secret Manager conceptual overview
在这里您可以找到Java实现:
import com.google.cloud.secretmanager.v1beta1.AccessSecretVersionRequest;
import com.google.cloud.secretmanager.v1beta1.AccessSecretVersionResponse;
import com.google.cloud.secretmanager.v1beta1.AddSecretVersionRequest;
import com.google.cloud.secretmanager.v1beta1.CreateSecretRequest;
import com.google.cloud.secretmanager.v1beta1.ProjectName;
import com.google.cloud.secretmanager.v1beta1.Replication;
import com.google.cloud.secretmanager.v1beta1.Secret;
import com.google.cloud.secretmanager.v1beta1.SecretManagerServiceClient;
import com.google.cloud.secretmanager.v1beta1.SecretPayload;
import com.google.cloud.secretmanager.v1beta1.SecretVersion;
import com.google.protobuf.ByteString;
public class Quickstart {
public void quickstart() throws Exception {
// TODO(developer): Replace these variables before running the sample.
String projectId = "your-project-id";
String secretId = "your-secret-id";
quickstart(projectId, secretId);
}
public void quickstart(String projectId, String secretId) throws Exception {
// Initialize client that will be used to send requests. This client only needs to be created
// once, and can be reused for multiple requests. After completing all of your requests, call
// the "close" method on the client to safely clean up any remaining background resources.
try (SecretManagerServiceClient client = SecretManagerServiceClient.create()) {
// Build the parent name from the project.
ProjectName parent = ProjectName.of(projectId);
// Create the parent secret.
CreateSecretRequest createRequest =
CreateSecretRequest.newBuilder()
.setParent(parent.toString())
.setSecretId(secretId)
.setSecret(
Secret.newBuilder()
.setReplication(
Replication.newBuilder()
.setAutomatic(Replication.Automatic.newBuilder().build())
.build())
.build())
.build();
Secret secret = client.createSecret(createRequest);
// Add a secret version.
AddSecretVersionRequest addRequest =
AddSecretVersionRequest.newBuilder()
.setParent(secret.getName())
.setPayload(
SecretPayload.newBuilder()
.setData(ByteString.copyFromUtf8("hello world!"))
.build())
.build();
SecretVersion version = client.addSecretVersion(addRequest);
// Access the secret version.
AccessSecretVersionRequest accessRequest =
AccessSecretVersionRequest.newBuilder().setName(version.getName()).build();
AccessSecretVersionResponse response = client.accessSecretVersion(accessRequest);
// Print the secret payload.
//
// WARNING: Do not print the secret in a production environment - this
// snippet is showing how to access the secret material.
String payload = response.getPayload().getData().toStringUtf8();
System.out.printf("Plaintext: %s\n", payload);
}
}
}
答案 1 :(得分:0)
我最终得到了这个解决方案:
我不会将任何敏感属性提交给git。在CI中,在部署和打包应用程序之前,我用此动作https://github.com/christian-draeger/write-properties编写了这些敏感属性,并从GithubSecrets获取了给定的值。
ie:编写数据库密码属性的步骤:
- name: set database password
uses: christian-draeger/write-properties@1.0.0
with:
path: './src/main/resources/application-prod.properties'
property: 'spring.datasource.password'
value: ${{secrets.database_password}}
我喜欢这种设置,因为我要在打包之前设置这些属性-在目标环境中不会对其进行硬编码。
尽管有一个不便,但此操作似乎一次只能写入一个属性,因此必须为每个属性多次取消给定的步骤。