Configure GCP Folder IAM Audit Logging

The gcp:folder/iamAuditConfig:IamAuditConfig resource, part of the Pulumi GCP provider, configures Cloud Audit Logs for a folder, controlling which API operations are logged and which members are exempt from logging. This guide focuses on three capabilities: enabling audit logging across services, configuring log types, and exempting specific members.

Audit configs apply to existing folders in your organization hierarchy and integrate with Cloud Logging. The example is intentionally small. Combine it with your own folder structure and logging infrastructure.

Enable audit logging for all services in a folder

Organizations tracking compliance and security events configure audit logging to capture administrative actions and data access across all GCP services.

import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";

const folder = new gcp.folder.IamAuditConfig("folder", {
    folder: "folders/1234567",
    service: "allServices",
    auditLogConfigs: [
        {
            logType: "ADMIN_READ",
        },
        {
            logType: "DATA_READ",
            exemptedMembers: ["user:joebloggs@example.com"],
        },
    ],
});
import pulumi
import pulumi_gcp as gcp

folder = gcp.folder.IamAuditConfig("folder",
    folder="folders/1234567",
    service="allServices",
    audit_log_configs=[
        {
            "log_type": "ADMIN_READ",
        },
        {
            "log_type": "DATA_READ",
            "exempted_members": ["user:joebloggs@example.com"],
        },
    ])
package main

import (
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/folder"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := folder.NewIamAuditConfig(ctx, "folder", &folder.IamAuditConfigArgs{
			Folder:  pulumi.String("folders/1234567"),
			Service: pulumi.String("allServices"),
			AuditLogConfigs: folder.IamAuditConfigAuditLogConfigArray{
				&folder.IamAuditConfigAuditLogConfigArgs{
					LogType: pulumi.String("ADMIN_READ"),
				},
				&folder.IamAuditConfigAuditLogConfigArgs{
					LogType: pulumi.String("DATA_READ"),
					ExemptedMembers: pulumi.StringArray{
						pulumi.String("user:joebloggs@example.com"),
					},
				},
			},
		})
		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 folder = new Gcp.Folder.IamAuditConfig("folder", new()
    {
        Folder = "folders/1234567",
        Service = "allServices",
        AuditLogConfigs = new[]
        {
            new Gcp.Folder.Inputs.IamAuditConfigAuditLogConfigArgs
            {
                LogType = "ADMIN_READ",
            },
            new Gcp.Folder.Inputs.IamAuditConfigAuditLogConfigArgs
            {
                LogType = "DATA_READ",
                ExemptedMembers = new[]
                {
                    "user:joebloggs@example.com",
                },
            },
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.folder.IamAuditConfig;
import com.pulumi.gcp.folder.IamAuditConfigArgs;
import com.pulumi.gcp.folder.inputs.IamAuditConfigAuditLogConfigArgs;
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 folder = new IamAuditConfig("folder", IamAuditConfigArgs.builder()
            .folder("folders/1234567")
            .service("allServices")
            .auditLogConfigs(            
                IamAuditConfigAuditLogConfigArgs.builder()
                    .logType("ADMIN_READ")
                    .build(),
                IamAuditConfigAuditLogConfigArgs.builder()
                    .logType("DATA_READ")
                    .exemptedMembers("user:joebloggs@example.com")
                    .build())
            .build());

    }
}
resources:
  folder:
    type: gcp:folder:IamAuditConfig
    properties:
      folder: folders/1234567
      service: allServices
      auditLogConfigs:
        - logType: ADMIN_READ
        - logType: DATA_READ
          exemptedMembers:
            - user:joebloggs@example.com

The service property set to “allServices” enables logging across all GCP APIs within the folder. The auditLogConfigs array defines which operation types to log: ADMIN_READ captures administrative read operations, while DATA_READ logs data access events. The exemptedMembers list excludes specific users from DATA_READ logging, useful for service accounts that generate high-volume routine access.

Beyond these examples

This snippet focuses on audit logging configuration: log type selection and member exemptions. It’s intentionally minimal rather than a complete audit strategy.

The example references pre-existing infrastructure such as GCP folders in the organization hierarchy and Cloud Logging infrastructure. It focuses on configuring audit logging rather than provisioning the folder hierarchy.

To keep things focused, common audit patterns are omitted, including:

  • Service-specific audit configs (using specific service names instead of allServices)
  • ADMIN_WRITE log type configuration
  • Integration with other IAM resources (IAMPolicy, IAMBinding, IAMMember)
  • Conditional audit logging based on resource attributes

These omissions are intentional: the goal is to illustrate how audit logging is wired, not provide drop-in compliance modules. See the Folder IamAuditConfig resource reference for all available configuration options.

Let's configure GCP Folder IAM Audit Logging

Get started with Pulumi Cloud, then follow our quick setup guide to deploy this infrastructure.

Try Pulumi Cloud for FREE

Frequently Asked Questions

Resource Selection & Conflicts
Can I accidentally lock myself out using IAMPolicy?
Yes. Deleting gcp.folder.IAMPolicy removes access from anyone without permissions on the parent folder or organization. It’s recommended to import the policy before applying changes and avoid using gcp.folder.IAMPolicy with your provider folder.
Can I use IAMPolicy with other folder IAM resources?
No. gcp.folder.IAMPolicy cannot be used with gcp.folder.IAMBinding, gcp.folder.IAMMember, or gcp.folder.IamAuditConfig as they will conflict over policy management.
Can I use IAMBinding and IAMMember together?
Yes, but only if they don’t grant privilege to the same role. Each role must be managed by either gcp.folder.IAMBinding or gcp.folder.IAMMember, not both.
What's the difference between the four folder IAM resources?

Each serves a different use case:

  • gcp.folder.IAMPolicy: Authoritative, replaces entire IAM policy
  • gcp.folder.IAMBinding: Authoritative for a role, preserves other roles
  • gcp.folder.IAMMember: Non-authoritative, adds single member to a role
  • gcp.folder.IamAuditConfig: Authoritative for a service’s audit logging
Configuration & Behavior
What format does the folder property require?
The folder property must use the format folders/{folder_id} (e.g., folders/1234567). This property is immutable after creation.
What does 'allServices' mean for audit logging?
The special value allServices for the service property enables audit logging for all GCP services in the folder.
What happens when multiple IamAuditConfig resources cover the same service?
When multiple gcp.folder.IamAuditConfig resources cover both allServices and a specific service, the union is used: all log_types are enabled, and all exempted_members are exempted.
IAM Conditions
Can I use IAM Conditions with Basic Roles?
No. IAM Conditions cannot be used with Basic Roles such as Owner due to API constraints. Use IAM Conditions only with predefined or custom roles.
Import & Migration
How do I import a folder IAM resource with a custom role?
Use the full name of the custom role in the format organizations/{{org_id}}/roles/{{role_id}}.
How do I import an IAM binding with a condition?
Include the condition title in the import command: terraform import google_folder_iam_binding.my_folder "folder roles/{{role_id}} condition-title".

Using a different cloud?

Explore security guides for other cloud providers: