Skip to main content

Osano Pulumi Provider

Build Status License: MIT npm version PyPI version NuGet version Go module version Maven Central version

⚠️ Unofficial community provider

This repo is not affiliated with Osano or Pulumi. It is maintained by the community and provided "as is" under the MIT license. Use GitHub Issues for support.

The provider lets you manage Osano Cookie Consent and Unified Consent workflows alongside the rest of your infrastructure-as-code. You can:

  • Create Cookie Consent configurations and rules, publish them after all dependencies settle, and export the hosted CMP script URL and exact HTML tag, so the same pipeline that provisions a website can put the consent script first in its <head>.
  • Look up the script, publish status, rules, discoveries, and audit log of any Cookie Consent configuration with getCookieConsentConfig, getCookieConsentConfigs, getCookieConsentRules, getCookieConsentDiscoveries, and getCookieConsentAuditLog, for example to consume a centrally managed configuration from a website stack or to gate a switch to production mode.
  • Submit consent decisions programmatically from Pulumi deployments, including Global Privacy Control consents.
  • Query unified consent state for a subject using Pulumi invokes.
  • Resolve verified, anonymous, and session references via osano.getSubject, osano.getSubjectProfile, and osano.getSession when stitching identity flows.
  • Inspect UC configuration and privacy protocol collections with osano.getConfig, osano.getCollections, and osano.getCollection invokes.
  • Check for existing consent state and hashed consent profiles with osano.checkConsent and osano.getConsentProfile.
  • Start and verify subject-profile challenges via osano.sendSubjectCode and osano.verifySubjectCode. Pulumi runs invokes on every preview, update, and refresh, so call these two from automation rather than declaring them in a long-lived stack; otherwise each run sends a new code.
  • Wire Osano calls into your CI/CD pipelines with first-class Node.js, Python, Go, .NET, and Java SDKs.

Table of contents

  1. Prerequisites
  2. Installation
  3. Quick start: publish a consent script
  4. Cookie Consent end to end
  5. Unified Consent
  6. Authentication
  7. Configuration
  8. Examples
  9. Development

Prerequisites

  • Pulumi CLI v3+
  • API access to an Osano tenant (a Customer REST API key for Cookie Consent, a Unified Consent API key for Unified Consent, or both for mixed workloads)
  • Runtime for your preferred language: Node.js 22+ (required by current @pulumi/pulumi releases), Python 3.10+, Go 1.26.6+, .NET 8+, or Java 11+

Installation

Add the SDK for your language to a Pulumi program. Each package is published to its language's registry; the badges above show the latest version:

The SDK declares its provider plugin, and Pulumi downloads the matching pulumi-resource-osano release from GitHub the first time you run pulumi preview or pulumi up. To install it manually, pin the version and point Pulumi at the GitHub releases:

pulumi plugin install resource osano 0.2.0 --server github://api.github.com/jflavan/pulumi-osano

The Java and plugin commands pin 0.2.0, the current release. Package publishing lists every published artifact, how each one is released, and how to verify its provenance or signature.

This TypeScript program creates a Cookie Consent configuration with one rule, publishes it, and hands the script tag to the rest of the program. It assumes a project created with pulumi new typescript:

npm install @jflavan/pulumi-osano
pulumi config set osano:osanoApiKey --secret   # Customer REST API key
pulumi up

index.ts:

import { createHash } from "crypto";
import * as pulumi from "@pulumi/pulumi";
import * as osano from "@jflavan/pulumi-osano";

const desired = {
  name: "www-example-com",
  domains: ["www.example.com"],
  mode: "permissive",
  configuration: { storagePolicyHref: "https://www.example.com/privacy" },
  rules: [{ storeType: "cookies", classification: "ANALYTICS", rule: "_ga", ruleType: "EXACT_MATCH" }],
};

const config = new osano.CookieConsentConfig("consent", {
  name: desired.name,
  domains: desired.domains,
  mode: desired.mode,
  configuration: desired.configuration,
});
const rules = desired.rules.map((rule, i) =>
  new osano.CookieConsentRule(`rule-${i}`, { configId: config.configId, ...rule }));

