Node.js Access Controls

No one can predict the future. Access controls let you change your mind about who has access and under what conditions.

Grant Access

Let’s say Bob enters your circle of trust. If you grant him access, he can decrypt your sensitive data.

// Grant existing policy
const Virtru = require("virtru-sdk");

function loadVirtruClient() {
  const email = process.env.VIRTRU_SDK_EMAIL;
  const appId = process.env.VIRTRU_SDK_APP_ID;
  if (!email || !appId) {
    throw "An environment variable is not set:\n- VIRTRU_SDK_EMAIL\n- VIRTRU_SDK_APP_ID";
  }
  return new Virtru.Client({ email, appId });
}

async function grantAccess(protectedFile) {
  const client = loadVirtruClient();

  // get policy
  const params = new Virtru.DecryptParamsBuilder()
    .withFileSource(protectedFile)
    .build();
  const policyId = await client.getPolicyId(params);
  const existingPolicy = await client.fetchPolicy(policyId);

  // update users
  const initialUsers = await existingPolicy.getUsersWithAccess();
  console.log("Initial users with access: " + initialUsers);
  const users = ["[email protected]"];
  const updatedPolicy = existingPolicy
    .builder()
    .addUsersWithAccess(users)
    .build();
  await client.updatePolicy(updatedPolicy);
  console.log(
    `Granted access to users: ${users} on encrypted file ${protectedFile}`
  );
}

// optionally execute from command line
if (require.main === module) {
  const protectedFile = "sensitive.txt.tdf.html";
  grantAccess(protectedFile);
}

You can also grant access before you encrypt:

// Grant new policy
const Virtru = require("virtru-sdk");

function loadVirtruClient() {
  const email = process.env.VIRTRU_SDK_EMAIL;
  const appId = process.env.VIRTRU_SDK_APP_ID;
  if (!email || !appId) {
    throw "An environment variable is not set:\n- VIRTRU_SDK_EMAIL\n- VIRTRU_SDK_APP_ID";
  }
  return new Virtru.Client({ email, appId });
}

async function protectWithAccess(unprotectedFile) {
  const client = loadVirtruClient();

  // prepare policy
  const users = ["[email protected]"];
  const policy = new Virtru.PolicyBuilder().addUsersWithAccess(users).build();
  const encryptParams = new Virtru.EncryptParamsBuilder()
    .withFileSource(unprotectedFile)
    .withDisplayFilename(unprotectedFile)
    .withPolicy(policy)
    .build();

  // encrypt
  const protectedStream = await client.encrypt(encryptParams);
  let protectedExt = ".tdf.html"; // HTML format
  const protectedFile = unprotectedFile + protectedExt;
  await protectedStream.toFile(protectedFile);
  console.log(
    `Encrypted file ${protectedFile} and granted access to users: ${users}`
  );
}

// optionally execute from command line
if (require.main === module) {
  const unprotectedFile = "sensitive.txt";
  protectWithAccess(unprotectedFile);
}

Revoke Access

Let’s say Bob leaves your circle of trust. It’d be great if he no longer had access to your sensitive data. Revoke will prevent Bob from decrypting your sensitive data:

// Revoke access
const Virtru = require("virtru-sdk");

function loadVirtruClient() {
  const email = process.env.VIRTRU_SDK_EMAIL;
  const appId = process.env.VIRTRU_SDK_APP_ID;
  if (!email || !appId) {
    throw "An environment variable is not set:\n- VIRTRU_SDK_EMAIL\n- VIRTRU_SDK_APP_ID";
  }
  return new Virtru.Client({ email, appId });
}

async function revokeAccess(protectedFile) {
  const client = loadVirtruClient();

  // get policy
  const params = new Virtru.DecryptParamsBuilder()
    .withFileSource(protectedFile)
    .build();
  const policyId = await client.getPolicyId(params);
  const existingPolicy = await client.fetchPolicy(policyId);

  // revoke access for user(s)
  const users = ["[email protected]"];
  const updatedPolicy = existingPolicy
    .builder()
    .removeUsersWithAccess(users)
    .build();
  await client.updatePolicy(updatedPolicy);
  console.log(
    `Revoked access from users: ${users} on encrypted file ${protectedFile}`
  );
}

