• Developer guide
  • API reference

›Security

Getting started

  • Introduction to Imply Polaris
  • Quickstart
  • Execute a POC
  • Create a dashboard
  • Navigate the console
  • Customize Polaris
  • Key concepts

Tables and data

  • Overview
  • Introduction to tables
  • Table schema
  • Ingestion jobs

    • Create an ingestion job
    • Ingest using SQL
    • Job auto-discovery
    • Timestamp expressions
    • SQL ingestion reference
    • Ingestion status reference
  • Data partitioning
  • Introduction to rollup
  • Replace data
  • Ingestion use cases

    • Approximation algorithms
    • Ingest earliest or latest value

Ingestion sources

  • Ingestion sources overview
  • Supported data formats
  • Create a connection
  • Ingest from files
  • Ingest data from a table
  • Ingest from S3
  • Ingest from Kafka and MSK
  • Ingest from Kinesis
  • Ingest from Confluent Cloud
  • Kafka Connector for Imply Polaris
  • Push event data
  • Connect to Confluent Schema Registry
  • Ingestion source reference

Analytics

  • Overview
  • Manage data cubes
  • Visualize data
  • Data cube dimensions
  • Data cube measures
  • Dashboards
  • Visualizations reference
  • Set up alerts
  • Set up reports
  • Embed visualizations

Querying

  • Overview
  • Time series functions

Monitoring

  • Overview
  • Monitoring dashboards
  • Monitor performance metrics
  • Integrate with Datadog
  • Integrate with Prometheus
  • Integrate with Elastic stack
  • Metrics reference

Management

  • Overview
  • Pause and resume a project

Usage and Billing

  • Billing structure overview
  • Polaris plans
  • Add a payment method
  • Monitor account usage

Security

    Polaris access

    • Overview
    • Invite users to your organization
    • Manage users
    • Permissions reference
    • Manage user groups
    • Enable SSO
    • SSO settings reference
    • Map IdP groups

    Secure networking

    • Connect to AWS
    • Create AWS PrivateLink connection

Developer guide

  • Overview
  • Security

    • Overview
    • Authenticate with API keys
    • Authenticate with OAuth
    • Manage users and groups
    • Restrict an embedding link
  • Migrate deprecated resources
  • Create a table
  • Upload files
  • Ingestion jobs

    • Create an ingestion job
    • Create a streaming ingestion job
    • Ingest using SQL
    • View and manage jobs

    Ingestion sources

    • Ingest from files
    • Ingest from a table
    • Get ARN for AWS access
    • Ingest from Amazon S3
    • Ingest from Kafka and MSK
    • Ingest from Amazon Kinesis
    • Ingest from Confluent Cloud
    • Push event data
    • Kafka Connector for Imply Polaris
    • Kafka Connector reference

    Ingestion use cases

    • Filter data to ingest
    • Ingest nested data
    • Ingest and query sketches
    • Specify data schema
    • Ingest Kafka metadata

    Analytics

    • Query data
    • Connect over JDBC
    • Link to BI tools
    • Query parameters reference
  • Update a project
  • API documentation

    • OpenAPI reference
    • Query API

    Migrations

    • Migrate from Hybrid

Product info

    Release notes

    • 2023
    • 2022
  • Known limitations
  • Druid extensions

Restrict an embedding link

The embedding feature in Imply Polaris provides non-Polaris users with a way to view visualizations outside the Polaris UI.

You can create public links to visualizations that anyone can access and view. See Embed visualizations for information on creating public links.

Restricted links are a more secure alternative to public links. Restricted links permit access only when the URL includes a parameter containing a signature. You create signatures programmatically using the secret key and additional parameters.

Generate restricted links

To generate restricted links you must perform the following tasks. The parameter names relate to the example scripts below.

  1. Create a restricted link and secret key.
    • url and SECRET_KEY parameters
  2. Define the link creation time.
    • created parameter
  3. Optional: Apply a data cube access filter.
    • cubeAccessFilter parameter
  4. Optional: Define an access filter for the link.
    • linkAccessFilter parameter
  5. Generate a restricted link.

