published on Thursday, Jun 25, 2026 by Pulumiverse
published on Thursday, Jun 25, 2026 by Pulumiverse
The Dynatrace GCP Principal resource provisions the Dynatrace GCP Principal (a service account) and exposes it via the principal attribute.
The principal must be granted the roles/iam.serviceAccountTokenCreator role on the GCP service account you want to impersonate, so that the dynatrace.GcpConnection resource can authenticate via service account impersonation.
This resource takes no input. The Dynatrace GCP Principal is a tenant-wide singleton that is provisioned by Dynatrace; this resource triggers its creation (if it does not exist yet), waits until it becomes available, and returns it. Creating the resource when a principal already exists is a no-op that simply reads the existing one.
updateanddeleteare no-ops. Because the principal is a Dynatrace-managed singleton,terraform destroyremoves the resource from state but leaves the principal in place.
This resource requires the API token scopes Read settings (
settings.read) and Write settings (settings.write), and the OAuth scopes Read settings (settings:objects:read) and Write settings (settings:objects:write).
Where the write permission applies is counter-intuitive. Provisioning is triggered by a call against the GCP connection schema (
builtin:hyperscaler-authentication.connections.gcp), so the Write settings permission must be granted on that schema. Write access on the GCP principal schema (builtin:hyperscaler-authentication.connections.gcp-dynatrace-principal) is not required at all — a caller who is denied write access on the principal schema can still provision the principal through this resource. This is a Dynatrace API characteristic and cannot be changed by the provider.
Dynatrace Documentation
- Settings API - https://www.dynatrace.com/support/help/dynatrace-api/environment-api/settings (schemaId:
builtin:hyperscaler-authentication.connections.gcp-dynatrace-principal)
Resource Example Usage
This example provisions the Dynatrace GCP Principal, grants it access to the impersonated service account, and wires it into a dynatrace.GcpConnection.
import * as pulumi from "@pulumi/pulumi";
import * as dynatrace from "@pulumiverse/dynatrace";
import * as gcp from "@pulumi/gcp";
const config = new pulumi.Config();
// The Google Cloud Platform project ID
const gcpProjectId = config.require("gcpProjectId");
// Create a Service Account in GCP
const impersonableServiceAccount = new gcp.serviceaccount.Account("impersonable_service_account", {
accountId: "test-service-account",
displayName: "Test Service Account",
});
// Provision the DT GCP Principal. This resource takes no input; it triggers creation of the
// Dynatrace-managed principal (a singleton) and exposes it via the `principal` attribute.
const principal = new dynatrace.GcpPrincipal("principal", {});
// Grant DT GCP Principal access to the service account
const wifBinding = new gcp.serviceaccount.IAMMember("wif_binding", {
serviceAccountId: impersonableServiceAccount.name,
member: pulumi.interpolate`serviceAccount:${principal.principal}`,
role: "roles/iam.serviceAccountTokenCreator",
});
// Create GCP connection
const myGcpConnection = new dynatrace.GcpConnection("my_gcp_connection", {
name: "My Gcp Connection",
type: "serviceAccountImpersonation",
serviceAccountImpersonation: {
serviceAccountId: impersonableServiceAccount.email,
consumers: ["SVC:com.dynatrace.da"],
},
}, {
dependsOn: [wifBinding],
});
import pulumi
import pulumi_gcp as gcp
import pulumiverse_dynatrace as dynatrace
config = pulumi.Config()
# The Google Cloud Platform project ID
gcp_project_id = config.require("gcpProjectId")
# Create a Service Account in GCP
impersonable_service_account = gcp.serviceaccount.Account("impersonable_service_account",
account_id="test-service-account",
display_name="Test Service Account")
# Provision the DT GCP Principal. This resource takes no input; it triggers creation of the
# Dynatrace-managed principal (a singleton) and exposes it via the `principal` attribute.
principal = dynatrace.GcpPrincipal("principal")
# Grant DT GCP Principal access to the service account
wif_binding = gcp.serviceaccount.IAMMember("wif_binding",
service_account_id=impersonable_service_account.name,
member=principal.principal.apply(lambda principal: f"serviceAccount:{principal}"),
role="roles/iam.serviceAccountTokenCreator")
# Create GCP connection
my_gcp_connection = dynatrace.GcpConnection("my_gcp_connection",
name="My Gcp Connection",
type="serviceAccountImpersonation",
service_account_impersonation={
"service_account_id": impersonable_service_account.email,
"consumers": ["SVC:com.dynatrace.da"],
},
opts = pulumi.ResourceOptions(depends_on=[wif_binding]))
package main
import (
"fmt"
"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/serviceaccount"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi/config"
"github.com/pulumiverse/pulumi-dynatrace/sdk/go/dynatrace"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
cfg := config.New(ctx, "")
// The Google Cloud Platform project ID
gcpProjectId := cfg.Require("gcpProjectId")
// Create a Service Account in GCP
impersonableServiceAccount, err := serviceaccount.NewAccount(ctx, "impersonable_service_account", &serviceaccount.AccountArgs{
AccountId: pulumi.String("test-service-account"),
DisplayName: pulumi.String("Test Service Account"),
})
if err != nil {
return err
}
// Provision the DT GCP Principal. This resource takes no input; it triggers creation of the
// Dynatrace-managed principal (a singleton) and exposes it via the `principal` attribute.
principal, err := dynatrace.NewGcpPrincipal(ctx, "principal", nil)
if err != nil {
return err
}
// Grant DT GCP Principal access to the service account
wifBinding, err := serviceaccount.NewIAMMember(ctx, "wif_binding", &serviceaccount.IAMMemberArgs{
ServiceAccountId: impersonableServiceAccount.Name,
Member: principal.Principal.ApplyT(func(principal string) (string, error) {
return fmt.Sprintf("serviceAccount:%v", principal), nil
}).(pulumi.StringOutput),
Role: pulumi.String("roles/iam.serviceAccountTokenCreator"),
})
if err != nil {
return err
}
// Create GCP connection
_, err = dynatrace.NewGcpConnection(ctx, "my_gcp_connection", &dynatrace.GcpConnectionArgs{
Name: pulumi.String("My Gcp Connection"),
Type: pulumi.String("serviceAccountImpersonation"),
ServiceAccountImpersonation: &dynatrace.GcpConnectionServiceAccountImpersonationArgs{
ServiceAccountId: impersonableServiceAccount.Email,
Consumers: pulumi.StringArray{
pulumi.String("SVC:com.dynatrace.da"),
},
},
}, pulumi.DependsOn([]pulumi.Resource{
wifBinding,
}))
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Dynatrace = Pulumiverse.Dynatrace;
using Gcp = Pulumi.Gcp;
return await Deployment.RunAsync(() =>
{
var config = new Config();
// The Google Cloud Platform project ID
var gcpProjectId = config.Require("gcpProjectId");
// Create a Service Account in GCP
var impersonableServiceAccount = new Gcp.ServiceAccount.Account("impersonable_service_account", new()
{
AccountId = "test-service-account",
DisplayName = "Test Service Account",
});
// Provision the DT GCP Principal. This resource takes no input; it triggers creation of the
// Dynatrace-managed principal (a singleton) and exposes it via the `principal` attribute.
var principal = new Dynatrace.GcpPrincipal("principal");
// Grant DT GCP Principal access to the service account
var wifBinding = new Gcp.ServiceAccount.IAMMember("wif_binding", new()
{
ServiceAccountId = impersonableServiceAccount.Name,
Member = principal.Principal.Apply(principal => $"serviceAccount:{principal}"),
Role = "roles/iam.serviceAccountTokenCreator",
});
// Create GCP connection
var myGcpConnection = new Dynatrace.GcpConnection("my_gcp_connection", new()
{
Name = "My Gcp Connection",
Type = "serviceAccountImpersonation",
ServiceAccountImpersonation = new Dynatrace.Inputs.GcpConnectionServiceAccountImpersonationArgs
{
ServiceAccountId = impersonableServiceAccount.Email,
Consumers = new[]
{
"SVC:com.dynatrace.da",
},
},
}, new CustomResourceOptions
{
DependsOn =
{
wifBinding,
},
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.serviceaccount.Account;
import com.pulumi.gcp.serviceaccount.AccountArgs;
import com.pulumi.dynatrace.GcpPrincipal;
import com.pulumi.gcp.serviceaccount.IAMMember;
import com.pulumi.gcp.serviceaccount.IAMMemberArgs;
import com.pulumi.dynatrace.GcpConnection;
import com.pulumi.dynatrace.GcpConnectionArgs;
import com.pulumi.dynatrace.inputs.GcpConnectionServiceAccountImpersonationArgs;
import com.pulumi.resources.CustomResourceOptions;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
final var config = ctx.config();
final var gcpProjectId = config.require("gcpProjectId");
// Create a Service Account in GCP
var impersonableServiceAccount = new Account("impersonableServiceAccount", AccountArgs.builder()
.accountId("test-service-account")
.displayName("Test Service Account")
.build());
// Provision the DT GCP Principal. This resource takes no input; it triggers creation of the
// Dynatrace-managed principal (a singleton) and exposes it via the `principal` attribute.
var principal = new GcpPrincipal("principal");
// Grant DT GCP Principal access to the service account
var wifBinding = new IAMMember("wifBinding", IAMMemberArgs.builder()
.serviceAccountId(impersonableServiceAccount.name())
.member(principal.principal().applyValue(_principal -> String.format("serviceAccount:%s", _principal)))
.role("roles/iam.serviceAccountTokenCreator")
.build());
// Create GCP connection
var myGcpConnection = new GcpConnection("myGcpConnection", GcpConnectionArgs.builder()
.name("My Gcp Connection")
.type("serviceAccountImpersonation")
.serviceAccountImpersonation(GcpConnectionServiceAccountImpersonationArgs.builder()
.serviceAccountId(impersonableServiceAccount.email())
.consumers("SVC:com.dynatrace.da")
.build())
.build(), CustomResourceOptions.builder()
.dependsOn(wifBinding)
.build());
}
}
configuration:
gcpProjectId:
type: string
resources:
# Create a Service Account in GCP
impersonableServiceAccount:
type: gcp:serviceaccount:Account
name: impersonable_service_account
properties:
accountId: test-service-account
displayName: Test Service Account
# Provision the DT GCP Principal. This resource takes no input; it triggers creation of the
# Dynatrace-managed principal (a singleton) and exposes it via the `principal` attribute.
principal:
type: dynatrace:GcpPrincipal
# Grant DT GCP Principal access to the service account
wifBinding:
type: gcp:serviceaccount:IAMMember
name: wif_binding
properties:
serviceAccountId: ${impersonableServiceAccount.name}
member: serviceAccount:${principal.principal}
role: roles/iam.serviceAccountTokenCreator
# Create GCP connection
myGcpConnection:
type: dynatrace:GcpConnection
name: my_gcp_connection
properties:
name: My Gcp Connection
type: serviceAccountImpersonation
serviceAccountImpersonation:
serviceAccountId: ${impersonableServiceAccount.email}
consumers:
- SVC:com.dynatrace.da
options:
dependsOn:
- ${wifBinding}
pulumi {
required_providers {
dynatrace = {
source = "pulumi/dynatrace"
}
gcp = {
source = "pulumi/gcp"
}
}
}
# Create a Service Account in GCP
resource "gcp_serviceaccount_account" "impersonable_service_account" {
account_id = "test-service-account"
display_name = "Test Service Account"
}
# Provision the DT GCP Principal. This resource takes no input; it triggers creation of the
# Dynatrace-managed principal (a singleton) and exposes it via the `principal` attribute.
resource "dynatrace_gcpprincipal" "principal" {
}
# Grant DT GCP Principal access to the service account
resource "gcp_serviceaccount_iammember" "wif_binding" {
service_account_id = gcp_serviceaccount_account.impersonable_service_account.name
member ="serviceAccount:${dynatrace_gcpprincipal.principal.principal}"
role = "roles/iam.serviceAccountTokenCreator"
}
# Create GCP connection
resource "dynatrace_gcpconnection" "my_gcp_connection" {
depends_on = [gcp_serviceaccount_iammember.wif_binding]
name = "My Gcp Connection"
type = "serviceAccountImpersonation"
service_account_impersonation = {
service_account_id = gcp_serviceaccount_account.impersonable_service_account.email
consumers = ["SVC:com.dynatrace.da"]
}
}
variable "gcpProjectId" {
type = string
description = "The Google Cloud Platform project ID"
}
Create GcpPrincipal Resource
Resources are created with functions called constructors. To learn more about declaring and configuring resources, see Resources.
Constructor syntax
new GcpPrincipal(name: string, args?: GcpPrincipalArgs, opts?: CustomResourceOptions);@overload
def GcpPrincipal(resource_name: str,
args: Optional[GcpPrincipalArgs] = None,
opts: Optional[ResourceOptions] = None)
@overload
def GcpPrincipal(resource_name: str,
opts: Optional[ResourceOptions] = None)func NewGcpPrincipal(ctx *Context, name string, args *GcpPrincipalArgs, opts ...ResourceOption) (*GcpPrincipal, error)public GcpPrincipal(string name, GcpPrincipalArgs? args = null, CustomResourceOptions? opts = null)
public GcpPrincipal(String name, GcpPrincipalArgs args)
public GcpPrincipal(String name, GcpPrincipalArgs args, CustomResourceOptions options)
type: dynatrace:GcpPrincipal
properties: # The arguments to resource properties.
options: # Bag of options to control resource's behavior.
resource "dynatrace_gcpprincipal" "name" {
# resource properties
}Parameters
- name string
- The unique name of the resource.
- args GcpPrincipalArgs
- The arguments to resource properties.
- opts CustomResourceOptions
- Bag of options to control resource's behavior.
- resource_name str
- The unique name of the resource.
- args GcpPrincipalArgs
- The arguments to resource properties.
- opts ResourceOptions
- Bag of options to control resource's behavior.
- ctx Context
- Context object for the current deployment.
- name string
- The unique name of the resource.
- args GcpPrincipalArgs
- The arguments to resource properties.
- opts ResourceOption
- Bag of options to control resource's behavior.
- name string
- The unique name of the resource.
- args GcpPrincipalArgs
- The arguments to resource properties.
- opts CustomResourceOptions
- Bag of options to control resource's behavior.
- name String
- The unique name of the resource.
- args GcpPrincipalArgs
- The arguments to resource properties.
- options CustomResourceOptions
- Bag of options to control resource's behavior.
Constructor example
The following reference example uses placeholder values for all input properties.
var gcpPrincipalResource = new Dynatrace.GcpPrincipal("gcpPrincipalResource");
example, err := dynatrace.NewGcpPrincipal(ctx, "gcpPrincipalResource", nil)
resource "dynatrace_gcpprincipal" "gcpPrincipalResource" {
}
var gcpPrincipalResource = new GcpPrincipal("gcpPrincipalResource");
gcp_principal_resource = dynatrace.GcpPrincipal("gcpPrincipalResource")
const gcpPrincipalResource = new dynatrace.GcpPrincipal("gcpPrincipalResource", {});
type: dynatrace:GcpPrincipal
properties: {}
GcpPrincipal Resource Properties
To learn more about resource properties and how to use them, see Inputs and Outputs in the Architecture and Concepts docs.
Inputs
In Python, inputs that are objects can be passed either as argument classes or as dictionary literals.
The GcpPrincipal resource accepts the following input properties:
Outputs
All input properties are implicitly available as output properties. Additionally, the GcpPrincipal resource produces the following output properties:
Look up Existing GcpPrincipal Resource
Get an existing GcpPrincipal resource’s state with the given name, ID, and optional extra properties used to qualify the lookup.
public static get(name: string, id: Input<ID>, state?: GcpPrincipalState, opts?: CustomResourceOptions): GcpPrincipal@staticmethod
def get(resource_name: str,
id: str,
opts: Optional[ResourceOptions] = None,
principal: Optional[str] = None) -> GcpPrincipalfunc GetGcpPrincipal(ctx *Context, name string, id IDInput, state *GcpPrincipalState, opts ...ResourceOption) (*GcpPrincipal, error)public static GcpPrincipal Get(string name, Input<string> id, GcpPrincipalState? state, CustomResourceOptions? opts = null)public static GcpPrincipal get(String name, Output<String> id, GcpPrincipalState state, CustomResourceOptions options)resources: _: type: dynatrace:GcpPrincipal get: id: ${id}import {
to = dynatrace_gcpprincipal.example
id = "${id}"
}
- name
- The unique name of the resulting resource.
- id
- The unique provider ID of the resource to lookup.
- state
- Any extra arguments used during the lookup.
- opts
- A bag of options that control this resource's behavior.
- resource_name
- The unique name of the resulting resource.
- id
- The unique provider ID of the resource to lookup.
- name
- The unique name of the resulting resource.
- id
- The unique provider ID of the resource to lookup.
- state
- Any extra arguments used during the lookup.
- opts
- A bag of options that control this resource's behavior.
- name
- The unique name of the resulting resource.
- id
- The unique provider ID of the resource to lookup.
- state
- Any extra arguments used during the lookup.
- opts
- A bag of options that control this resource's behavior.
- name
- The unique name of the resulting resource.
- id
- The unique provider ID of the resource to lookup.
- state
- Any extra arguments used during the lookup.
- opts
- A bag of options that control this resource's behavior.
- Principal string
- Dynatrace GCP Service Account
- Principal string
- Dynatrace GCP Service Account
- principal string
- Dynatrace GCP Service Account
- principal String
- Dynatrace GCP Service Account
- principal string
- Dynatrace GCP Service Account
- principal str
- Dynatrace GCP Service Account
- principal String
- Dynatrace GCP Service Account
Package Details
- Repository
- dynatrace pulumiverse/pulumi-dynatrace
- License
- Apache-2.0
- Notes
- This Pulumi package is based on the
dynatraceTerraform Provider.
published on Thursday, Jun 25, 2026 by Pulumiverse