<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Prithvi S</title>
    <description>The latest articles on DEV Community by Prithvi S (@iprithv).</description>
    <link>https://dev.to/iprithv</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3869317%2Fe48d8dde-3457-4eca-881a-f414fac5b86e.jpg</url>
      <title>DEV Community: Prithvi S</title>
      <link>https://dev.to/iprithv</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/iprithv"/>
    <language>en</language>
    <item>
      <title>How Apache Polaris Vends Credentials: Securing Data Access Without Sharing Keys</title>
      <dc:creator>Prithvi S</dc:creator>
      <pubDate>Thu, 09 Apr 2026 09:10:24 +0000</pubDate>
      <link>https://dev.to/iprithv/how-apache-polaris-vends-credentials-securing-data-access-without-sharing-keys-156i</link>
      <guid>https://dev.to/iprithv/how-apache-polaris-vends-credentials-securing-data-access-without-sharing-keys-156i</guid>
      <description>&lt;p&gt;The modern data warehouse demands a fundamental shift in how we think about access control. When you build multi-tenant systems at scale, the traditional approach - distributing long-lived API keys or database credentials - becomes a security nightmare. Apache Polaris solves this elegantly: vend temporary, scoped credentials on demand, revoke instantly, audit everything.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem: Why Long-Lived Credentials Don't Scale
&lt;/h2&gt;

&lt;p&gt;At Netflix, Cloudera, or any major data platform, you're managing access across hundreds of users, services, and applications. If you hand out permanent API keys:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Revocation is impossible&lt;/strong&gt; - a compromised key stays valid until you manually rotate it&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Audit trails are fuzzy&lt;/strong&gt; - you don't know which key accessed which data when&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Compliance is painful&lt;/strong&gt; - SOC2, HIPAA, PCI-DSS demand temporal, traceable access&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Key rotation is a nightmare&lt;/strong&gt; - updating thousands of clients, coordinating across teams&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scope is too broad&lt;/strong&gt; - a key that works today still works tomorrow, even if access should have expired&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is why cloud providers moved away from permanent credentials. AWS uses temporary STS tokens. GCP uses short-lived access tokens. Azure has managed identities. The pattern is clear: trust should be ephemeral, scoped, and revocable.&lt;/p&gt;

&lt;p&gt;Polaris applies this principle to data catalogs and table access.&lt;/p&gt;

&lt;h2&gt;
  
  
  How Polaris Vends Credentials
&lt;/h2&gt;

&lt;p&gt;Polaris is an open-source, REST-first Iceberg catalog that implements the Iceberg REST API. Unlike traditional catalogs (which require direct database access or assume long-lived credentials), Polaris mints temporary credentials on every access.&lt;/p&gt;

&lt;p&gt;Here's the flow:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Authorization Check (Who Are You? What Can You Do?)
&lt;/h3&gt;

&lt;p&gt;When a client requests data access, Polaris first checks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Is this principal (user/service) authenticated?&lt;/li&gt;
&lt;li&gt;Do they have a role with permission to access this table?&lt;/li&gt;
&lt;li&gt;Is the access read-only or read-write?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This uses Polaris's two-tier RBAC model:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Principal Roles&lt;/strong&gt; - assigned to service principals (identities)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Catalog Roles&lt;/strong&gt; - define actual permissions (TABLE_READ_DATA, TABLE_WRITE_DATA, etc.)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example: A data analyst gets role &lt;code&gt;analyst_prod&lt;/code&gt;, which is granted &lt;code&gt;TABLE_READ_DATA&lt;/code&gt; on &lt;code&gt;catalog.sales.transactions&lt;/code&gt;. A service account gets role &lt;code&gt;etl_writer&lt;/code&gt;, which gets &lt;code&gt;TABLE_WRITE_DATA&lt;/code&gt; on &lt;code&gt;catalog.etl.staging&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Storage Configuration Lookup
&lt;/h3&gt;