You must use the exact parameter names created, cubeAccessFilter, and linkAccessFilter for Polaris to recognize them. See the example scripts for implementation examples.

Create a restricted link and secret key

See Embed visualizations for details on how to create a restricted link and secret key in the Polaris UI. You can also use the Embedding API to create a private key for an embedding link.

Define the link creation time

Set the created parameter to a string value representing the time the link was created, in milliseconds. See the example scripts for examples.

When a user accesses a restricted link, Polaris verifies the signature. If created is less than an hour ago, Polaris stores a cookie containing the authentication details. The link enables cookie creation for an hour. Polaris revokes link access at cookie creation time plus time to live from the link properties.

Optional: Apply a data cube access filter

If you're creating a restricted link for data cube that has an access filter applied, you can apply that access filter to your link.

For example, you might set up a Koalas to the Max data cube with an access filter that allows analysts in France to see only the data relevant to their home country and the United States. See the access filter example for a full example.

To find the access filter ID to plug into your script:

  1. In the Polaris UI, click Data cubes in the left pane.
  2. Click the name of the data cube that underlies the link view.
  3. Click the edit icon in the top right to edit the data cube.
  4. Click the Access filters tab and click the edit icon in the top right corner of the page.
  5. Click the view details icon to the right of the filter name.
  6. Copy the Group ID that appears.

Set the cubeAccessFilter parameter to the ID.

Optional: Define a link access filter

In addition to, or instead of, applying a data cube access filter, you can define an access filter for your specific link.

For example, if you apply the data cube filter for analysts in France outlined in the access filter example, you might want to apply an extra filter to your link for managers in Paris to view. This filter would further restrict the data in the embedded visualization to match the city name Paris:

t."cityname" = 'Paris'

Define the access filter in the linkAccessFilter parameter.

Generate a restricted link

Next, programmatically generate a signature for your link using the restricted link as follows:

  1. Import your secret key.
    The key is in Privacy Enhanced Mail (PEM) format. Import it using the Elliptic Curve Digital Signature Algorithm (ECDSA) with a P-256 curve and ensure that it has signing permissions.
  2. Create a payload of parameters with the following names, in the following order: {cubeAccessFilter, linkAccessFilter, created}.
    You can include unused parameters as undefined if you're using JavaScript or TypeScript. Otherwise, omit unused parameters.
  3. Sign the payload using the ECDSA algorithm SHA-256 and ensure it's in IEEE P1363 format.

Access a restricted link

To access the restricted link, include the signature and signed parameters as query parameters—for example:

http://ORGANIZATION_NAME.REGION.CLOUD_PROVIDER.api.imply.io/e/34392300657dc3c5d0?signature=W4HDEO4-FOX54V-cskOX&cubeAccessFilter=0e760716-b0b4-4b60-bd68&linkAccessFilter=t."cityname"='Paris'&created=1679003827755

You can add extra query parameters to the link, to vary the data in the visualization while applying the same restrictions through the signature.

Implementing restricted links

The way in which you implement the link generation depends on your specific use case. As an example, you could create a session token when a user logs into your application. You could set the session token expiry to the same period as your restricted link's time to live.

Using this configuration, you would only need to create the restricted link once per user session.

Example scripts

See the following scripts for detailed Python and JavaScript examples of programmatically generating links:

Python
JavaScript
import base64
import json
import time
​
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives.asymmetric import ec
from cryptography.hazmat.primitives.asymmetric.utils import decode_dss_signature
from cryptography.hazmat.primitives.serialization import load_pem_private_key
from cryptography.hazmat.primitives import hashes
from URLSearchParams import URLSearchParams
​
# Secret key from the Polaris UI
secretKeyPEM = "SECRET_KEY";
​
# Link URL from the Polaris UI
url = "http://ORGANIZATION_NAME.REGION.CLOUD_PROVIDER.api.imply.io/e/34392300657dc3c5d0"
​
# ID of the data cube access filter
cubeAccessFilter = "676fd330-aabc-4d76-b1a3-e9f1eff4b3a2";
​
# SQL access filter to apply to the link
linkAccessFilter = t."cityname"='Paris';

