diff --git a/mmv1/third_party/terraform/services/resourcemanager/data_source_google_service_accounts.go b/mmv1/third_party/terraform/services/resourcemanager/data_source_google_service_accounts.go index e2f86163660d..375314e62075 100644 --- a/mmv1/third_party/terraform/services/resourcemanager/data_source_google_service_accounts.go +++ b/mmv1/third_party/terraform/services/resourcemanager/data_source_google_service_accounts.go @@ -5,11 +5,13 @@ package resourcemanager import ( "context" "fmt" + "regexp" "strings" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-provider-google/google/tpgresource" transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" + "github.com/hashicorp/terraform-provider-google/google/verify" "google.golang.org/api/iam/v1" ) @@ -17,10 +19,19 @@ func DataSourceGoogleServiceAccounts() *schema.Resource { return &schema.Resource{ Read: datasourceGoogleServiceAccountsRead, Schema: map[string]*schema.Schema{ + "prefix": { + Type: schema.TypeString, + Optional: true, + }, "project": { Type: schema.TypeString, Optional: true, }, + "regex": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: verify.ValidateRegexCompiles(), + }, "accounts": { Type: schema.TypeList, Computed: true, @@ -73,14 +84,34 @@ func datasourceGoogleServiceAccountsRead(d *schema.ResourceData, meta interface{ return fmt.Errorf("Error fetching project for service accounts: %s", err) } + prefix := d.Get("prefix").(string) + regexPattern := d.Get("regex").(string) + + var regex *regexp.Regexp + if regexPattern != "" { + regex, err = regexp.Compile(regexPattern) + if err != nil { + return fmt.Errorf("Invalid regex pattern: %s", err) + } + } + accounts := make([]map[string]interface{}, 0) request := config.NewIamClient(userAgent).Projects.ServiceAccounts.List("projects/" + project) err = request.Pages(context.Background(), func(accountList *iam.ListServiceAccountsResponse) error { for _, account := range accountList.Accounts { + accountId := strings.Split(account.Email, "@")[0] + + if prefix != "" && !strings.HasPrefix(accountId, prefix) { + continue + } + if regex != nil && !regex.MatchString(account.Email) { + continue + } + accounts = append(accounts, map[string]interface{}{ - "account_id": strings.Split(account.Email, "@")[0], + "account_id": accountId, "disabled": account.Disabled, "email": account.Email, "display_name": account.DisplayName, @@ -100,10 +131,17 @@ func datasourceGoogleServiceAccountsRead(d *schema.ResourceData, meta interface{ return fmt.Errorf("Error setting service accounts: %s", err) } - d.SetId(fmt.Sprintf( - "projects/%s", - project, - )) + idParts := []string{"projects", project} + + if prefix != "" { + idParts = append(idParts, "prefix/"+prefix) + } + if regexPattern != "" { + idParts = append(idParts, "regex/"+regexPattern) + } + + // Set the ID dynamically based on the provided attributes + d.SetId(strings.Join(idParts, "/")) return nil } diff --git a/mmv1/third_party/terraform/services/resourcemanager/data_source_google_service_accounts_test.go b/mmv1/third_party/terraform/services/resourcemanager/data_source_google_service_accounts_test.go index a5ee59409d87..3f9eac9add16 100644 --- a/mmv1/third_party/terraform/services/resourcemanager/data_source_google_service_accounts_test.go +++ b/mmv1/third_party/terraform/services/resourcemanager/data_source_google_service_accounts_test.go @@ -50,6 +50,18 @@ func TestAccDataSourceGoogleServiceAccounts_basic(t *testing.T) { resource.TestCheckResourceAttrSet("data.google_service_accounts.all", "accounts.1.member"), resource.TestCheckResourceAttrSet("data.google_service_accounts.all", "accounts.1.name"), resource.TestCheckResourceAttrSet("data.google_service_accounts.all", "accounts.1.unique_id"), + + // Check for prefix on account id + resource.TestCheckResourceAttr("data.google_service_accounts.with_prefix", "accounts.0.account_id", sa_1), + + // Check for regex on email + resource.TestCheckResourceAttr("data.google_service_accounts.with_regex", "accounts.0.email", fmt.Sprintf("%s@%s.iam.gserviceaccount.com", sa_1, project)), + + // Check if the account_id matches the prefix + resource.TestCheckResourceAttr("data.google_service_accounts.with_prefix_and_regex", "accounts.0.account_id", fmt.Sprintf(sa_1)), + + // Check if the email matches the regex + resource.TestCheckResourceAttr("data.google_service_accounts.with_prefix_and_regex", "accounts.0.email", fmt.Sprintf("%s@%s.iam.gserviceaccount.com", sa_1, project)), ), }, }, @@ -80,10 +92,26 @@ data "google_service_accounts" "all" { project = local.project_id depends_on = [ - google_service_account.sa_one, - google_service_account.sa_two, + google_service_account.sa_one, + google_service_account.sa_two, ] } + +data "google_service_accounts" "with_prefix" { + prefix = google_service_account.sa_one.account_id + project = local.project_id +} + +data "google_service_accounts" "with_regex" { + project = local.project_id + regex = ".*${google_service_account.sa_one.account_id}.*@.*\\.gserviceaccount\\.com" +} + +data "google_service_accounts" "with_prefix_and_regex" { + prefix = google_service_account.sa_one.account_id + project = local.project_id + regex = ".*${google_service_account.sa_one.account_id}.*@.*\\.gserviceaccount\\.com" +} `, context["project"].(string), context["sa_1"].(string), diff --git a/mmv1/third_party/terraform/verify/validation.go b/mmv1/third_party/terraform/verify/validation.go index b3a0152e7436..3967336fba03 100644 --- a/mmv1/third_party/terraform/verify/validation.go +++ b/mmv1/third_party/terraform/verify/validation.go @@ -438,3 +438,14 @@ func ValidateRegexp(re string) schema.SchemaValidateFunc { return } } + +func ValidateRegexCompiles() schema.SchemaValidateFunc { + return func(v interface{}, k string) (ws []string, errs []error) { + value := v.(string) + if _, err := regexp.Compile(value); err != nil { + errs = append(errs, fmt.Errorf( + "%s (%s) is not a valid regex pattern: %s", k, value, err)) + } + return + } +} diff --git a/mmv1/third_party/terraform/website/docs/d/service_accounts.html.markdown b/mmv1/third_party/terraform/website/docs/d/service_accounts.html.markdown index f263c41cd681..5b1b2ad2997c 100644 --- a/mmv1/third_party/terraform/website/docs/d/service_accounts.html.markdown +++ b/mmv1/third_party/terraform/website/docs/d/service_accounts.html.markdown @@ -13,7 +13,7 @@ and [API](https://cloud.google.com/iam/docs/reference/rest/v1/projects.serviceAc ## Example Usage -Example service accounts. +Get all service accounts from a project ```hcl data "google_service_accounts" "example" { @@ -21,12 +21,40 @@ data "google_service_accounts" "example" { } ``` +Get all service accounts that are prefixed with `"foo"` + +```hcl +data "google_service_accounts" "foo" { + prefix = "foo" +} +``` + +Get all service accounts that contain `"bar"` + +```hcl +data "google_service_accounts" "bar" { + regex = ".*bar.*" +} +``` + +Get all service accounts that are prefixed with `"foo"` and contain `"bar"` + +```hcl +data "google_service_accounts" "foo_bar" { + prefix = "foo" + regex = ".*bar.*" +} +``` + ## Argument Reference The following arguments are supported: +* `prefix` - (Optional) A prefix for filtering. It's applied with the `account_id`. + * `project` - (Optional) The ID of the project. If it is not provided, the provider project is used. +* `regex` - (Optional) A regular expression for filtering. It's applied with the `email`. Further information about the syntax can be found [here](https://github.com/google/re2/wiki/Syntax). ## Attributes Reference