The gcp:projects/apiKey:ApiKey resource, part of the Pulumi GCP provider, provisions Google Cloud API keys with platform-specific restrictions and service targeting. This guide focuses on three capabilities: platform-specific restrictions (Android, iOS, browser, server), API service and method targeting, and service account binding for auth-enabled keys.
API keys belong to GCP projects. Service account binding requires an existing service account. The examples are intentionally small. Combine them with your own project configuration and IAM policies.
Create an unrestricted API key
Development workflows often start with an unrestricted key to verify service connectivity before applying production restrictions.
import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";
const primary = new gcp.projects.ApiKey("primary", {
name: "key",
displayName: "sample-key",
});
import pulumi
import pulumi_gcp as gcp
primary = gcp.projects.ApiKey("primary",
name="key",
display_name="sample-key")
package main
import (
"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/projects"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := projects.NewApiKey(ctx, "primary", &projects.ApiKeyArgs{
Name: pulumi.String("key"),
DisplayName: pulumi.String("sample-key"),
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Gcp = Pulumi.Gcp;
return await Deployment.RunAsync(() =>
{
var primary = new Gcp.Projects.ApiKey("primary", new()
{
Name = "key",
DisplayName = "sample-key",
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.projects.ApiKey;
import com.pulumi.gcp.projects.ApiKeyArgs;
import java.util.List;
import java.util.ArrayList;
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) {
var primary = new ApiKey("primary", ApiKeyArgs.builder()
.name("key")
.displayName("sample-key")
.build());
}
}
resources:
primary:
type: gcp:projects:ApiKey
properties:
name: key
displayName: sample-key
The name property sets a unique identifier within the project (lowercase, RFC-1034 compliant). The displayName provides a human-readable label. Without restrictions, the key works with any Google API from any source.
Restrict API key to browser referrers
Web applications need to protect API keys while allowing legitimate browser requests from known domains.
import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";
const primary = new gcp.projects.ApiKey("primary", {
name: "key",
displayName: "sample-key",
restrictions: {
apiTargets: [{
service: "translate.googleapis.com",
methods: ["GET*"],
}],
browserKeyRestrictions: {
allowedReferrers: [".*"],
},
},
});
import pulumi
import pulumi_gcp as gcp
primary = gcp.projects.ApiKey("primary",
name="key",
display_name="sample-key",
restrictions={
"api_targets": [{
"service": "translate.googleapis.com",
"methods": ["GET*"],
}],
"browser_key_restrictions": {
"allowed_referrers": [".*"],
},
})
package main
import (
"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/projects"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := projects.NewApiKey(ctx, "primary", &projects.ApiKeyArgs{
Name: pulumi.String("key"),
DisplayName: pulumi.String("sample-key"),
Restrictions: &projects.ApiKeyRestrictionsArgs{
ApiTargets: projects.ApiKeyRestrictionsApiTargetArray{
&projects.ApiKeyRestrictionsApiTargetArgs{
Service: pulumi.String("translate.googleapis.com"),
Methods: pulumi.StringArray{
pulumi.String("GET*"),
},
},
},
BrowserKeyRestrictions: &projects.ApiKeyRestrictionsBrowserKeyRestrictionsArgs{
AllowedReferrers: pulumi.StringArray{
pulumi.String(".*"),
},
},
},
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Gcp = Pulumi.Gcp;
return await Deployment.RunAsync(() =>
{
var primary = new Gcp.Projects.ApiKey("primary", new()
{
Name = "key",
DisplayName = "sample-key",
Restrictions = new Gcp.Projects.Inputs.ApiKeyRestrictionsArgs
{
ApiTargets = new[]
{
new Gcp.Projects.Inputs.ApiKeyRestrictionsApiTargetArgs
{
Service = "translate.googleapis.com",
Methods = new[]
{
"GET*",
},
},
},
BrowserKeyRestrictions = new Gcp.Projects.Inputs.ApiKeyRestrictionsBrowserKeyRestrictionsArgs
{
AllowedReferrers = new[]
{
".*",
},
},
},
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.projects.ApiKey;
import com.pulumi.gcp.projects.ApiKeyArgs;
import com.pulumi.gcp.projects.inputs.ApiKeyRestrictionsArgs;
import com.pulumi.gcp.projects.inputs.ApiKeyRestrictionsBrowserKeyRestrictionsArgs;
import java.util.List;
import java.util.ArrayList;
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) {
var primary = new ApiKey("primary", ApiKeyArgs.builder()
.name("key")
.displayName("sample-key")
.restrictions(ApiKeyRestrictionsArgs.builder()
.apiTargets(ApiKeyRestrictionsApiTargetArgs.builder()
.service("translate.googleapis.com")
.methods("GET*")
.build())
.browserKeyRestrictions(ApiKeyRestrictionsBrowserKeyRestrictionsArgs.builder()
.allowedReferrers(".*")
.build())
.build())
.build());
}
}
resources:
primary:
type: gcp:projects:ApiKey
properties:
name: key
displayName: sample-key
restrictions:
apiTargets:
- service: translate.googleapis.com
methods:
- GET*
browserKeyRestrictions:
allowedReferrers:
- .*
The browserKeyRestrictions property limits usage to requests with matching HTTP referrer headers. The allowedReferrers array accepts regex patterns; .* allows all referrers. The apiTargets array restricts which services and methods the key can access. Here, only GET methods on the Translation API are permitted.
Restrict API key to Android applications
Mobile applications embed API keys in client code, requiring package name and certificate fingerprint validation.
import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";
const primary = new gcp.projects.ApiKey("primary", {
name: "key",
displayName: "sample-key",
restrictions: {
androidKeyRestrictions: {
allowedApplications: [{
packageName: "com.example.app123",
sha1Fingerprint: "1699466a142d4682a5f91b50fdf400f2358e2b0b",
}],
},
apiTargets: [{
service: "translate.googleapis.com",
methods: ["GET*"],
}],
},
});
import pulumi
import pulumi_gcp as gcp
primary = gcp.projects.ApiKey("primary",
name="key",
display_name="sample-key",
restrictions={
"android_key_restrictions": {
"allowed_applications": [{
"package_name": "com.example.app123",
"sha1_fingerprint": "1699466a142d4682a5f91b50fdf400f2358e2b0b",
}],
},
"api_targets": [{
"service": "translate.googleapis.com",
"methods": ["GET*"],
}],
})
package main
import (
"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/projects"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := projects.NewApiKey(ctx, "primary", &projects.ApiKeyArgs{
Name: pulumi.String("key"),
DisplayName: pulumi.String("sample-key"),
Restrictions: &projects.ApiKeyRestrictionsArgs{
AndroidKeyRestrictions: &projects.ApiKeyRestrictionsAndroidKeyRestrictionsArgs{
AllowedApplications: projects.ApiKeyRestrictionsAndroidKeyRestrictionsAllowedApplicationArray{
&projects.ApiKeyRestrictionsAndroidKeyRestrictionsAllowedApplicationArgs{
PackageName: pulumi.String("com.example.app123"),
Sha1Fingerprint: pulumi.String("1699466a142d4682a5f91b50fdf400f2358e2b0b"),
},
},
},
ApiTargets: projects.ApiKeyRestrictionsApiTargetArray{
&projects.ApiKeyRestrictionsApiTargetArgs{
Service: pulumi.String("translate.googleapis.com"),
Methods: pulumi.StringArray{
pulumi.String("GET*"),
},
},
},
},
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Gcp = Pulumi.Gcp;
return await Deployment.RunAsync(() =>
{
var primary = new Gcp.Projects.ApiKey("primary", new()
{
Name = "key",
DisplayName = "sample-key",
Restrictions = new Gcp.Projects.Inputs.ApiKeyRestrictionsArgs
{
AndroidKeyRestrictions = new Gcp.Projects.Inputs.ApiKeyRestrictionsAndroidKeyRestrictionsArgs
{
AllowedApplications = new[]
{
new Gcp.Projects.Inputs.ApiKeyRestrictionsAndroidKeyRestrictionsAllowedApplicationArgs
{
PackageName = "com.example.app123",
Sha1Fingerprint = "1699466a142d4682a5f91b50fdf400f2358e2b0b",
},
},
},
ApiTargets = new[]
{
new Gcp.Projects.Inputs.ApiKeyRestrictionsApiTargetArgs
{
Service = "translate.googleapis.com",
Methods = new[]
{
"GET*",
},
},
},
},
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.projects.ApiKey;
import com.pulumi.gcp.projects.ApiKeyArgs;
import com.pulumi.gcp.projects.inputs.ApiKeyRestrictionsArgs;
import com.pulumi.gcp.projects.inputs.ApiKeyRestrictionsAndroidKeyRestrictionsArgs;
import java.util.List;
import java.util.ArrayList;
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) {
var primary = new ApiKey("primary", ApiKeyArgs.builder()
.name("key")
.displayName("sample-key")
.restrictions(ApiKeyRestrictionsArgs.builder()
.androidKeyRestrictions(ApiKeyRestrictionsAndroidKeyRestrictionsArgs.builder()
.allowedApplications(ApiKeyRestrictionsAndroidKeyRestrictionsAllowedApplicationArgs.builder()
.packageName("com.example.app123")
.sha1Fingerprint("1699466a142d4682a5f91b50fdf400f2358e2b0b")
.build())
.build())
.apiTargets(ApiKeyRestrictionsApiTargetArgs.builder()
.service("translate.googleapis.com")
.methods("GET*")
.build())
.build())
.build());
}
}
resources:
primary:
type: gcp:projects:ApiKey
properties:
name: key
displayName: sample-key
restrictions:
androidKeyRestrictions:
allowedApplications:
- packageName: com.example.app123
sha1Fingerprint: 1699466a142d4682a5f91b50fdf400f2358e2b0b
apiTargets:
- service: translate.googleapis.com
methods:
- GET*
The androidKeyRestrictions property validates both the app’s package name and its SHA-1 signing certificate fingerprint. This prevents unauthorized apps from using the key even if they obtain it from decompiled code. The apiTargets array further restricts which services the key can access.
Restrict API key to iOS applications
iOS applications require bundle ID validation to ensure only authorized apps can use the embedded key.
import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";
const primary = new gcp.projects.ApiKey("primary", {
name: "key",
displayName: "sample-key",
restrictions: {
apiTargets: [{
service: "translate.googleapis.com",
methods: ["GET*"],
}],
iosKeyRestrictions: {
allowedBundleIds: ["com.google.app.macos"],
},
},
});
import pulumi
import pulumi_gcp as gcp
primary = gcp.projects.ApiKey("primary",
name="key",
display_name="sample-key",
restrictions={
"api_targets": [{
"service": "translate.googleapis.com",
"methods": ["GET*"],
}],
"ios_key_restrictions": {
"allowed_bundle_ids": ["com.google.app.macos"],
},
})
package main
import (
"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/projects"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := projects.NewApiKey(ctx, "primary", &projects.ApiKeyArgs{
Name: pulumi.String("key"),
DisplayName: pulumi.String("sample-key"),
Restrictions: &projects.ApiKeyRestrictionsArgs{
ApiTargets: projects.ApiKeyRestrictionsApiTargetArray{
&projects.ApiKeyRestrictionsApiTargetArgs{
Service: pulumi.String("translate.googleapis.com"),
Methods: pulumi.StringArray{
pulumi.String("GET*"),
},
},
},
IosKeyRestrictions: &projects.ApiKeyRestrictionsIosKeyRestrictionsArgs{
AllowedBundleIds: pulumi.StringArray{
pulumi.String("com.google.app.macos"),
},
},
},
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Gcp = Pulumi.Gcp;
return await Deployment.RunAsync(() =>
{
var primary = new Gcp.Projects.ApiKey("primary", new()
{
Name = "key",
DisplayName = "sample-key",
Restrictions = new Gcp.Projects.Inputs.ApiKeyRestrictionsArgs
{
ApiTargets = new[]
{
new Gcp.Projects.Inputs.ApiKeyRestrictionsApiTargetArgs
{
Service = "translate.googleapis.com",
Methods = new[]
{
"GET*",
},
},
},
IosKeyRestrictions = new Gcp.Projects.Inputs.ApiKeyRestrictionsIosKeyRestrictionsArgs
{
AllowedBundleIds = new[]
{
"com.google.app.macos",
},
},
},
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.projects.ApiKey;
import com.pulumi.gcp.projects.ApiKeyArgs;
import com.pulumi.gcp.projects.inputs.ApiKeyRestrictionsArgs;
import com.pulumi.gcp.projects.inputs.ApiKeyRestrictionsIosKeyRestrictionsArgs;
import java.util.List;
import java.util.ArrayList;
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) {
var primary = new ApiKey("primary", ApiKeyArgs.builder()
.name("key")
.displayName("sample-key")
.restrictions(ApiKeyRestrictionsArgs.builder()
.apiTargets(ApiKeyRestrictionsApiTargetArgs.builder()
.service("translate.googleapis.com")
.methods("GET*")
.build())
.iosKeyRestrictions(ApiKeyRestrictionsIosKeyRestrictionsArgs.builder()
.allowedBundleIds("com.google.app.macos")
.build())
.build())
.build());
}
}
resources:
primary:
type: gcp:projects:ApiKey
properties:
name: key
displayName: sample-key
restrictions:
apiTargets:
- service: translate.googleapis.com
methods:
- GET*
iosKeyRestrictions:
allowedBundleIds:
- com.google.app.macos
The iosKeyRestrictions property validates the app’s bundle identifier. The allowedBundleIds array lists permitted bundle IDs. Combined with apiTargets, this ensures only your iOS app can access specific Google services.
Restrict API key to server IP addresses
Backend services running on known infrastructure can restrict key usage to specific IP addresses.
import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";
const primary = new gcp.projects.ApiKey("primary", {
name: "key",
displayName: "sample-key",
restrictions: {
apiTargets: [{
service: "translate.googleapis.com",
methods: ["GET*"],
}],
serverKeyRestrictions: {
allowedIps: ["127.0.0.1"],
},
},
});
import pulumi
import pulumi_gcp as gcp
primary = gcp.projects.ApiKey("primary",
name="key",
display_name="sample-key",
restrictions={
"api_targets": [{
"service": "translate.googleapis.com",
"methods": ["GET*"],
}],
"server_key_restrictions": {
"allowed_ips": ["127.0.0.1"],
},
})
package main
import (
"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/projects"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := projects.NewApiKey(ctx, "primary", &projects.ApiKeyArgs{
Name: pulumi.String("key"),
DisplayName: pulumi.String("sample-key"),
Restrictions: &projects.ApiKeyRestrictionsArgs{
ApiTargets: projects.ApiKeyRestrictionsApiTargetArray{
&projects.ApiKeyRestrictionsApiTargetArgs{
Service: pulumi.String("translate.googleapis.com"),
Methods: pulumi.StringArray{
pulumi.String("GET*"),
},
},
},
ServerKeyRestrictions: &projects.ApiKeyRestrictionsServerKeyRestrictionsArgs{
AllowedIps: pulumi.StringArray{
pulumi.String("127.0.0.1"),
},
},
},
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Gcp = Pulumi.Gcp;
return await Deployment.RunAsync(() =>
{
var primary = new Gcp.Projects.ApiKey("primary", new()
{
Name = "key",
DisplayName = "sample-key",
Restrictions = new Gcp.Projects.Inputs.ApiKeyRestrictionsArgs
{
ApiTargets = new[]
{
new Gcp.Projects.Inputs.ApiKeyRestrictionsApiTargetArgs
{
Service = "translate.googleapis.com",
Methods = new[]
{
"GET*",
},
},
},
ServerKeyRestrictions = new Gcp.Projects.Inputs.ApiKeyRestrictionsServerKeyRestrictionsArgs
{
AllowedIps = new[]
{
"127.0.0.1",
},
},
},
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.projects.ApiKey;
import com.pulumi.gcp.projects.ApiKeyArgs;
import com.pulumi.gcp.projects.inputs.ApiKeyRestrictionsArgs;
import com.pulumi.gcp.projects.inputs.ApiKeyRestrictionsServerKeyRestrictionsArgs;
import java.util.List;
import java.util.ArrayList;
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) {
var primary = new ApiKey("primary", ApiKeyArgs.builder()
.name("key")
.displayName("sample-key")
.restrictions(ApiKeyRestrictionsArgs.builder()
.apiTargets(ApiKeyRestrictionsApiTargetArgs.builder()
.service("translate.googleapis.com")
.methods("GET*")
.build())
.serverKeyRestrictions(ApiKeyRestrictionsServerKeyRestrictionsArgs.builder()
.allowedIps("127.0.0.1")
.build())
.build())
.build());
}
}
resources:
primary:
type: gcp:projects:ApiKey
properties:
name: key
displayName: sample-key
restrictions:
apiTargets:
- service: translate.googleapis.com
methods:
- GET*
serverKeyRestrictions:
allowedIps:
- 127.0.0.1
The serverKeyRestrictions property limits requests to specific source IPs. The allowedIps array accepts individual addresses or CIDR ranges. This prevents key misuse if it’s exposed in logs or configuration files.
Bind API key to a service account
Service account binding creates authentication-enabled keys that inherit the service account’s IAM permissions and audit trail.
import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";
const project = new gcp.organizations.Project("project", {
projectId: "app",
name: "app",
orgId: "123456789",
deletionPolicy: "DELETE",
});
const keyServiceAccount = new gcp.serviceaccount.Account("key_service_account", {
accountId: "app",
project: project.projectId,
displayName: "Test Service Account",
});
const primary = new gcp.projects.ApiKey("primary", {
name: "key",
displayName: "sample-key",
project: project.projectId,
serviceAccountEmail: keyServiceAccount.email,
});
import pulumi
import pulumi_gcp as gcp
project = gcp.organizations.Project("project",
project_id="app",
name="app",
org_id="123456789",
deletion_policy="DELETE")
key_service_account = gcp.serviceaccount.Account("key_service_account",
account_id="app",
project=project.project_id,
display_name="Test Service Account")
primary = gcp.projects.ApiKey("primary",
name="key",
display_name="sample-key",
project=project.project_id,
service_account_email=key_service_account.email)
package main
import (
"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/organizations"
"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/projects"
"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/serviceaccount"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
project, err := organizations.NewProject(ctx, "project", &organizations.ProjectArgs{
ProjectId: pulumi.String("app"),
Name: pulumi.String("app"),
OrgId: pulumi.String("123456789"),
DeletionPolicy: pulumi.String("DELETE"),
})
if err != nil {
return err
}
keyServiceAccount, err := serviceaccount.NewAccount(ctx, "key_service_account", &serviceaccount.AccountArgs{
AccountId: pulumi.String("app"),
Project: project.ProjectId,
DisplayName: pulumi.String("Test Service Account"),
})
if err != nil {
return err
}
_, err = projects.NewApiKey(ctx, "primary", &projects.ApiKeyArgs{
Name: pulumi.String("key"),
DisplayName: pulumi.String("sample-key"),
Project: project.ProjectId,
ServiceAccountEmail: keyServiceAccount.Email,
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Gcp = Pulumi.Gcp;
return await Deployment.RunAsync(() =>
{
var project = new Gcp.Organizations.Project("project", new()
{
ProjectId = "app",
Name = "app",
OrgId = "123456789",
DeletionPolicy = "DELETE",
});
var keyServiceAccount = new Gcp.ServiceAccount.Account("key_service_account", new()
{
AccountId = "app",
Project = project.ProjectId,
DisplayName = "Test Service Account",
});
var primary = new Gcp.Projects.ApiKey("primary", new()
{
Name = "key",
DisplayName = "sample-key",
Project = project.ProjectId,
ServiceAccountEmail = keyServiceAccount.Email,
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.organizations.Project;
import com.pulumi.gcp.organizations.ProjectArgs;
import com.pulumi.gcp.serviceaccount.Account;
import com.pulumi.gcp.serviceaccount.AccountArgs;
import com.pulumi.gcp.projects.ApiKey;
import com.pulumi.gcp.projects.ApiKeyArgs;
import java.util.List;
import java.util.ArrayList;
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) {
var project = new Project("project", ProjectArgs.builder()
.projectId("app")
.name("app")
.orgId("123456789")
.deletionPolicy("DELETE")
.build());
var keyServiceAccount = new Account("keyServiceAccount", AccountArgs.builder()
.accountId("app")
.project(project.projectId())
.displayName("Test Service Account")
.build());
var primary = new ApiKey("primary", ApiKeyArgs.builder()
.name("key")
.displayName("sample-key")
.project(project.projectId())
.serviceAccountEmail(keyServiceAccount.email())
.build());
}
}
resources:
primary:
type: gcp:projects:ApiKey
properties:
name: key
displayName: sample-key
project: ${project.projectId}
serviceAccountEmail: ${keyServiceAccount.email}
project:
type: gcp:organizations:Project
properties:
projectId: app
name: app
orgId: '123456789'
deletionPolicy: DELETE
keyServiceAccount:
type: gcp:serviceaccount:Account
name: key_service_account
properties:
accountId: app
project: ${project.projectId}
displayName: Test Service Account
The serviceAccountEmail property binds the key to a service account, enabling authentication and IAM-based authorization. This creates an auth-enabled key that appears in audit logs with the service account’s identity. The key inherits the service account’s permissions rather than relying solely on API key restrictions.
Beyond these examples
These snippets focus on specific API key features: platform-specific restrictions (Android, iOS, browser, server), API service and method targeting, and service account binding. They’re intentionally minimal rather than full access control configurations.
The examples may reference pre-existing infrastructure such as GCP organizations (for service account example) and billing accounts (for project creation). They focus on configuring the key rather than provisioning surrounding infrastructure.
To keep things focused, common API key patterns are omitted, including:
- Key rotation and lifecycle management
- Multiple API target configurations
- Combining restriction types
- Project-level key quotas and limits
These omissions are intentional: the goal is to illustrate how each API key feature is wired, not provide drop-in security modules. See the API Key resource reference for all available configuration options.
Let's create GCP API Keys
Get started with Pulumi Cloud, then follow our quick setup guide to deploy this infrastructure.
Try Pulumi Cloud for FREEFrequently Asked Questions
Key Configuration & Naming
name must be lowercase, match the regex [a-z]([a-z0-9-]{0,61}[a-z0-9])? (RFC-1034 compliant), have a maximum of 63 characters, and be unique within the project. This property is immutable after creation.name, project, and serviceAccountEmail. Choose these values carefully during initial creation.Restrictions & Security
You can apply four platform-specific restrictions:
- Android -
androidKeyRestrictionswith package names and SHA1 fingerprints - iOS -
iosKeyRestrictionswith allowed bundle IDs - Browser -
browserKeyRestrictionswith allowed referrers - Server -
serverKeyRestrictionswith allowed IP addresses
apiTargets within restrictions with the service name and allowed methods. For example, service: "translate.googleapis.com" with methods: ["GET*"] restricts the key to GET requests on the Translate API.name and displayName properties, as shown in the minimal_key example. However, applying restrictions is recommended for security.serviceAccountEmail to the email address of a service account. This creates an auth-enabled key bound to that service account. Note that this property is immutable after creation.Key Access & Usage
keyString output property contains the encrypted and signed key value, but it can only be accessed through the GetKeyString method, not directly from the resource output.