Exercise - Ensure secure access with access control list

Completed

In this exercise, you update the code responsible for importing local markdowns files with configuring ACLs on selected items.

Before you start

Before you do this exercise, be sure to complete the previous exercise in this module.

Import content that's available to everyone in the organization

When you implemented the code for importing external content in the previous exercise, you configured it to be available to everyone in the organization. Here's the code that you used:

function transform(documents: Document[]): ExternalConnectors.ExternalItem[] {
  return documents.map(doc => {
    const docId = getDocId(doc);
    return {
      id: docId,
      properties: {
        title: doc.data.title ?? '',
        description: doc.data.description ?? '',
        url: doc.url,
        iconUrl: doc.iconUrl
      },
      content: {
        value: doc.content ?? '',
        type: 'text'
      },
      acl: [
        {
          accessType: 'grant',
          type: 'everyone',
          value: 'everyone'
        }
      ]
    } as ExternalConnectors.ExternalItem
  });
}

You configured the ACL to grant access to everyone. Let's adjust it for selected markdown pages that you're importing.

Import content available to select users

First, configure one of the pages that you're importing to be accessible only to a specific user.

In the web browser:

  1. Navigate to the Azure portal at https://portal.azure.com and sign in with your work or school account.

  2. From the sidebar, select Microsoft Entra ID.

  3. From the navigation, select Users.

  4. From the list of users, open one of the users by selecting their name.

  5. Copy the value of the Object ID property.

    Screenshot of the Azure portal with a user profile open.

Use this value to define a new ACL for a specific markdown page.

In the code editor:

  1. Open the loadContent.ts file, and locate the transform function.

  2. Inside the map function, define the default ACL that applies to all imported items:

    let acl: ExternalConnectors.Acl = {
      type: 'everyone',
      value: 'everyone',
      accessType: 'grant'
    };
    
  3. Next, override the default ACL for the markdown file with name ending in use-the-api.md:

    if (doc.relativePath.endsWith('use-the-api.md')) {
      acl = {
        type: 'user',
        // AdeleV
        value: '6de8ec04-6376-4939-ab47-83a2c85ab5f5',
        accessType: 'grant'
      };
    }
    
  4. Finally, update the code that returns the external item to use the defined ACL:

    return {
      id: docId,
      properties: {
        title: doc.data.title ?? '',
        description: doc.data.description ?? '',
        url: doc.url,
        iconUrl: doc.iconUrl
      },
      content: {
        value: doc.content ?? '',
        type: 'text'
      },
      acl: [
        acl
      ]
    } as ExternalConnectors.ExternalItem
    
  5. The updated transform function looks as follows:

    function transform(documents: Document[]): ExternalConnectors.ExternalItem[] {
      return documents.map(doc => {
        let acl: ExternalConnectors.Acl = {
          type: 'everyone',
          value: 'everyone',
          accessType: 'grant'
        };
        if (doc.relativePath.endsWith('use-the-api.md')) {
          acl = {
            type: 'user',
            // AdeleV
            value: '6de8ec04-6376-4939-ab47-83a2c85ab5f5',
            accessType: 'grant'
          };
        }
        const docId = getDocId(doc);
        return {
          id: docId,
          properties: {
            title: doc.data.title ?? '',
            description: doc.data.description ?? '',
            url: doc.url,
            iconUrl: doc.iconUrl
          },
          content: {
            value: doc.content ?? '',
            type: 'text'
          },
          acl: [
            acl
          ]
        } as ExternalConnectors.ExternalItem
      });
    }
    
  6. Save your changes.

Import content available to a select group

Now, let's extend the code so that another page is only accessible by a select group of users.

In the web browser:

  1. Navigate to the Azure portal at https://portal.azure.com and sign in with your work or school account.
  2. From the sidebar, select Microsoft Entra ID.
  3. From the navigation, select Groups.
  4. From the list of groups, open one of the groups by selecting their name.
  5. Copy the value of the Object Id property.

Screenshot of the Azure portal with a group page open.

Use this value to define a new ACL for a specific markdown page.

In the code editor:

  1. Open the loadContent.ts file, and locate the transform function

  2. Extend the previously defined if clause, with an extra condition to define the ACL for the markdown file with name ending in traverse-the-graph.md:

    if (doc.relativePath.endsWith('use-the-api.md')) {
      acl = {
        type: 'user',
        // AdeleV
        value: '6de8ec04-6376-4939-ab47-83a2c85ab5f5',
        accessType: 'grant'
      };
    }
    else if (doc.relativePath.endsWith('traverse-the-graph.md')) {
      acl = {
        type: 'group',
        // Sales and marketing
        value: 'a9fd282f-4634-4cba-9dd4-631a2ee83cd3',
        accessType: 'grant'
      };
    }
    
  3. The updated transform function looks as follows:

    function transform(documents: Document[]): ExternalConnectors.ExternalItem[] {
      return documents.map(doc => {
        let acl: ExternalConnectors.Acl = {
          type: 'everyone',
          value: 'everyone',
          accessType: 'grant'
        };
        if (doc.relativePath.endsWith('use-the-api.md')) {
          acl = {
            type: 'user',
            // AdeleV
            value: '6de8ec04-6376-4939-ab47-83a2c85ab5f5',
            accessType: 'grant'
          };
        }
        else if (doc.relativePath.endsWith('traverse-the-graph.md')) {
          acl = {
            type: 'group',
            // Sales and marketing
            value: 'a9fd282f-4634-4cba-9dd4-631a2ee83cd3',
            accessType: 'grant'
          };
        }
        const docId = getDocId(doc);
        return {
          id: docId,
          properties: {
            title: doc.data.title ?? '',
            description: doc.data.description ?? '',
            url: doc.url,
            iconUrl: doc.iconUrl
          },
          content: {
            value: doc.content ?? '',
            type: 'text'
          },
          acl: [
            acl
          ]
        } as ExternalConnectors.ExternalItem
      });
    }
    
  4. Save your changes.

Apply the new ACLs

The final step is to apply the newly configured ACLs.

  1. Open a terminal and change the working directory to your project.
  2. Build the project by running the npm run build command.
  3. Start loading the content by running the npm run start:loadContent command.