# String value of the time the link was created, in milliseconds
created = str(int(time.time() * 1000));
​
# Payload containing the required parameters
# Sign the payload parameters in the following order: {cubeAccessFilter, linkAccessFilter, created}
payload = {"created": created}
​
# Separators to prevent adding whitespace around symbols
payload = json.dumps(payload, separators=(',', ':')).encode('utf-8')
​
# Load the secret key
secretKey = load_pem_private_key(secretKeyPEM, password=None, backend=default_backend())
​
# Generate a signature format using ECDSA P-256
signature = secretKey.sign(
payload,
ec.ECDSA(hashes.SHA256())
)
​
# Convert signature format to IEEE P1363
(r, s) = decode_dss_signature(signature)
signatureP1363 = r.to_bytes(32, byteorder='big') + s.to_bytes(32, byteorder='big')
​
# Output signature as a URL-safe base64 string
print('payload signed: ', payload)
print('signature created: ', base64.urlsafe_b64encode(signatureP1363).decode('utf-8'))
​
# Build the restricted link from the signed parameters
src = URLSearchParams(url).append(
{"created": created, "signature": base64.urlsafe_b64encode(signatureP1363).decode('utf-8')})
print('You can now access your restricted link from: ', src)
const crypto = require('crypto');

function importSecretKeyFromPEM(pem) {
// Import secret key using ECDSA and P-256
return crypto.webcrypto.subtle.importKey(
'pkcs8',
Buffer.from(pem, 'base64url'),
{
name: 'ECDSA',
namedCurve: 'P-256',
},
false,
['sign']
);
}

async function signPayload(secretKeyPem, data) {
// Import secret key from PEM format
const secretKey = await importSecretKeyFromPEM(secretKeyPem);

// Sign payload with secret key using SHA-256
const signature = await crypto.webcrypto.subtle.sign(
{
name: 'ECDSA',
hash: { name: 'SHA-256' },
...secretKey.algorithm,
},
secretKey,
Buffer.from(JSON.stringify(data))
);

return signature;
}

const secretKeyPEM = 'SECRET_KEY';
const url = 'http://ORGANIZATION_NAME.REGION.CLOUD_PROVIDER.api.imply.io/e/34392300657dc3c5d0';

// Data cube access filter ID
const cubeAccessFilter = '676fd330-aabc-4d76-b1a3-e9f1eff4b3a2';

// SQL access filter to apply to the link
const linkAccessFilter = `'t."cityname"='Paris'`;

// String value of the time the link was created, in milliseconds
const created = Date.now().toString();

// Payload containing the required parameters
// Sign the payload parameters in the following order
const payload = { cubeAccessFilter: cubeAccessFilter, linkAccessFilter: linkAccessFilter, created: created };

signPayload(secretKeyPEM, payload)
.then((signature) => {
const signatureString = Buffer.from(signature).toString('base64url');

// Build the restricted link from the signed parameters
const urlObject = new URL(url)
const searchParams = new URLSearchParams(urlObject.searchParams);
if (signatureString) {
searchParams.append('signature', signatureString);
}
if (payload.cubeAccessFilter) {
searchParams.append('cubeAccessFilter', payload.cubeAccessFilter);
}
if (payload.linkAccessFilter) {
searchParams.append('linkAccessFilter', payload.linkAccessFilter);
}
searchParams.append('created', payload.created);

// Print the signed URL
console.log('payload signed: ' + JSON.stringify(payload));
console.log('signature created: ' + signatureString);
console.error('You can now access your restricted link from:');
console.log(urlObject.origin + urlObject.pathname + '?' + searchParams.toString());
})
.catch((err) => {
});
← Manage users and groupsMigrate deprecated resources →
  • Generate restricted links
    • Create a restricted link and secret key
    • Define the link creation time
    • Optional: Apply a data cube access filter
    • Optional: Define a link access filter
    • Generate a restricted link
  • Access a restricted link
  • Implementing restricted links
  • Example scripts
Key links
Try ImplyApache Druid siteImply GitHub
Get help
Stack OverflowSupportContact us
Learn more
BlogApache Druid docs
Copyright © 2023 Imply Data, Inc