Skip to content

Commit

Permalink
Svidstore gcp region (#5718)
Browse files Browse the repository at this point in the history
* Add support for regions
* Add support for multiple regions
* Add that regions selector is immutable

Signed-off-by: Jens Hörnström <[email protected]>
  • Loading branch information
jenshornan authored Jan 20, 2025
1 parent 50d73f4 commit 05c641a
Show file tree
Hide file tree
Showing 3 changed files with 135 additions and 5 deletions.
1 change: 1 addition & 0 deletions doc/plugin_agent_svidstore_gcp_secretmanager.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,3 +71,4 @@ Selectors are used on `storable` entries to describe metadata that is needed by
| `gcp_secretmanager:projectid` | `gcp_secretmanager:projectid:some-project` | x | The Google Cloud project ID which the plugin will use Secret Manager |
| `gcp_secretmanager:role` | `gcp_secretmanager:role:roles/secretmanager.viewer` | - | The Google Cloud role id for IAM policy (serviceaccount required when set) |
| `gcp_secretmanager:serviceaccount` | `gcp_secretmanager:serviceaccount:[email protected]` | - | The Google Cloud Service account for IAM policy (role required when set) |
| `gcp_secretmanager:regions` | `gcp_secretmanager:regions:europe-north1,europe-west1` | - | List of Google Cloud Region to create the secret in, this is immutable and cannot be changed (Omit to use automatic region selection) |
48 changes: 43 additions & 5 deletions pkg/agent/plugin/svidstore/gcpsecretmanager/gcloud.go
Original file line number Diff line number Diff line change
Expand Up @@ -145,11 +145,7 @@ func (p *SecretManagerPlugin) PutX509SVID(ctx context.Context, req *svidstorev1.
Parent: opt.parent(),
SecretId: opt.name,
Secret: &secretmanagerpb.Secret{
Replication: &secretmanagerpb.Replication{
Replication: &secretmanagerpb.Replication_Automatic_{
Automatic: &secretmanagerpb.Replication_Automatic{},
},
},
Replication: opt.replication,
Labels: map[string]string{
"spire-svid": p.tdHash,
},
Expand Down Expand Up @@ -302,6 +298,7 @@ type secretOptions struct {
name string
roleName string
serviceAccount string
replication *secretmanagerpb.Replication
}

// parent gets parent in the format `projects/*`
Expand Down Expand Up @@ -346,11 +343,52 @@ func optionsFromSecretData(selectorData []string) (*secretOptions, error) {
return nil, status.Error(codes.InvalidArgument, "service account is required when role is set")
}

regions, ok := data["regions"]

var replica *secretmanagerpb.Replication

if !ok {
replica = &secretmanagerpb.Replication{
Replication: &secretmanagerpb.Replication_Automatic_{
Automatic: &secretmanagerpb.Replication_Automatic{},
},
}
} else {
regionsSlice := strings.Split(regions, ",")

var replicas []*secretmanagerpb.Replication_UserManaged_Replica

for _, region := range regionsSlice {
// Avoid adding empty strings as region
if region == "" {
continue
}
replica := &secretmanagerpb.Replication_UserManaged_Replica{
Location: region,
}

replicas = append(replicas, replica)
}

if len(replicas) == 0 {
return nil, status.Error(codes.InvalidArgument, "need to specify at least one region")
}

replica = &secretmanagerpb.Replication{
Replication: &secretmanagerpb.Replication_UserManaged_{
UserManaged: &secretmanagerpb.Replication_UserManaged{
Replicas: replicas,
},
},
}
}

return &secretOptions{
name: name,
projectID: projectID,
roleName: roleName,
serviceAccount: serviceAccount,
replication: replica,
}, nil
}

Expand Down
91 changes: 91 additions & 0 deletions pkg/agent/plugin/svidstore/gcpsecretmanager/gcloud_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -460,6 +460,97 @@ func TestPutX509SVID(t *testing.T) {
getSecretErr: status.Error(codes.NotFound, "secret not found"),
},
},
{
name: "Add payload and create regional secret",
req: &svidstore.X509SVID{
SVID: successReq.SVID,
Metadata: []string{
"name:secret1",
"projectid:project1",
"regions:europe-north1",
},
FederatedBundles: successReq.FederatedBundles,
},
expectCreateSecretReq: &secretmanagerpb.CreateSecretRequest{
Parent: "projects/project1",
SecretId: "secret1",
Secret: &secretmanagerpb.Secret{
Replication: &secretmanagerpb.Replication{
Replication: &secretmanagerpb.Replication_UserManaged_{
UserManaged: &secretmanagerpb.Replication_UserManaged{
Replicas: []*secretmanagerpb.Replication_UserManaged_Replica{
{
Location: "europe-north1",
},
},
},
},
},
Labels: map[string]string{
"spire-svid": tdHash,
},
},
},
expectGetSecretReq: &secretmanagerpb.GetSecretRequest{
Name: "projects/project1/secrets/secret1",
},
expectAddSecretVersionReq: &secretmanagerpb.AddSecretVersionRequest{
Parent: "projects/project1/secrets/secret1",
Payload: &secretmanagerpb.SecretPayload{
Data: payload,
},
},
clientConfig: &clientConfig{
getSecretErr: status.Error(codes.NotFound, "secret not found"),
},
},
{
name: "Add payload and create secret in multiple regions",
req: &svidstore.X509SVID{
SVID: successReq.SVID,
Metadata: []string{
"name:secret1",
"projectid:project1",
"regions:europe-north1,europe-west1",
},
FederatedBundles: successReq.FederatedBundles,
},
expectCreateSecretReq: &secretmanagerpb.CreateSecretRequest{
Parent: "projects/project1",
SecretId: "secret1",
Secret: &secretmanagerpb.Secret{
Replication: &secretmanagerpb.Replication{
Replication: &secretmanagerpb.Replication_UserManaged_{
UserManaged: &secretmanagerpb.Replication_UserManaged{
Replicas: []*secretmanagerpb.Replication_UserManaged_Replica{
{
Location: "europe-north1",
},
{
Location: "europe-west1",
},
},
},
},
},
Labels: map[string]string{
"spire-svid": tdHash,
},
},
},
expectGetSecretReq: &secretmanagerpb.GetSecretRequest{
Name: "projects/project1/secrets/secret1",
},
expectAddSecretVersionReq: &secretmanagerpb.AddSecretVersionRequest{
Parent: "projects/project1/secrets/secret1",
Payload: &secretmanagerpb.SecretPayload{
Data: payload,
},
},
clientConfig: &clientConfig{
getSecretErr: status.Error(codes.NotFound, "secret not found"),
},
},
{
name: "Add IAM policy when creating",
req: &svidstore.X509SVID{
Expand Down

0 comments on commit 05c641a

Please sign in to comment.