Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
8fbea5e
start by moving auth config to azure_common
jlaundry Feb 22, 2026
cf02890
add auth to azure_blob
jlaundry Feb 24, 2026
f560854
initial auth switch
jlaundry Feb 25, 2026
2903a28
integration test WIP
jlaundry Feb 25, 2026
45d9e74
doc updates
jlaundry Feb 25, 2026
206692f
add feature changelog
jlaundry Feb 25, 2026
30e73b5
clippy changes
jlaundry Feb 25, 2026
5a0b5d2
add account_name and blob_endpoint options
jlaundry Feb 27, 2026
c611d4d
remove block_in_place
jlaundry Feb 28, 2026
1ad3097
add ClientCertificateCredential
jlaundry Mar 4, 2026
d03f6a6
remake certificate with required attributes
jlaundry Mar 4, 2026
f3dc448
refactor integration tests to support both connection string and oauth
jlaundry Mar 5, 2026
2de30d8
update doc examples
jlaundry Mar 5, 2026
6f94501
make clippy happy
jlaundry Mar 5, 2026
50e4ff0
fix tests
jlaundry Mar 5, 2026
bc44aea
make "client_secret_credential" explicitly configured
jlaundry Mar 10, 2026
69b8b38
add azure_logs_ingestion to Azure integration tests
jlaundry Mar 10, 2026
f2ec30f
Err out the other TlsConfig options
jlaundry Mar 10, 2026
212a90a
Add warning message to connection_string
jlaundry Mar 10, 2026
4ed4324
Simplify TlsConfig
jlaundry Mar 10, 2026
e4b650f
add workload identity config options
jlaundry Mar 10, 2026
17d51bb
Merge remote-tracking branch 'origin/master' into feature-azure_auth
thomasqueirozb Mar 12, 2026
5af8d1a
Move warning into docs::warnings
thomasqueirozb Mar 12, 2026
348cc24
Properly regenerate cue file
thomasqueirozb Mar 12, 2026
9254aee
Fix spaces
thomasqueirozb Mar 12, 2026
a18adfc
tidy options creation
jlaundry Mar 12, 2026
2d9f1a6
add UAMI type option
jlaundry Mar 12, 2026
9fa6f9a
Merge branch 'master' into feature-azure_auth
jlaundry Mar 23, 2026
6166c11
add note about breaking change
jlaundry Mar 26, 2026
3d7cff8
propagate credential errors instead of panicking
jlaundry Mar 27, 2026
022b39e
Merge branch 'master' into feature-azure_auth
jlaundry Mar 27, 2026
1069731
Merge branch 'master' into feature-azure_auth
jlaundry Mar 31, 2026
337b2fb
automatic Cargo lock change
jlaundry Mar 31, 2026
0fd42e3
Merge branch 'master' into feature-azure_auth
pront Apr 3, 2026
f7a2c60
clarify PEM cert file
jlaundry Apr 4, 2026
aa9758a
action test fixes
jlaundry Apr 4, 2026
04f91f5
Merge branch 'master' into feature-azure_auth
pront Apr 6, 2026
17090e3
allow sinks-azure_logs_ingestion to build without sinks-azure_blob
jlaundry Apr 7, 2026
abff085
require auth when using account_name or blob_endpoint
jlaundry Apr 7, 2026
e3289d4
add dep:base64
jlaundry Apr 7, 2026
9b04d66
Merge branch 'master' into feature-azure_auth
pront Apr 7, 2026
a4e5139
check-fmt changes
jlaundry Apr 7, 2026
24a7496
space diff fix
jlaundry Apr 7, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/actions/spelling/allow.txt
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,7 @@
GSM
gvisor
gws
gzip'd
hadoop
Haier
Haipad
Expand Down Expand Up @@ -256,19 +257,19 @@
JAMCRC
Jameel
Jaytech
jchap-pnnl

Check warning on line 260 in .github/actions/spelling/allow.txt

View workflow job for this annotation

GitHub Actions / Check Spelling

Ignoring entry because it contains non-alpha characters (non-alpha-in-dictionary)
jemalloc
jemallocator
jetbrains
JetBrains
jhbigler-pnnl

Check warning on line 265 in .github/actions/spelling/allow.txt

View workflow job for this annotation

GitHub Actions / Check Spelling

Ignoring entry because it contains non-alpha characters (non-alpha-in-dictionary)
Jia
Jiayu
jimmystewpot
jlambatl
jndi
Joda
jorgehermo9

Check warning on line 272 in .github/actions/spelling/allow.txt

View workflow job for this annotation

GitHub Actions / Check Spelling

