Files
windmill/backend/windmill-common/src/oidc_oss.rs
6c8fd6cfe2 feat: per-user Anthropic Workload Identity Federation for Windmill AI (#11998)
* feat: authenticate Windmill AI to Anthropic with per-user Workload Identity Federation

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix: reject WIF-only Anthropic resources in agent steps, scale token refresh margin

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* refactor: move Anthropic WIF to a separate anthropic_federated resource type

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix: point agent steps at an anthropic resource instead of a federated one

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix: report a federated resource missing a field instead of reading it as standard

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* feat: count Anthropic federated token exchanges in feature_usage

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* chore: update ee-repo-ref to 747336910e5c7498544613ad7863cea59f4db6a1

This commit updates the EE repository reference after PR #923 was merged in windmill-ee-private.

Previous ee-repo-ref: 3ea70adff288448f7318ff20b41225fd726ca8d1

New ee-repo-ref: 747336910e5c7498544613ad7863cea59f4db6a1

Automated by sync-ee-ref workflow.

* feat: authenticate AI agent steps with anthropic_federated resources (#11999)

* feat: authenticate AI agent steps with anthropic_federated resources

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix: keep get_id_token's signature for its EE callers

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* chore: update ee-repo-ref to 747336910e5c7498544613ad7863cea59f4db6a1

This commit updates the EE repository reference after PR #923 was merged in windmill-ee-private.

Previous ee-repo-ref: 3ea70adff288448f7318ff20b41225fd726ca8d1

New ee-repo-ref: 747336910e5c7498544613ad7863cea59f4db6a1

Automated by sync-ee-ref workflow.

* feat: switch between anthropic and anthropic_federated when adding a resource

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix: keep registryCcCapable's doc comment on it

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com>
2026-10-25 16:37:29 +01:00

129 lines
3.5 KiB
Rust

#[cfg(feature = "private")]
#[allow(unused)]
pub use crate::oidc_ee::*;
/*
* Author: Ruben Fiszel
* Copyright: Windmill Labs, Inc 2023
* This file and its contents are licensed under the AGPLv3 License.
* Please see the included NOTICE for copyright information and
* LICENSE-AGPL for a copy of the license.
*/
#[cfg(not(feature = "private"))]
use serde::{Deserialize, Serialize};
#[cfg(not(feature = "private"))]
use tokio::sync::RwLock;
#[cfg(all(
feature = "enterprise",
feature = "openidconnect",
not(feature = "private")
))]
use {
crate::db::DB,
crate::{
auth::IdToken as WindmillIdToken,
error::{Error, Result},
},
anyhow,
};
#[cfg(all(feature = "openidconnect", not(feature = "private")))]
use openidconnect::AdditionalClaims;
#[cfg(all(feature = "openidconnect", not(feature = "private")))]
impl AdditionalClaims for JobClaim {}
#[cfg(all(feature = "openidconnect", not(feature = "private")))]
impl AdditionalClaims for WorkspaceClaim {}
#[cfg(all(feature = "openidconnect", not(feature = "private")))]
impl AdditionalClaims for InstanceClaim {}
#[derive(Clone, Debug, Default, Deserialize, PartialEq, Eq, Serialize)]
#[cfg(not(feature = "private"))]
pub struct WorkspaceClaim {
pub workspace: String,
}
#[derive(Clone, Debug, Default, Deserialize, PartialEq, Eq, Serialize)]
#[cfg(not(feature = "private"))]
pub struct InstanceClaim {}
#[derive(Clone, Debug, Default, Deserialize, PartialEq, Eq, Serialize)]
#[cfg(not(feature = "private"))]
pub struct JobClaim {
pub job_id: String,
pub path: Option<String>,
pub flow_path: Option<String>,
pub groups: Vec<String>,
pub username: String,
pub email: String,
pub workspace: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub fork_parent_workspace: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub end_user_email: Option<String>,
pub job_kind: String,
pub deployed: bool,
pub root_job_id: String,
pub root_path: Option<String>,
pub root_job_kind: String,
pub root_trigger_kind: Option<String>,
pub root_trigger: Option<String>,
pub latest: bool,
pub version: Option<String>,
pub root_version: Option<String>,
pub digest: Option<String>,
pub root_digest: Option<String>,
pub tag: String,
pub worker_group: Option<String>,
pub run_as_type: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub job_token_scopes: Option<Vec<String>>,
pub jti: String,
}
#[cfg(not(feature = "private"))]
lazy_static::lazy_static! {
static ref PRIVATE_KEY: RwLock<Option<String>> = RwLock::new(None);
}
#[cfg(not(feature = "private"))]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum OidcCaller {
JobMint,
S3Instance,
S3Workspace,
Vault,
Sqs,
Bedrock,
Anthropic,
}
#[cfg(not(feature = "private"))]
pub async fn generate_id_token<T: AdditionalClaims>(
_caller: OidcCaller,
_db: Option<&DB>,
_claim: T,
_audience: &str,
_identifier: String,
_email: Option<String>,
_expires_in: Option<i64>,
) -> Result<WindmillIdToken> {
Err(Error::internal_err(
"Not implemented in Windmill's Open Source repository".to_string(),
))
}
#[cfg(all(
feature = "enterprise",
feature = "openidconnect",
not(feature = "private")
))]
pub async fn get_private_key(_db: Option<&DB>) -> anyhow::Result<String> {
Err(anyhow::anyhow!(
"Not implemented in Windmill's Open Source repository"
))
}