&lt;p&gt;Polaris queries its configuration:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Which cloud provider hosts this table? (AWS S3, GCS, Azure Blob)&lt;/li&gt;
&lt;li&gt;What credentials should be used for minting? (Polaris's service role)&lt;/li&gt;
&lt;li&gt;Are there any table-specific overrides?&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. Credential Minting
&lt;/h3&gt;

&lt;p&gt;Here's where the magic happens. Polaris calls the cloud provider's API to mint temporary, scoped credentials:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;For AWS (S3):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;assume-role(
  role_arn=polaris-service-role,
  session_name=client-session-xyz,
  session_duration=15m,
  policy=restrict-to-s3://bucket/table-path/
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Returns: temporary AWS credentials (access key + secret key) valid for 15 minutes, scoped to the specific table path.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;For GCS:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;create-service-account-key(
  service_account=polaris-sa@project.iam.gserviceaccount.com,
  lifetime=15m,
  custom-claims={ "resource": "gs://bucket/table-path" }
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Returns: short-lived JWT valid for 15 minutes, scoped to the table path.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;For Azure:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;get-managed-identity-token(
  resource=https://storage.azure.com,
  lifetime=15m,
  scope=/subscriptions/xxx/resourceGroups/yyy/providers/Microsoft.Storage/storageAccounts/zzz/blobServices/default/containers/table-path
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Returns: short-lived bearer token (OAuth2) valid for 15 minutes, scoped to the container path.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Scope Restriction
&lt;/h3&gt;

&lt;p&gt;The credentials are scoped to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Path&lt;/strong&gt; - exact table location (e.g., &lt;code&gt;s3://data/catalog/table/&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Operations&lt;/strong&gt; - read-only (GET) vs read-write (GET, PUT, DELETE)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Duration&lt;/strong&gt; - typically 15 minutes (configurable)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A client can't use these credentials to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Access other tables&lt;/li&gt;
&lt;li&gt;Write data to a read-only table&lt;/li&gt;
&lt;li&gt;Perform actions after expiration&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  5. Return to Client
&lt;/h3&gt;

&lt;p&gt;Polaris returns the temporary credentials to the client. The client's query engine (Spark, Trino, Presto, DuckDB, etc.) receives these credentials and uses them to read/write data directly to object storage.&lt;/p&gt;

&lt;p&gt;No long-lived secrets are distributed. The client never sees Polaris's service credentials.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why This Matters
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Security Benefits
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Instant Revocation&lt;/strong&gt; - Delete a principal's role, all future requests are denied instantly&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fine-Grained Access&lt;/strong&gt; - per-table, per-operation, per-principal permissions&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Auditability&lt;/strong&gt; - every credential mint event is logged (who, when, which table, read/write)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Compliance-Ready&lt;/strong&gt; - temporal credentials, immutable audit trails, no shared secrets&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Blast Radius&lt;/strong&gt; - if a credential leaks, it's only valid for 15 minutes and only for one table&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Operational Benefits
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;No Credential Rotation&lt;/strong&gt; - credentials are automatically rotated every request&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No Key Distribution&lt;/strong&gt; - no need to distribute, store, or rotate permanent keys&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multi-Cloud Ready&lt;/strong&gt; - same API works with S3, GCS, Azure, MinIO&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Client Simplicity&lt;/strong&gt; - clients just receive credentials and query - they don't manage them&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Business Benefits
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Compliance Aligned&lt;/strong&gt; - meets SOC2, HIPAA, PCI-DSS, FedRAMP requirements&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cost Control&lt;/strong&gt; - audit who accessed what, charge accordingly&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Governance&lt;/strong&gt; - enforce data mesh principles (teams own their data, Polaris mediates access)&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Real-World Example: Data Mesh at Scale
&lt;/h2&gt;

&lt;p&gt;Imagine you're running a data mesh with 50 teams, each owning their own datasets. Without Polaris:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Each team issues permanent API keys to consumers&lt;/li&gt;
&lt;li&gt;Keys spread across configuration files, CI/CD pipelines, notebooks&lt;/li&gt;
&lt;li&gt;A leaked key compromises an entire dataset&lt;/li&gt;
&lt;li&gt;Revocation requires manual updates across dozens of systems&lt;/li&gt;
&lt;li&gt;Audit trails are incomplete (keys used by multiple systems)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With Polaris:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Each consumer requests access via Polaris API (authenticated via OIDC, OAuth2, mTLS)&lt;/li&gt;
&lt;li&gt;Polaris checks if consumer's identity has permission&lt;/li&gt;
&lt;li&gt;Polaris mints a 15-minute credential scoped to the specific table and operation&lt;/li&gt;
&lt;li&gt;Consumer queries the data with the temporary credential&lt;/li&gt;
&lt;li&gt;On next request, the credential is already expired - a new one is minted&lt;/li&gt;
&lt;li&gt;Revoke a consumer's role, and all future requests fail instantly&lt;/li&gt;
&lt;li&gt;Audit logs show exactly which identity accessed which table at what time&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Version 1.3.0 Features (January 2026)
&lt;/h2&gt;

&lt;p&gt;Recent Polaris releases added:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Federated Credential Vending&lt;/strong&gt; - Polaris can mint credentials for external catalogs (Snowflake, AWS Glue) instead of clients using their own credentials&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;OPA Integration&lt;/strong&gt; - externalize authorization logic to Open Policy Agent for complex policies&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Generic Tables&lt;/strong&gt; - support Delta Lake and Hudi alongside Iceberg&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Metrics Reporting&lt;/strong&gt; - pluggable framework to report table metrics (row/byte counts, commits)&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Getting Started
&lt;/h2&gt;

&lt;p&gt;Polaris is on Apache Foundation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;GitHub:&lt;/strong&gt; &lt;a href="https://github.com/apache/polaris" rel="noopener noreferrer"&gt;https://github.com/apache/polaris&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Docs:&lt;/strong&gt; &lt;a href="https://polaris.apache.org/" rel="noopener noreferrer"&gt;https://polaris.apache.org/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;REST API:&lt;/strong&gt; Implements Iceberg REST Catalog spec&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you're building a data platform, data mesh, or multi-tenant system, Polaris's credential vending model is worth studying. It's a pattern that applies beyond Iceberg - any system managing shared resource access can benefit from temporal, scoped credentials.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;About the author:&lt;/strong&gt; I'm Prithvi S, Staff Software Engineer at Cloudera and Opensource Enthusiast. Follow my work on &lt;a href="https://github.com/iprithv" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>polaris</category>
      <category>security</category>
      <category>api</category>
      <category>cloud</category>
    </item>
  </channel>
</rss>