Ignoring entry because it contains non-alpha characters (non-alpha-in-dictionary)
journalctl
jsonnet
jsontag
Expand Down Expand Up @@ -460,6 +461,7 @@
Salesforce
Samsung
SBT
schema'd
scriptblock
Sega
Segoe
Expand Down
1 change: 1 addition & 0 deletions .github/actions/spelling/expect.txt
Original file line number Diff line number Diff line change
Expand Up @@ -379,6 +379,7 @@ mycie
mycorp
mydatabase
mylabel
mylogstorage
mypod
myvalue
Namazu
Expand Down
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 6 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,7 @@ aws-smithy-types = { version = "1.2.11", default-features = false, features = ["

# Azure
azure_core = { version = "0.30", features = ["reqwest", "hmac_openssl"], optional = true }
azure_identity = { version = "0.30", optional = true }
azure_identity = { version = "0.30", features = ["client_certificate"], optional = true }

# Azure Storage
azure_storage_blob = { version = "0.7", optional = true }
Expand Down Expand Up @@ -875,8 +875,8 @@ sinks-aws_s3 = ["dep:base64", "dep:md-5", "aws-core", "dep:aws-sdk-s3"]
sinks-aws_sqs = ["aws-core", "dep:aws-sdk-sqs"]
sinks-aws_sns = ["aws-core", "dep:aws-sdk-sns"]
sinks-axiom = ["sinks-http"]
sinks-azure_blob = ["dep:azure_core", "dep:azure_storage_blob"]
sinks-azure_logs_ingestion = ["dep:azure_core", "dep:azure_identity"]
sinks-azure_blob = ["dep:azure_core", "dep:azure_identity", "dep:azure_storage_blob", "dep:base64"]
sinks-azure_logs_ingestion = ["dep:azure_core", "dep:azure_identity", "dep:azure_storage_blob", "dep:base64"]
sinks-azure_monitor_logs = []
sinks-blackhole = []
sinks-chronicle = []
Expand Down Expand Up @@ -987,7 +987,8 @@ aws-integration-tests = [
]

azure-integration-tests = [
"azure-blob-integration-tests"
"azure-blob-integration-tests",
"azure-logs-ingestion-integration-tests",
]

aws-cloudwatch-logs-integration-tests = ["sinks-aws_cloudwatch_logs"]
Expand All @@ -1001,6 +1002,7 @@ aws-sqs-integration-tests = ["sinks-aws_sqs"]
aws-sns-integration-tests = ["sinks-aws_sns"]
axiom-integration-tests = ["sinks-axiom"]
azure-blob-integration-tests = ["sinks-azure_blob"]
azure-logs-ingestion-integration-tests = ["sinks-azure_logs_ingestion"]
chronicle-integration-tests = ["sinks-gcp"]
clickhouse-integration-tests = ["sinks-clickhouse"]
databend-integration-tests = ["sinks-databend"]
Expand Down
3 changes: 3 additions & 0 deletions changelog.d/24729_azure_blob_authentication.feature.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Re-introduced Azure authentication support to `azure_blob`, including Azure CLI, Managed Identity, Workload Identity, and Managed Identity-based Client Assertion authentication types.

authors: jlaundry
3 changes: 3 additions & 0 deletions changelog.d/24729_azure_logs_ingestion.breaking.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
If using the `azure_logs_ingestion` sink (added in Vector 0.54.0) with Client Secret credentials, add `azure_credential_kind = "client_secret_credential"` to your sink config (this was previously the default, and now must be explicitly configured).

authors: jlaundry
88 changes: 83 additions & 5 deletions src/sinks/azure_blob/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ use crate::{
sinks::{
Healthcheck, VectorSink,
azure_common::{
self, config::AzureBlobRetryLogic, service::AzureBlobService, sink::AzureBlobSink,
self, config::AzureAuthentication, config::AzureBlobRetryLogic,
config::AzureBlobTlsConfig, service::AzureBlobService, sink::AzureBlobSink,
},
util::{
BatchConfig, BulkSizeBasedDefaultBatchSettings, Compression, ServiceBuilderExt,
Expand All @@ -41,6 +42,10 @@ impl TowerRequestConfigDefaults for AzureBlobTowerRequestConfigDefaults {
#[derive(Clone, Debug)]
#[serde(deny_unknown_fields)]
pub struct AzureBlobSinkConfig {
#[configurable(derived)]
#[serde(default)]
pub auth: Option<AzureAuthentication>,

/// The Azure Blob Storage Account connection string.
///
/// Authentication with an access key or shared access signature (SAS)
Expand All @@ -55,13 +60,33 @@ pub struct AzureBlobSinkConfig {
/// | Allowed services | Blob |
/// | Allowed resource types | Container & Object |
/// | Allowed permissions | Read & Create |
#[configurable(metadata(
docs::warnings = "Access keys and SAS tokens can be used to gain unauthorized access to Azure Blob Storage \
resources. Numerous security breaches have occurred due to leaked connection strings. It is important to keep \
connection strings secure and not expose them in logs, error messages, or version control systems."
))]
#[configurable(metadata(
docs::examples = "DefaultEndpointsProtocol=https;AccountName=mylogstorage;AccountKey=storageaccountkeybase64encoded;EndpointSuffix=core.windows.net"
))]
#[configurable(metadata(
docs::examples = "BlobEndpoint=https://mylogstorage.blob.core.windows.net/;SharedAccessSignature=generatedsastoken"
))]
pub connection_string: SensitiveString,
#[configurable(metadata(docs::examples = "AccountName=mylogstorage"))]
pub connection_string: Option<SensitiveString>,