// optionally execute from command line
if (require.main === module) {
  const protectedFile = "sensitive.txt.tdf.html";
  revokeAccess(protectedFile);
}

You will still have access to your sensitive data.

Revoke All Access

Let’s say you landed a new job Alice. Well done! But your circle of trust becomes outdated. Rather than removing every Bob from accessing your sensitive data, you can remove everyone with revoke all:

// Revoke all access
const Virtru = require("virtru-sdk");

function loadVirtruClient() {
  const email = process.env.VIRTRU_SDK_EMAIL;
  const appId = process.env.VIRTRU_SDK_APP_ID;
  if (!email || !appId) {
    throw "An environment variable is not set:\n- VIRTRU_SDK_EMAIL\n- VIRTRU_SDK_APP_ID";
  }
  return new Virtru.Client({ email, appId });
}

async function revokeAll(protectedFile) {
  const client = loadVirtruClient();

  // get policy
  const decryptParams = new Virtru.DecryptParamsBuilder()
    .withFileSource(protectedFile)
    .build();
  const policyId = await client.getPolicyId(decryptParams);

  // revoke access for all users
  await client.revokePolicy(policyId);
  console.log(
    `Revoked access for all users on encrypted file ${protectedFile}`
  );
}

// optionally execute from command line
if (require.main === module) {
  const protectedFile = "sensitive.txt.tdf.html";
  revokeAll(protectedFile);
}

You will still have access to your sensitive data.

Expire Access

Some things aren’t meant to last. Your landlord, Trent, shouldn’t have access to the sensitive data in your lease forever. Let’s make sure your sensitive data expires in a year when your lease does:

// Expire access with relative datetime
const Virtru = require("virtru-sdk");

function loadVirtruClient() {
  const email = process.env.VIRTRU_SDK_EMAIL;
  const appId = process.env.VIRTRU_SDK_APP_ID;
  if (!email || !appId) {
    throw "An environment variable is not set:\n- VIRTRU_SDK_EMAIL\n- VIRTRU_SDK_APP_ID";
  }
  return new Virtru.Client({ email, appId });
}

async function expireRelative(protectedFile) {
  const client = loadVirtruClient();

  // get policy
  const decryptParams = new Virtru.DecryptParamsBuilder()
    .withFileSource(protectedFile)
    .build();
  const policyId = await client.getPolicyId(decryptParams);
  const existingPolicy = await client.fetchPolicy(policyId);

  // expire access
  let secondsInYear = 60 * 60 * 24 * 365; // min * hour * day * year;
  const updatedPolicy = existingPolicy
    .builder()
    .enableExpirationDeadlineFromNow(secondsInYear)
    .build();
  await client.updatePolicy(updatedPolicy);
  console.log(
    `Expire access to encrypted file ${protectedFile} in ${secondsInYear} seconds`
  );
}

// optionally execute from command line
if (require.main === module) {
  const protectedFile = "sensitive.txt.tdf.html";
  expireRelative(protectedFile);
}

You can also expire at a specific date and time:

// Expire access with specific datetime
const Virtru = require("virtru-sdk");

function loadVirtruClient() {
  const email = process.env.VIRTRU_SDK_EMAIL;
  const appId = process.env.VIRTRU_SDK_APP_ID;
  if (!email || !appId) {
    throw "An environment variable is not set:\n- VIRTRU_SDK_EMAIL\n- VIRTRU_SDK_APP_ID";
  }
  return new Virtru.Client({ email, appId });
}

async function expireSpecific(protectedFile) {
  const client = loadVirtruClient();

  // get policy
  const decryptParams = new Virtru.DecryptParamsBuilder()
    .withFileSource(protectedFile)
    .build();
  const policyId = await client.getPolicyId(decryptParams);
  const existingPolicy = await client.fetchPolicy(policyId);

  // expire access
  let expiresOn = "2022-08-12T14:37:26.101Z"; // ISO-8601 Format
  const updatedPolicy = existingPolicy
    .builder()
    .enableExpirationDeadline(expiresOn)
    .build();
  await client.updatePolicy(updatedPolicy);
  console.log(
    `Expire access to encrypted file ${protectedFile} on ${expiresOn}`
  );
}