// Publish exactly once per change: derive the token from everything that is published.
const publication = new osano.CookieConsentPublication("publication", {
  configId: config.configId,
  changeToken: createHash("sha256").update(JSON.stringify(desired)).digest("hex"),
}, { dependsOn: [config, ...rules], customTimeouts: { create: "20m", update: "20m" } });

// Hand the tag to whatever renders or configures the site's <head>; it must come first.
export const scriptTag = publication.scriptTag;
export const headHtml = pulumi.interpolate`<head>\n  ${publication.scriptTag}\n</head>`;

pulumi preview never publishes. pulumi up creates the configuration and rule, publishes, waits for Osano to finish, and returns <script src="https://cmp.osano.com/{customerId}/{configId}/osano.js"></script>. Running it again without changes publishes nothing.

If you're working from a repository clone instead of published packages, the repo-local examples under examples are aimed at contributors: they build against the SDKs generated in the clone and need a locally built provider plugin. Follow the setup in the quickstart README, which also shows how to switch an example to the published packages.

The canonical C# Cookie Consent example creates a CMP configuration and its rules, then uses CookieConsentPublication to publish only after those resources settle. The companion TypeScript example implements the same lifecycle. Both compute a deterministic changeToken, declare explicit dependsOn relationships, and allow a twenty-minute customTimeouts window.

Cookie Consent resources require a Customer REST API key:

export OSANO_API_KEY="replace-with-a-customer-rest-api-key"

After publication succeeds, the resource exposes these exact public outputs:

var publication = new CookieConsentPublication(/* ... */);

return new Dictionary<string, object?>
{
    ["cookieConsentScriptSrc"] = publication.ScriptSrc, // scriptSrc
    ["cookieConsentScriptTag"] = publication.ScriptTag, // scriptTag
};

scriptSrc has the form https://cmp.osano.com/{customerId}/{configId}/osano.js; scriptTag is exactly <script src="{scriptSrc}"></script>. These installation values are deliberately non-secret. Put the returned tag first in the site <head> without async or defer, so the CMP loads before scripts it may control. The URL never changes between revisions, so a website only needs it once. Publication completion and CDN propagation are separate: Osano's CDN can take up to 15 minutes to serve a new revision, and browsers cache osano.js for up to 24 hours.

To use the script in another stack, such as one per website, read it with getCookieConsentConfig instead of managing the configuration there:

const consent = osano.getCookieConsentConfigOutput({ configId: "<config-id>" });
export const headScript = consent.scriptTag;     // the same value the publication exports
export const published = consent.publishStatus;  // the URL returns 403 until the first publish

Before switching a configuration to production mode, which blocks everything unclassified, getCookieConsentDiscoveries lists what osano.js has discovered that no rule covers yet. The end-to-end workflow guide covers the whole pipeline, including Content Security Policy settings and per-environment configurations.

See Osano's Consent JavaScript API and direct Customer REST API publishConfig operation for the upstream contracts.

The Consent resource submits a consent decision, and the functions read consent state back. This TypeScript snippet assumes a project created with pulumi new typescript:

npm install @jflavan/pulumi-osano
pulumi config set osano:unifiedConsentApiKey --secret
pulumi config set subjectRef <subject-id> --secret
pulumi config set configId <config-id>
pulumi config set privacyProtocolId <protocol-id>
pulumi up

index.ts:

import * as pulumi from "@pulumi/pulumi";
import * as osano from "@jflavan/pulumi-osano";

const cfg = new pulumi.Config();
const subjectRef = cfg.requireSecret("subjectRef");
const configId = cfg.require("configId");
const privacyProtocolId = cfg.require("privacyProtocolId");
const subjectType = cfg.get("subjectType") ?? "verified";

const subject = subjectRef.apply((value) =>
  subjectType === "anonymous" ? { anonymousId: value } : { verifiedId: value }
);

const consent = new osano.Consent("example", {
  subject,
  actions: [
    { target: privacyProtocolId, vendor: configId, action: "ACCEPT" },
  ],
  attributes: { pulumiStack: pulumi.getStack() },
  origin: "api",
  tags: ["demo"],
});

export const consentId = consent.consentId;

