tessl install tessl/golang-cloud-google-com--go--kms@1.24.0Go Client Library for Google Cloud Key Management Service (KMS) API for managing cryptographic keys and performing cryptographic operations
The KMS Inventory API provides cross-project visibility into KMS keys and tracking of resources protected by those keys. The library provides two specialized clients:
Package: cloud.google.com/go/kms/inventory/apiv1
func DefaultAuthScopes() []stringReturns the default set of authentication scopes to use with the inventory package.
Returns:
[]string{
"https://www.googleapis.com/auth/cloud-platform",
}Example:
import inventory "cloud.google.com/go/kms/inventory/apiv1"
scopes := inventory.DefaultAuthScopes()
// Use scopes for custom authentication configurationThe KeyDashboardClient provides aggregated views of cryptographic keys managed by Cloud KMS in a given Cloud project.
func NewKeyDashboardClient(ctx context.Context, opts ...option.ClientOption) (*KeyDashboardClient, error)Creates a new key dashboard service client based on gRPC.
func NewKeyDashboardRESTClient(ctx context.Context, opts ...option.ClientOption) (*KeyDashboardClient, error)Creates a new key dashboard service REST client.
Example:
import inventory "cloud.google.com/go/kms/inventory/apiv1"
ctx := context.Background()
client, err := inventory.NewKeyDashboardClient(ctx)
if err != nil {
// Handle error
}
defer client.Close()type KeyDashboardClient struct {
// CallOptions contains the retry settings for each method
CallOptions *KeyDashboardCallOptions
// Has unexported fields
}func (c *KeyDashboardClient) ListCryptoKeys(ctx context.Context, req *inventorypb.ListCryptoKeysRequest, opts ...gax.CallOption) *CryptoKeyIteratorReturns cryptographic keys managed by Cloud KMS in a given Cloud project. Note that this includes keys from all locations in the project.
Request:
type ListCryptoKeysRequest struct {
Parent string // Required: "projects/{project}"
PageSize int32 // Optional: Max 1000
PageToken string // Optional: Pagination token
}Example:
import (
"cloud.google.com/go/kms/inventory/apiv1/inventorypb"
"google.golang.org/api/iterator"
)
req := &inventorypb.ListCryptoKeysRequest{
Parent: "projects/my-project",
PageSize: 100,
}
it := client.ListCryptoKeys(ctx, req)
for {
key, err := it.Next()
if err == iterator.Done {
break
}
if err != nil {
// Handle error
}
fmt.Printf("CryptoKey: %s\n", key.Name)
}func (c *KeyDashboardClient) Close() error
func (c *KeyDashboardClient) Connection() *grpc.ClientConn // Deprecatedtype KeyDashboardCallOptions struct {
ListCryptoKeys []gax.CallOption
}The KeyTrackingClient provides tracking of resources protected by KMS keys across your organization.
func NewKeyTrackingClient(ctx context.Context, opts ...option.ClientOption) (*KeyTrackingClient, error)Creates a new key tracking service client based on gRPC.
func NewKeyTrackingRESTClient(ctx context.Context, opts ...option.ClientOption) (*KeyTrackingClient, error)Creates a new key tracking service REST client.
Example:
import inventory "cloud.google.com/go/kms/inventory/apiv1"
ctx := context.Background()
client, err := inventory.NewKeyTrackingClient(ctx)
if err != nil {
// Handle error
}
defer client.Close()type KeyTrackingClient struct {
// CallOptions contains the retry settings for each method
CallOptions *KeyTrackingCallOptions
// Has unexported fields
}func (c *KeyTrackingClient) GetProtectedResourcesSummary(ctx context.Context, req *inventorypb.GetProtectedResourcesSummaryRequest, opts ...gax.CallOption) (*inventorypb.ProtectedResourcesSummary, error)Returns aggregate information about the resources protected by the given Cloud KMS CryptoKey in the same Cloud organization.
Request:
type GetProtectedResourcesSummaryRequest struct {
Name string // Required: "projects/{project}/locations/{location}/keyRings/{keyRing}/cryptoKeys/{cryptoKey}/protectedResourcesSummary"
}Response:
type ProtectedResourcesSummary struct {
Name string // Resource name
ResourceCount int64 // Total number of protected resources
ProjectCount int32 // Number of distinct projects
ResourceTypes map[string]int64 // Number of resources per resource type
CloudProducts map[string]int64 // Number of resources per cloud product
Locations map[string]int64 // Number of resources per location
}Example:
import "cloud.google.com/go/kms/inventory/apiv1/inventorypb"
req := &inventorypb.GetProtectedResourcesSummaryRequest{
Name: "projects/my-project/locations/us-central1/keyRings/my-keyring/cryptoKeys/my-key/protectedResourcesSummary",
}
summary, err := client.GetProtectedResourcesSummary(ctx, req)
if err != nil {
// Handle error
}
fmt.Printf("Total protected resources: %d\n", summary.ResourceCount)
fmt.Printf("Across %d projects\n", summary.ProjectCount)
for resourceType, count := range summary.ResourceTypes {
fmt.Printf(" %s: %d\n", resourceType, count)
}func (c *KeyTrackingClient) SearchProtectedResources(ctx context.Context, req *inventorypb.SearchProtectedResourcesRequest, opts ...gax.CallOption) *ProtectedResourceIteratorReturns metadata about the resources protected by the given Cloud KMS CryptoKey in the given Cloud organization.
Request:
type SearchProtectedResourcesRequest struct {
Scope string // Required: "organizations/{organization}"
CryptoKey string // Required: CryptoKey resource name
PageSize int32 // Optional: Max 500
PageToken string // Optional: Pagination token
ResourceTypes []string // Optional: Filter by resource types
}Example:
import (
"cloud.google.com/go/kms/inventory/apiv1/inventorypb"
"google.golang.org/api/iterator"
)
req := &inventorypb.SearchProtectedResourcesRequest{
Scope: "organizations/123456789",
CryptoKey: "projects/my-project/locations/us-central1/keyRings/my-keyring/cryptoKeys/my-key",
PageSize: 100,
ResourceTypes: []string{"compute.googleapis.com/Disk"},
}
it := client.SearchProtectedResources(ctx, req)
for {
resource, err := it.Next()
if err == iterator.Done {
break
}
if err != nil {
// Handle error
}
fmt.Printf("Protected Resource: %s\n", resource.Name)
fmt.Printf(" Project: %s\n", resource.Project)
fmt.Printf(" Location: %s\n", resource.Location)
fmt.Printf(" Type: %s\n", resource.ResourceType)
fmt.Printf(" CryptoKeyVersion: %s\n", resource.CryptoKeyVersion)
}func (c *KeyTrackingClient) Close() error
func (c *KeyTrackingClient) Connection() *grpc.ClientConn // Deprecatedtype KeyTrackingCallOptions struct {
GetProtectedResourcesSummary []gax.CallOption
SearchProtectedResources []gax.CallOption
}type ProtectedResource struct {
Name string // Full resource name of the protected resource
Project string // Project ID
ProjectId string // Project ID (alternate field)
CloudProduct string // Cloud product (e.g., "compute", "storage")
ResourceType string // Resource type (e.g., "disk", "bucket")
Location string // Location
Labels map[string]string // Resource labels
CryptoKeyVersion string // CryptoKeyVersion used to protect this resource
CryptoKeyVersions []string // All CryptoKeyVersions used (for multi-key resources)
CreateTime *timestamppb.Timestamp // Creation time
}Metadata about a resource protected by a Cloud KMS key.
Common Resource Types:
compute.googleapis.com/Diskstorage.googleapis.com/Bucketbigquery.googleapis.com/Datasetpubsub.googleapis.com/Topiccompute.googleapis.com/Snapshotcompute.googleapis.com/Imagepackage main
import (
"context"
"fmt"
"log"
inventory "cloud.google.com/go/kms/inventory/apiv1"
"cloud.google.com/go/kms/inventory/apiv1/inventorypb"
"google.golang.org/api/iterator"
)
func inventoryExample() {
ctx := context.Background()
// List all keys in a project
dashboardClient, err := inventory.NewKeyDashboardClient(ctx)
if err != nil {
log.Fatal(err)
}
defer dashboardClient.Close()
fmt.Println("=== All CryptoKeys in Project ===")
it := dashboardClient.ListCryptoKeys(ctx, &inventorypb.ListCryptoKeysRequest{
Parent: "projects/my-project",
})
for {
key, err := it.Next()
if err == iterator.Done {
break
}
if err != nil {
log.Fatal(err)
}
fmt.Printf("- %s (Purpose: %v)\n", key.Name, key.Purpose)
}
// Track protected resources for a specific key
trackingClient, err := inventory.NewKeyTrackingClient(ctx)
if err != nil {
log.Fatal(err)
}
defer trackingClient.Close()
cryptoKeyName := "projects/my-project/locations/us-central1/keyRings/my-keyring/cryptoKeys/my-key"
// Get summary
fmt.Println("\n=== Protected Resources Summary ===")
summaryName := cryptoKeyName + "/protectedResourcesSummary"
summary, err := trackingClient.GetProtectedResourcesSummary(ctx, &inventorypb.GetProtectedResourcesSummaryRequest{
Name: summaryName,
})
if err != nil {
log.Fatal(err)
}
fmt.Printf("Total resources: %d\n", summary.ResourceCount)
fmt.Printf("Across %d projects\n", summary.ProjectCount)
fmt.Println("\nBy resource type:")
for resourceType, count := range summary.ResourceTypes {
fmt.Printf(" %s: %d\n", resourceType, count)
}
fmt.Println("\nBy cloud product:")
for product, count := range summary.CloudProducts {
fmt.Printf(" %s: %d\n", product, count)
}
fmt.Println("\nBy location:")
for location, count := range summary.Locations {
fmt.Printf(" %s: %d\n", location, count)
}
// Search for specific protected resources
fmt.Println("\n=== Protected Compute Disks ===")
searchIt := trackingClient.SearchProtectedResources(ctx, &inventorypb.SearchProtectedResourcesRequest{
Scope: "organizations/123456789",
CryptoKey: cryptoKeyName,
ResourceTypes: []string{"compute.googleapis.com/Disk"},
PageSize: 50,
})
diskCount := 0
for {
resource, err := searchIt.Next()
if err == iterator.Done {
break
}
if err != nil {
log.Fatal(err)
}
diskCount++
fmt.Printf("Disk %d:\n", diskCount)
fmt.Printf(" Name: %s\n", resource.Name)
fmt.Printf(" Project: %s\n", resource.Project)
fmt.Printf(" Location: %s\n", resource.Location)
fmt.Printf(" Created: %v\n", resource.CreateTime.AsTime())
}
fmt.Printf("Total disks found: %d\n", diskCount)
}Determine which keys are actively protecting resources and which are unused:
func auditKeyUsage(dashboardClient *inventory.KeyDashboardClient, trackingClient *inventory.KeyTrackingClient) {
ctx := context.Background()
// List all keys
it := dashboardClient.ListCryptoKeys(ctx, &inventorypb.ListCryptoKeysRequest{
Parent: "projects/my-project",
})
for {
key, err := it.Next()
if err == iterator.Done {
break
}
if err != nil {
log.Fatal(err)
}
// Get usage summary
summaryName := key.Name + "/protectedResourcesSummary"
summary, err := trackingClient.GetProtectedResourcesSummary(ctx, &inventorypb.GetProtectedResourcesSummaryRequest{
Name: summaryName,
})
if err != nil {
continue // Key may have no protected resources
}
if summary.ResourceCount == 0 {
fmt.Printf("UNUSED KEY: %s\n", key.Name)
} else {
fmt.Printf("ACTIVE KEY: %s (%d resources)\n", key.Name, summary.ResourceCount)
}
}
}Generate reports on encryption coverage across your organization:
func complianceReport(trackingClient *inventory.KeyTrackingClient, cryptoKeyName, orgID string) {
ctx := context.Background()
summary, err := trackingClient.GetProtectedResourcesSummary(ctx, &inventorypb.GetProtectedResourcesSummaryRequest{
Name: cryptoKeyName + "/protectedResourcesSummary",
})
if err != nil {
log.Fatal(err)
}
fmt.Println("=== Encryption Compliance Report ===")
fmt.Printf("CryptoKey: %s\n", cryptoKeyName)
fmt.Printf("Total encrypted resources: %d\n", summary.ResourceCount)
fmt.Printf("Projects with encrypted resources: %d\n", summary.ProjectCount)
// Detailed breakdown
it := trackingClient.SearchProtectedResources(ctx, &inventorypb.SearchProtectedResourcesRequest{
Scope: fmt.Sprintf("organizations/%s", orgID),
CryptoKey: cryptoKeyName,
PageSize: 500,
})
projectMap := make(map[string]int)
for {
resource, err := it.Next()
if err == iterator.Done {
break
}
if err != nil {
log.Fatal(err)
}
projectMap[resource.Project]++
}
fmt.Println("\nPer-project breakdown:")
for project, count := range projectMap {
fmt.Printf(" %s: %d resources\n", project, count)
}
}Identify all resources that will be affected by key rotation:
func planKeyRotation(trackingClient *inventory.KeyTrackingClient, cryptoKeyName, orgID string) {
ctx := context.Background()
it := trackingClient.SearchProtectedResources(ctx, &inventorypb.SearchProtectedResourcesRequest{
Scope: fmt.Sprintf("organizations/%s", orgID),
CryptoKey: cryptoKeyName,
PageSize: 500,
})
byType := make(map[string][]string)
for {
resource, err := it.Next()
if err == iterator.Done {
break
}
if err != nil {
log.Fatal(err)
}
byType[resource.ResourceType] = append(byType[resource.ResourceType], resource.Name)
}
fmt.Println("=== Key Rotation Impact Analysis ===")
fmt.Printf("CryptoKey: %s\n\n", cryptoKeyName)
for resourceType, resources := range byType {
fmt.Printf("%s (%d resources)\n", resourceType, len(resources))
for i, name := range resources {
if i < 5 { // Show first 5
fmt.Printf(" - %s\n", name)
}
}
if len(resources) > 5 {
fmt.Printf(" ... and %d more\n", len(resources)-5)
}
fmt.Println()
}
}cloudkms.cryptoKeys.list - List CryptoKeyscloudkms.cryptoKeys.getIamPolicy - Get IAM policies