// optionally execute from command line
if (require.main === module) {
  const protectedFile = "sensitive.txt.tdf.html";
  expireSpecific(protectedFile);
}

Expiration prevents everyone else on the policy from decrypting after that time. You will still have access.

Make the same expiration calls to update dates or times.

If you’re feeling permissive, you can always remove expiration too:

// Remove access expiration
const Virtru = require("virtru-sdk");

function loadVirtruClient() {
  const email = process.env.VIRTRU_SDK_EMAIL;
  const appId = process.env.VIRTRU_SDK_APP_ID;
  if (!email || !appId) {
    throw "An environment variable is not set:\n- VIRTRU_SDK_EMAIL\n- VIRTRU_SDK_APP_ID";
  }
  return new Virtru.Client({ email, appId });
}

async function expireDisable(protectedFile) {
  const client = loadVirtruClient();

  // get policy
  const decryptParams = new Virtru.DecryptParamsBuilder()
    .withFileSource(protectedFile)
    .build();
  const policyId = await client.getPolicyId(decryptParams);
  const existingPolicy = await client.fetchPolicy(policyId);

  // remove access expiration
  const updatedPolicy = existingPolicy
    .builder()
    .disableExpirationDeadline()
    .build();
  await client.updatePolicy(updatedPolicy);
  console.log(`Removed access expiration on encrypted file ${protectedFile}`);
}

// optionally execute from command line
if (require.main === module) {
  const protectedFile = "sensitive.txt.tdf.html";
  expireDisable(protectedFile);
}

Watermark Access

Trust doesn’t have to be absolute. If you want Bob to access your sensitive data, but discourage him from sharing it, you can enable watermarking:

// Enable access watermark
const Virtru = require("virtru-sdk");

function loadVirtruClient() {
  const email = process.env.VIRTRU_SDK_EMAIL;
  const appId = process.env.VIRTRU_SDK_APP_ID;
  if (!email || !appId) {
    throw "An environment variable is not set:\n- VIRTRU_SDK_EMAIL\n- VIRTRU_SDK_APP_ID";
  }
  return new Virtru.Client({ email, appId });
}

async function watermarkEnable(protectedFile) {
  const client = loadVirtruClient();

  // get policy
  const decryptParams = new Virtru.DecryptParamsBuilder()
    .withFileSource(protectedFile)
    .build();
  const policyId = await client.getPolicyId(decryptParams);
  const existingPolicy = await client.fetchPolicy(policyId);

  // watermark access
  const updatedPolicy = existingPolicy
    .builder()
    .enableWatermarking()
    .build();
  await client.updatePolicy(updatedPolicy);
  console.log(
    `Enabled watermark when accessing encrypted file ${protectedFile}`
  );
}

// optionally execute from command line
if (require.main === module) {
  const protectedFile = "sensitive.txt.tdf.html";
  watermarkEnable(protectedFile);
}

This option only applies in Virtru’s Secure Reader, where Bob’s email address will always overlay the decrypted sensitive data.

To disable watermarking:

// Disable access watermark
const Virtru = require("virtru-sdk");

function loadVirtruClient() {
  const email = process.env.VIRTRU_SDK_EMAIL;
  const appId = process.env.VIRTRU_SDK_APP_ID;
  if (!email || !appId) {
    throw "An environment variable is not set:\n- VIRTRU_SDK_EMAIL\n- VIRTRU_SDK_APP_ID";
  }
  return new Virtru.Client({ email, appId });
}

async function watermarkDisable(protectedFile) {
  const client = loadVirtruClient();

  // get policy
  const decryptParams = new Virtru.DecryptParamsBuilder()
    .withFileSource(protectedFile)
    .build();
  const policyId = await client.getPolicyId(decryptParams);
  const existingPolicy = await client.fetchPolicy(policyId);

  // watermark access
  const updatedPolicy = existingPolicy
    .builder()
    .disableWatermarking()
    .build();
  await client.updatePolicy(updatedPolicy);
  console.log(
    `Disabled watermark when accessing encrypted file ${protectedFile}`
  );
}

// optionally execute from command line
if (require.main === module) {
  const protectedFile = "sensitive.txt.tdf.html";
  watermarkDisable(protectedFile);
}

Did this page help you?