Run pulumi up to submit the consent. Destroying the stack removes the logical Pulumi resource but does not delete historical events from Osano (they are immutable).

Look anonymous and verified IDs up with the default referenceType (subject); session resolves a session ID. To submit a Global Privacy Control consent, set origin: "gpc" and omit actions: Osano derives the actions and the resource exports them as gpcActions. When a pipeline submits consents on a subject's behalf, set countryCodeOverride (and regionCodeOverride) so Osano does not geolocate the CI runner. The runnable version of this program is in examples/quickstart.

Authentication

Two API keys exist:

Key Header Usage
Unified Consent API key x-uc-api-key Required for consent submissions and read operations
Osano Customer REST API key x-osano-api-key Required for Cookie Consent resources and functions; sendSubjectCode and verifySubjectCode send every configured key, so either this key or the Unified Consent API key is enough

Configure them with Pulumi config:

pulumi config set osano:unifiedConsentApiKey --secret
pulumi config set osano:osanoApiKey --secret   # required for Cookie Consent and subject verification

Or set environment variables for CI:

export OSANO_UC_API_KEY="..."
export OSANO_API_KEY="..."

Configuration

Provider-level settings (all optional unless noted):

Key Description
osano:unifiedConsentApiKey Unified Consent API key (secret); OSANO_UC_API_KEY takes precedence when set
osano:osanoApiKey Customer REST API key for Cookie Consent and subject verification (secret); OSANO_API_KEY takes precedence when set
osano:apiBaseUrl Override the Unified Consent API base URL, including any path prefix; defaults to https://uc.api.osano.com; OSANO_API_BASE_URL takes precedence when set
osano:customerBaseUrl Override the Customer REST API base URL; defaults to https://api.osano.com
osano:requestTimeoutSeconds HTTP timeout for Customer REST and Unified Consent calls, default 60 seconds; OSANO_API_TIMEOUT_SECONDS takes precedence when valid

The deprecated osano:ucApiKey and osano:ucBaseUrl keys are still read as fallbacks for unifiedConsentApiKey and apiBaseUrl.

Resource-level inputs are documented in the generated SDKs, for example the Go package reference.

Examples

These repo-local examples contain Pulumi.yaml plus language-specific dependency files that reference the SDKs generated in this repository. The shared quickstart README documents the local SDK and plugin setup required when running them from a clone, and how to switch an example to the published packages.

Development

  1. Install toolchain dependencies: eval "$(mise activate zsh)" && mise install
  2. Build the provider: make provider
  3. Run tests: make test_provider
  4. Regenerate schema + SDKs after editing Go code: make codegen

For the full lifecycle (install, deploy, day-2 changes, import, teardown, and the contributor loop) see the end-to-end workflow guide. For releases, see the release guide and package publishing. See CONTRIBUTING.md and the docs for troubleshooting tips and workflows.

Release files for pulumi-osano 0.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for pulumi-osano 0.2.0
File Size Uploaded
pulumi_osano-0.2.0.tar.gz 43.2 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for pulumi-osano 0.2.0
File Interpreter ABI Platform
pulumi_osano-0.2.0-py3-none-any.whl Python 3 none any Details

Total release size: 103.9 kB

Release files / pulumi_osano-0.2.0.tar.gz

Download URL pulumi_osano-0.2.0.tar.gz
Size 43.2 kB
Tags Source
SHA-256 checksum
How to use checksums
381aa1eafd9e896b6497ebdd76b8655cc2edad8164c854e4ea1655286af17d18
BLAKE2b-256 checksum
How to use checksums
c2f45498280a8516fc15fc29c4ac884b10890b1cd4d46679ad8a16338ac043c2
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 25, 2026.

Transparency log

Release files / pulumi_osano-0.2.0-py3-none-any.whl

Download URL pulumi_osano-0.2.0-py3-none-any.whl
Size 60.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
3f8dc33f32b14cba5944e282e243470197b65d3ccada7fd0a6169bf3e760a821
BLAKE2b-256 checksum
How to use checksums
c255e14b25d3e47b1c3fe17f9491a9fbaccf286fbd975e2c55fb0d42918e6a8d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 25, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.2.0 This release

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page