The gcp:projects/apiKey:ApiKey resource, part of the Pulumi GCP provider, provisions Google Cloud API keys that authenticate requests to Google APIs. This guide focuses on three capabilities: platform-specific restrictions (Android, iOS, browser, server), API service targeting, and service account binding.
API keys authenticate to Google APIs within a project. Some configurations reference service accounts that must exist separately. The examples are intentionally small. Combine them with your own project structure and API enablement.
Create an unrestricted API key
Most teams start with an unrestricted key during development to verify API connectivity.
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 the resource identifier (must be unique, lowercase, RFC-1034 compliant). The displayName provides a human-readable label. Without restrictions, this key works from any platform and can access any enabled API in the project.
Restrict keys to specific APIs and referrers
Web applications limit which APIs a key can access and which domains can use it.
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 restrictions block controls key usage. The apiTargets array specifies which services the key can call; here, only translate.googleapis.com with GET methods. The browserKeyRestrictions block limits usage to requests from allowed referrer domains. The pattern “.” allows all referrers; replace with specific domains like “https://example.com/” for production.
Restrict keys to Android applications
Mobile apps distributed through app stores bind keys to specific package names and signing certificates.
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 block requires both packageName and sha1Fingerprint. Google Play verifies these values at runtime, ensuring the key only works when called from the specified app. The apiTargets array limits which services the key can access, even from the allowed application.
Restrict keys to iOS applications
iOS apps verify the calling application’s bundle identifier to prevent unauthorized use.
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 block accepts a list of allowedBundleIds. iOS verifies the bundle identifier at runtime. Like Android restrictions, this combines with apiTargets to control both platform identity and service access.
Restrict keys to server IP addresses
Backend services running on known infrastructure use IP-based 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",
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 block limits key usage to requests originating from allowedIps. This works for servers with static IP addresses or known IP ranges. Combine with apiTargets to control both network location and service access.
Bind keys to service accounts
Applications that need both API key simplicity and service account identity can bind keys to service accounts.
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, creating an “auth-enabled” key. This combines API key authentication with service account identity, useful when you need both the simplicity of API keys and the identity tracking of service accounts. The key inherits the service account’s IAM permissions.
Beyond these examples
These snippets focus on specific API key features: platform-specific restrictions (Android, iOS, browser, server), API service targeting and method filtering, and service account binding. They’re intentionally minimal rather than full authentication solutions.
The examples may reference pre-existing infrastructure such as GCP projects with enabled APIs, and service accounts (for binding example). They focus on configuring the key rather than provisioning the surrounding project infrastructure.
To keep things focused, common API key patterns are omitted, including:
- Key rotation and lifecycle management
- Quota limits per key
- Multiple API targets with different method restrictions
- Combining platform restrictions with service account binding
These omissions are intentional: the goal is to illustrate how each key restriction is wired, not provide drop-in authentication 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 letters, numbers, and hyphens only, matching the regex [a-z]([a-z0-9-]{0,61}[a-z0-9])?. It must start with a letter, end with a letter or number, conform to RFC-1034, and have a maximum length of 63 characters.name, project, and serviceAccountEmail properties are immutable. Changes to these fields require recreating the resource.displayName property is modifiable and can be updated after creation.Restrictions & Security
You can restrict by platform using one of these options:
- Android - Use
androidKeyRestrictionswith package names and SHA1 fingerprints - iOS - Use
iosKeyRestrictionswith bundle IDs - Browser - Use
browserKeyRestrictionswith allowed referrers - Server - Use
serverKeyRestrictionswith allowed IP addresses
apiTargets within the restrictions property, specifying the service name (e.g., translate.googleapis.com) and allowed methods (e.g., ["GET*"]).name and displayName, though applying restrictions is recommended for production use.serviceAccountEmail property to the service account’s email address. This creates a service account bound key with authentication enabled.Key Access & Usage
keyString output field contains an encrypted and signed value that can only be accessed through the GetKeyString method, not directly from resource outputs.projects/{{project}}/locations/global/keys/{{name}}, {{project}}/{{name}}, or just {{name}}.