/// The Azure Blob Storage Account name.
///
/// If provided, this will be used instead of the `connection_string`.
/// This is useful for authenticating with an Azure credential.
#[configurable(metadata(docs::examples = "mylogstorage"))]
pub(super) account_name: Option<String>,

/// The Azure Blob Storage endpoint.
///
/// If provided, this will be used instead of the `connection_string`.
/// This is useful for authenticating with an Azure credential.
#[configurable(metadata(docs::examples = "https://mylogstorage.blob.core.windows.net/"))]
pub(super) blob_endpoint: Option<String>,

/// The Azure Blob Storage Account container name.
#[configurable(metadata(docs::examples = "my-logs"))]
Expand Down Expand Up @@ -138,6 +163,10 @@ pub struct AzureBlobSinkConfig {
skip_serializing_if = "crate::serde::is_default"
)]
pub(super) acknowledgements: AcknowledgementsConfig,

#[configurable(derived)]
Comment thread
jlaundry marked this conversation as resolved.
#[serde(default)]
pub tls: Option<AzureBlobTlsConfig>,
}

pub fn default_blob_prefix() -> Template {
Expand All @@ -147,7 +176,10 @@ pub fn default_blob_prefix() -> Template {
impl GenerateConfig for AzureBlobSinkConfig {
fn generate_config() -> toml::Value {
toml::Value::try_from(Self {
connection_string: String::from("DefaultEndpointsProtocol=https;AccountName=some-account-name;AccountKey=some-account-key;").into(),
auth: None,
connection_string: Some(String::from("DefaultEndpointsProtocol=https;AccountName=some-account-name;AccountKey=some-account-key;").into()),
account_name: None,
blob_endpoint: None,
container_name: String::from("logs"),
blob_prefix: default_blob_prefix(),
blob_time_format: Some(String::from("%s")),
Expand All @@ -157,6 +189,7 @@ impl GenerateConfig for AzureBlobSinkConfig {
batch: BatchConfig::default(),
request: TowerRequestConfig::default(),
acknowledgements: Default::default(),
tls: None,
})
.unwrap()
}
Expand All @@ -166,11 +199,56 @@ impl GenerateConfig for AzureBlobSinkConfig {
#[typetag::serde(name = "azure_blob")]
impl SinkConfig for AzureBlobSinkConfig {
async fn build(&self, cx: SinkContext) -> Result<(VectorSink, Healthcheck)> {
let connection_string: String = match (
&self.connection_string,
&self.account_name,
&self.blob_endpoint,
) {
(Some(connstr), None, None) => connstr.inner().into(),
(None, Some(account_name), None) => {
if self.auth.is_none() {
return Err(
"`auth` configuration must be provided when using `account_name`".into(),
);
}
format!("AccountName={}", account_name)
}
(None, None, Some(blob_endpoint)) => {
if self.auth.is_none() {
return Err(
"`auth` configuration must be provided when using `blob_endpoint`".into(),
);
}
// BlobEndpoint must always end in a trailing slash
let blob_endpoint = if blob_endpoint.ends_with('/') {
blob_endpoint.clone()
} else {
format!("{}/", blob_endpoint)
};
format!("BlobEndpoint={}", blob_endpoint)
}
(None, None, None) => {
return Err("One of `connection_string`, `account_name`, or `blob_endpoint` must be provided".into());
}
(Some(_), Some(_), _) => {
return Err("Cannot provide both `connection_string` and `account_name`".into());
}
(Some(_), _, Some(_)) => {
return Err("Cannot provide both `connection_string` and `blob_endpoint`".into());
}
(_, Some(_), Some(_)) => {
return Err("Cannot provide both `account_name` and `blob_endpoint`".into());
}
};

let client = azure_common::config::build_client(
self.connection_string.clone().into(),
self.auth.clone(),
Comment thread
jlaundry marked this conversation as resolved.
connection_string.clone(),
self.container_name.clone(),
cx.proxy(),
)?;
self.tls.clone(),
)
.await?;

let healthcheck = azure_common::config::build_healthcheck(
self.container_name.clone(),
Expand Down
Loading
Loading