Saturday, 7 May 2022

Perspectives on the Future of Service Provider Networking: Evolved Connectivity 

The digital transformation in this decade is demanding more from the network. Multi-cloud, edge, telework, 5G, and IoT are creating an evolved connectivity ecosystem characterized by highly distributed elements needing to communicate with one another in a complex, multi-domain, many-to-many fashion. The world of north-south, east-west traffic flows is quickly disappearing. The evolved connectivity demand is for more connections from more locations, to and from more applications, with tighter Service Level Agreements (SLAs) and involving many, many more endpoints.

Further, enterprises are moving data closer to the sources consuming it and are distributing their applications to drive optimized user experiences. All these new digital assets connect and interact across multiple clouds (private, hybrid, public, and edge).

Cisco, Cisco Exam Prep, Cisco Certification, Cisco Learning, Cisco Career, Cisco Skills, Cisco Jobs, Cisco Preparation Exam

• 70-80% of large enterprises are working toward executing a multi-cloud strategy
• The number of devices requiring communications will continue to grow
- IoT devices will account for 50% (14.7 billion) of all global networked devices by 2023
- Mobile subscribers will grow from 66% of the global population to 71% of the global population by 2023
• More applications and data requiring network connectivity in new places
- More than 50% of all workloads run outside the enterprise data center
- 90% of all applications support microservices architectures, enabling distributed deployments
• STL Partners’ forecast of the capacity of network edge computing estimates around 1,600 network edge data centers and 200,000 edge servers in 55 telco networks by 2025

Today’s service provider transport network finds itself on a collision course with this evolved connectivity ecosystem. The network is highly heterogeneous, spanning access, metro, WAN, and data center technologies. Stitching these silos together leads to an explosion of complexity and policy state in the network that exists simply to make the domains interoperate. The resulting architecture is burdened with a built-in complexity tax on operations, which hampers operator agility and innovation. As application and endpoint connectivity requirements become increasingly decentralized with their functionality and data deployed across multiple domains, the underlying network is proving too rigid to adapt quickly enough. The status quo has become a complex connectivity mélange with application experience entrusted to network overlays running over best-effort IP, and innovation moves out of the network domain.

Our position: the network should operate like the cloud


As network providers, it’s time we started thinking like cloud providers. From the cloud provider’s perspective, their data centers are simply giant resource pools for their customers’ applications to dynamically consume to perform computing and storage work. Like the cloud, we should instead think of the network as a resource pool for on-demand connectivity services like segmentation, security, or SLA. This resource pool should be built on three key principles:

1. Minimize the capital and operational cost per forwarded Gb
2. Maximize the value the network provides per forwarded Gb (the value from the perspective of the application itself)
3. Eliminate friction or other barriers to applications consuming network services

The cloud operators simplify their resource pool as much as possible and ruthlessly standardize everything from data center facilities down through hardware, programmable interfaces, and infrastructure like hypervisors and container orchestration systems. All the simplification and standardization mean less cost to build, automate, and operate the infrastructure (Principle 1). More importantly, simplification means more resources to invest in innovation (Principle 2). The entire infrastructure can then be abstracted as a resource pool and presented as a catalog of services and APIs for customers’ applications to consume (Principle 3).

Our colleague Emerson Moura’s post later in this series focuses specifically on network simplification, however, we want to spend some time on the subject through the evolved connectivity and cloud provider lens. With connectivity spanning across domains, the most fundamental thing we can do is to standardize end-to-end on a common data plane to minimize the stitching points between edge, data center, cloud, and transport networks. We refer to this as the Unified Forwarding Paradigm (UFP).

A common forwarding architecture allows us to simplify elsewhere such as IPAM, DNS, and first-hop security. Consistent network connectivity means fewer moving parts for operations as all traffic transiting edge, data center, and cloud would follow common forwarding behaviors and be subject to common policies and tools for filtering and service chaining. And there’s a bonus in common telemetry metrics as well!

Our UFP recommendation is to adopt SRv6 wherever possible and ultimately IPv6 end-to-end. This common forwarding architecture provides a foundation for unified, service-aware forwarding across all network domains and includes familiar services like VPNs (EVPN, etc.) and traffic steering. More importantly, connectivity services may become software-defined. Moving to a UFP will lead to a massive reduction in friction and the network can make a true transition from configuration-centric to programmable, elastic, and on-demand. Imagine network connectivity services like pipes into the cloud or some edge environment moving to a demand-driven consumption model. Businesses no longer need to wait for operators to provision the network service. Operators would expose services via APIs for applications and users to consume in the same manner we consume VMs in the cloud: “I need an LSP/VPN to edge-zone X and I need it for two hours.” And as user and application behaviors change and require updates to the services they’re subscribed to, the change is executed via software and the network responds almost immediately.

The relationship between network overlay and underlay will also benefit from standardizing on SRv6/IPv6 and SDN. Today the overlay network is only as good as the underlay serving it. With a unified forwarding architecture and on-demand segment routing services, an SD-WAN system could directly access and consume underlay services for improved quality of experience. For flows that are latency-sensitive, the overlay network would subscribe to an underlay behavior that ensures traffic is delivered as fast as possible without delays. For the overlay networks, the SRv6 underlay that is SDN controlled provides a richer connectivity experience.

Cisco, Cisco Exam Prep, Cisco Certification, Cisco Learning, Cisco Career, Cisco Skills, Cisco Jobs, Cisco Preparation Exam

Conclusion: from ‘reachability’ to ‘rich connectivity’


Rich connectivity means the network is responsive to the user or application experience and does so in a frictionless manner. It means network overlays can subscribe to underlay services and exert granular control over how their traffic traverses the network. Rich connectivity means applications can dynamically consume low latency or lossless network services, or access security services to enable a zero-trust relationship with other elements they may need to interact with.

We believe service providers who adopt the Unified Forwarding Paradigm and embrace SDN-driven operations and consumption-based rich connectivity service models will transform themselves into platforms for innovation.

Source: cisco.com

Tuesday, 3 May 2022

The SASE story II: How Cisco IT developed our SASE product amid an evolving industry landscape

As revealed in The SASE story, part I, the SASE model brings value to enterprise IT organizations looking to achieve connectivity and security resilience through a secure, efficient, hybrid architecture. In Part II, we’ll outline the journey we took to develop our Cisco SASE solution.

CloudPort: The precursor to SASE

Throughout the past decade, IT organizations have witnessed two significant trends: the migration of applications to the Cloud, followed by Hybrid Work. These trends caused IT leaders to think differently about how to better connect users to applications. Many — including Cisco IT — realized that networking and security problems can no longer be solved in isolation. To address this, Cisco IT embarked on a journey to build our own bespoke solution by combining different Cisco networking and security components, delivering SASE-like capabilities in an on-prem platform.

At a Cisco IT offsite in 2013, during a time when workloads were starting to migrate to the cloud, we drafted what is now the CloudPort vision on a hotel bar napkin. The plan was to deploy highly scalable networking and security hardware platforms in colocation facilities worldwide.

Initially, CloudPort was conceived in response to this Hybrid Cloud paradigm shift, providing us with the opportunity to strategically place our network edge directly with major ISPs and Cloud providers. Over time, we realized we could fuse security services directly into this architecture, which allowed us to bring together networking and security into a common platform. This was, effectively, a hardware- and co-lo-based precursor to current cloud-delivered SASE. The crux of this plan was that it allowed us to layer more and more services on top – offering similar capabilities (VPN, Firewall, Zero Trust Network Access, URL filtering, etc.) to what would become known as SASE.

Cisco Exam Prep, Cisco Certification, Cisco Learning, Cisco Tutorial and Material, Cisco Career, Cisco Skill, Cisco Jobs

The CloudPort solution was and is very effective – allowing us to securely interconnect the Cisco enterprise network with the outside world.  However, as technology evolved and business requirements changed, it started to pose some challenges:

◉ Due to the layered nature of the solution, it became complex to build and operate

◉ It required specialized skillsets, which became difficult to find in the industry

◉ After years of iteration, CloudPort became an amalgamation of different technologies and solutions we had layered together ourselves, so it became difficult to quickly adjust to increasingly agile business needs

Taking into account these challenges, we decided that it was time for a different approach.

A modernized “SASE” Hub


As a stepping-stone between CloudPort and fully Cloud-delivered SASE, Cisco IT’s Customer Zero team developed a modernized solution, branded the “CZ SASE Hub.”  Since we have the in-house expertise, and we needed to use physical appliances to meet scale requirements, we decided to deploy our own solution. For customers, this new version provides a simple, easy-to-operate, Zero Trust-ready platform, and will later allow for easier migration to SASE.

The CZ SASE Hub is SD-WAN centric, leveraging both Meraki and Viptela. This allows us to efficiently bring connectivity and policy to a central, easy-to-manage place in the network. By extending micro (Cisco TrustSec) and macro segments (SDA & SD-WAN VPNs) into Cisco Secure Firewall, we can enforce identity-based policies supporting our Zero Trust for the Workplace initiatives (SDA, TrustSec/ISE). In addition, we significantly improved our observability (DNA-C/vManage Assurance, ThousandEyes, DNA Traffic Telemetry Appliance) to make sure the platform is healthy and delivers a great experience to our end users.

Cisco Exam Prep, Cisco Certification, Cisco Learning, Cisco Tutorial and Material, Cisco Career, Cisco Skill, Cisco Jobs

This homegrown solution turned out to be much easier to deploy and operate, with a much smaller footprint. If we need to expand our footprint into different colocation facilities to meet new business demands, we will entertain using Cisco SD-WAN Cloud OnRamp for colocation or Secure Agile Exchange (SAE). These highly virtualized solutions offer the same capabilities with controller-based orchestration and integrations that offload a lot of the complexity.

Adopting Cloud delivered SASE


Although our do-it-yourself platform is doing mostly what we need it to do, it poses a few challenges. Building and operating a homegrown SASE-type solution remains complex and requires in-depth expertise of many different technologies.

To address these challenges, we look to move to a cloud-delivered SASE model. With this model we can outsource the complexity, allowing experts to build and operate the platform for us. We no longer have to deploy bigger-than-needed boxes to factor in potential future growth — we can now scale up and down when business needs change. Finally, SASE provides new security capabilities within a single offering, preventing us from having to deploy a multitude of standalone security tools. An added bonus? We believe SASE can result in cost optimizations.

Our aspiration is to migrate to Unified SASE for most of our network. These easy-to-order, easy-to-operate SASE solutions provide superb integrations among some of the best technologies (SD-WAN, Umbrella SIG, AnyConnect, ZTNA/Duo), all available through a unified services portal.

For the parts of our network where we don’t migrate to Unified SASE, we will adopt Disaggregated SASE. As a large enterprise customer, Cisco has complex use-cases that ask for a bit more flexibility. Disaggregated SASE is similar to Unified SASE in that it provides much better integrations between similar technologies, yet it allows for more customization to fit our specific needs. Disaggregated SASE deconstructs certain components of Unified SASE to allow for a more flexible, scaled deployment. For example, Cisco Secure Firewall Cloud Native (SFCN) allows a containerized deployment of Next-Generation Firewall in AWS. The customer can then combine this with custom deployments of SD-WAN, Umbrella, and Duo to create a distributed, scaled-out architecture to meet Enterprise needs.

Our ultimate aim is to drive a unified solution that is tenable for large-scale, complex environments like ours, and produce a reference solution that customers can easily replicate.

Source: cisco.com

Monday, 2 May 2022

Securing Your Cloud-Native Application with Cisco App-First Security

We have some exciting news: the popular Application-First Security lab with AWS has been updated, and it is better than ever! It has now been redesigned to follow the Cisco Validated Design “Securing Cloud-Native Applications – AWS Design Guide”. We also have an updated DevNet Sandbox, which you can use to go through this lab. This lab is “ByoAWS”, or bring your own AWS org (unless you are at a proctored Cisco event). That being said, we have a cleanup script that deletes all resources afterwards, so the costs should be minimal when you go through the lab (only a couple of $).

Read More: 700-150: Introduction to Cisco Sales (ICS)

In this lab you’ll deploy the Sock Shop microservices demo application, maintained by Weaveworks and Container Solutions. Sock Shop simulates the user-facing part of an e-commerce website that sells socks. All of the Sock Shop source is on GitHub and you’ll be updating part of the application’s source code in a future portion of the lab.


Cisco Application-First Security


Before we go into the details, let’s take a step back. If you are familiar with Cisco Application-First Security, then you can skip ahead to the updates.

Cisco’s Application-First Security solution enables you to gain visibility into application behavior and increase the effectiveness of security controls by combining capabilities of best-in-class products including Cisco Secure Workload, Cisco Secure Cloud Analytics Cloud, Cisco Duo Beyond and Cisco AppDynamics with Secure Application (not yet part of the lab, coming soon!). Key features include:

◉ Closer to the application: Security closer to your application gives you insight and context of your applications so you can easily make intelligent decisions to protect them.

◉ Continuous as application changes: Application-First Security follows your applications as it changes and moves to ensure continuous protections in your digital business.

◉ Adaptive to application dependencies: Security designed to adapt to your application so it can give you granular control and reduce risk by detecting and preventing threats based on overall understanding of your environment.

In the lab you will secure a cloud-native application (i.e. Sock Shop) and public cloud infrastructure using the earlier mentioned Cisco Solutions. You’ll stage the infrastructure, modify and deploy the application, instrument the security products into the environment. In the process, you’ll get your hands dirty with products and technologies including git, Kubernetes, GitLab, Docker, AWS and others.

What has been updated?


New: Cisco Validated Design

As mentioned, this lab has now been redesigned to follow the Cisco Validated Design “Securing Cloud-Native Applications – AWS Design Guide”. This lab uses AWS to host the workloads and applications and takes advantage of many of their native services. This diagram shows how the different components are logically connected:


Now this diagram obviously doesn’t really show what the end user might see. Below you see a screenshot of the Sock Shop front end page. When first deployed, no security tools are installed yet!


New: GitLab

The lab has been updated to now include GitLab. The deployment of the Kubernetes cluster now works with a GitLab pipeline, to give an example of how this would look like in real world scenario. Pipelines are the top-level component of continuous integration, delivery, and deployment.

Pipelines comprise of jobs and stages:

◉ Jobs, which define what to do. For example, jobs that compile or test code.

◉ Stages, which define when to run the jobs. For example, stages that run tests after stages that compile the code.

In an yml file, you can define the scripts and the commands that you want to run. The scripts are grouped into jobs, and jobs run as part of a larger pipeline. You can group multiple independent jobs into stages that run in a defined order. You should organize your jobs in a sequence that suits your application and is in accordance with the tests you wish to perform. To visualize the process, imagine the scripts you add to jobs are the same as CLI commands you run on your computer to build, test and deploy your application.

New: Development script

Something else that is new is a deployment bash script that will automatically do all of the preparation steps for you. The nice thing about this is that if you only want to do the Secure Workload, Secure Cloud Analytics or only the Duo lab section, you can do that now. Before this lab was not that modular, and took in total at least 4 hours. To do this, all you need to do is run deployinfraforme from the AWS Cloud9 terminal window and you can choose. Obviously, we recommend going through the entire lab, since setting up the Kubernetes cluster is very educational.

Source: cisco.com

Sunday, 1 May 2022

ChatOps: How to Secure Your Webex Bot

This is the second blog in our series about writing software for ChatOps. In the first post of this ChatOps series, we built a Webex bot that received and logged messages to its running console. In this post, we’ll walk through how to secure your Webex bot with authentication and authorization. Securing a Webex bot in this way will allow us to feel more confident in our deployment as we move on to adding more complex features.

[Access the complete code for this post on GitHub here.]

Very important: This post picks up right where the first blog in this ChatOps series left off. Be sure to read the first post of our ChatOps series to learn how to make your local development environment publicly accessible so that Webex webhook events can reach your API. Make sure your tunnel is up and running and webhook events can flow through to your API successfully before proceeding on to the next section. From here on out, this post assumes that you’ve taken those steps and have a successful end-to-end data flow. [You can find the code from the first post on how to build a Webex bot here.]

How to secure your Webex bot with an authentication check

Webex employs HMAC-SHA1 encryption based on a secret key that you can provide, to add security to your service endpoint. For the purposes of this blog post, I’ll include that in the web service code as an Express middleware function, which will be applied to all routes. This way, it will be checked before any other route handler is called. In your environment, you might add this to your API gateway (or whatever is powering your environment’s ingress, e.g. Nginx, or an OPA policy).

How to add a secret to the Webhook

Use your preferred tool to generate a random, unique, and complex string. Make sure that it is long and complex enough to be difficult to guess. There are plenty of tools available to create a key. Since I’m on a Mac, I used the following command:

$ cat /dev/urandom | base64 | tr -dc '0-9a-zA-Z' | head -c30

The resulting string was printed into my Shell window. Be sure to hold onto it. You’ll use it in a few places in the next few steps.

Now you can use that string to update your Webhook with a PUT request. You can also add it to a new Webhook if you’d like to DELETE your old one:

Cisco ChatOps, Cisco Certification, Cisco Learning, Cisco Prep, Cisco Exam Prep, Cisco Career, Cisco Skills, Cisco Jobs, Cisco Guides, Cisco

Webex will now send an additional header with each notification request under the header key x-spark-spark-signature. The header value will be a one-way encryption of the POST body, done with the secret value that you provided. On the server side, we can attempt the same one-way encryption. If the API client sending the POST request (ideally Webex) used the same encryption secret that we used, then our resulting string should match the x-spark-spark-signature header value.

How to add an application configuration

Now that things are starting to get more complex, let’s build out an application along the lines of what we can expect to see in the real world. First, we create a simple (but extensible) AppConfig class in config/appConfig.js. We’ll use this to pull in environment variables and then reference those values in other parts of our code. For now, it’ll just include the three variables needed to power authentication:

◉ the secret that we added to our Webhook
◉ the header key where we’ll examine the encrypted value of the POST body
◉ the encryption algorithm used, which in this case is ”sha1”

Here’s the code for the AppConfig class, which we’ll add as our code gets more complex:

// in config/appConfig.js
import process from 'process';

export class AppConfig {
    constructor() {
        this.encryptionSecret = process.env['WEBEX_ENCRYPTION_SECRET'];
        this.encryptionAlgorithm = process.env['WEBEX_ENCRYPTION_ALGO'];
        this.encryptionHeader = process.env['WEBEX_ENCRYPTION_HEADER'];
    }
}

Super important: Be sure to populate these environment variables in your development environment. Skipping this step can lead to a few minutes of frustration before remembering to populate these values.

Now we can create an Auth service class that will expose a method to run our encrypted string comparison:

// in services/Auth.js
import crypto from "crypto";

export class Auth {
    constructor(appConfig) {
        this.encryptionSecret = appConfig.encryptionSecret;
        this.encryptionAlgorithm = appConfig.encryptionAlgorithm;
    }

    isProperlyEncrypted(signedValue, messsageBody) {
        // create an encryption stream
        const hmac = crypto.createHmac(this.encryptionAlgorithm, 
this.encryptionSecret);
        // write the POST body into the encryption stream
        hmac.write(JSON.stringify(messsageBody));
        // close the stream to make its resulting string readable
        hmac.end();
        // read the encrypted value
        const hash = hmac.read().toString('hex');
        // compare the freshly encrypted value to the POST header value,
        // and return the result
        return hash === signedValue;
    }
}

Pretty straightforward, right? Now we need to leverage this method in a router middleware that will check all incoming requests for authentication. If the authentication check doesn’t pass, the service will return a 401 and respond immediately. I do this in a new file called routes/auth.js:

// in routes/auth.js
import express from 'express'
import {AppConfig} from '../config/AppConfig.js';
import {Auth} from "../services/Auth.js";

const router = express.Router();
const config = new AppConfig();
const auth = new Auth(config);

router.all('/*', async (req, res, next) => {
    // a convenience reference to the POST body
    const messageBody = req.body;
    // a convenience reference to the encrypted string, with a fallback if the value isn’t set
    const signedValue = req.headers[config.encryptionHeader] || "";
    // call the authentication check
    const isProperlyEncrypted = auth.isProperlyEncrypted(signedValue, messageBody);
    if(!isProperlyEncrypted) {
        res.statusCode = 401;
        res.send("Access denied");
    }

    next();
});

export default router;

All that’s left to do is to add this router into the Express application, just before the handler that we defined earlier. Failing the authentication check will end the request’s flow through the service logic before it ever gets to any other route handlers. If the check does pass, then the request can continue on to the next route handler:

// in app.js

import express from 'express';
import logger from 'morgan';
// ***ADD THE AUTH ROUTER IMPORT***
import authRouter from './routes/auth.js';
import indexRouter from './routes/index.js';

// skipping some of the boilerplate…

// ***ADD THE AUTH ROUTER TO THE APP***
app.use(authRouter);

app.use('/', indexRouter);

// the rest of the file stays the same…

Now if you run your server again, you can test out your authentication check. You can try with just a simple POST from a local cURL or Postman request. Here’s a cURL command that I used to test it against my local service:

$ curl --location --request POST 'localhost:3000' \
--header 'x-spark-signature: incorrect-value' \
--header 'Content-Type: application/json' \
--data-raw '{
    "key": "value"
}'

Running that same request in Postman produces the following output:

Cisco ChatOps, Cisco Certification, Cisco Learning, Cisco Prep, Cisco Exam Prep, Cisco Career, Cisco Skills, Cisco Jobs, Cisco Guides, Cisco

Now, if you send a message to your bot through Webex, you should see the Webhook event flow through your authentication check and into the route handler that we created in the first post.

How to add optional authorization


At this point, we can rest assured that any request that comes through came from Webex. But that doesn’t mean we’re done with security! We might want to restrict which users in Webex can call our bot by mentioning it in a Webex Room. If that’s the case, we need to add an authorization check as well.

How to check against a list of authorized users

Webex sends user information with each event notification, indicating the Webex user ID and the corresponding email address of the person who triggered the event (an example is displayed in the first post in this series). In the case of a message creation event, this is the person who wrote the message about which our web service is notified. There are dozens of ways to check for authorization – AD groups, AWS Cognito integrations, etc.

For simplicity’s sake, in this demo service, I’m just using a hard-coded list of approved email addresses that I’ve added to the Auth service constructor, and a simple public method to check the email address that Webex provided in the POST body against that hard-coded list. Other, more complicated modes of authz checks are beyond the scope of this post.

// in services/Auth.js
export class Auth {
    constructor(appConfig) {
        this.encryptionSecret = appConfig.encryptionSecret;
        this.encryptionAlgorithm = appConfig.encryptionAlgorithm;
        // ADDING AUTHORIZED USERS
        this.authorizedUsers = [
           "colacy@cisco.com" // hey, that’s me!
        ];
    }

    // ADDING AUTHZ CHECK METHOD
    isUserAuthorized(messageBody) {
        return this.authorizedUsers.indexOf(messageBody.data.personEmail) 
!== -1
    }
// the rest of the class is unchanged

Just like with the authentication check, we need to add this to our routes/auth.js handler. We’ll add this between the authentication check and the next() call that completes the route handler.

// in routes/auth.js
// …

    const isProperlyEncrypted = auth.isProperlyEncrypted(signedValue, messageBody);
    if(!isProperlyEncrypted) {
        res.statusCode = 401;
        res.send("Access denied");
        return;
    }

    // ADD THE AUTHORIZATION CHECK
    const isAuthorized = auth.isUserAuthorized(messageBody);
    if(!isAuthorized) {
        res.statusCode = 403;
        res.send("Unauthorized");
        return;
    }

    next();
// …

If the sender’s email address isn’t in that list, the bot will send a 403 back to the API client with a message that the user was unauthorized. But that doesn’t really let the user know what went wrong, does it?

User Feedback


If the user is unauthorized, we should let them know so that they aren’t under the incorrect assumption that their request was successful — or worse, wondering why nothing happened. In this situation, the only way to provide the user with that feedback is to respond in the Webex Room where they posted their message to the bot.

Creating messages on Webex is done with POST requests to the Webex API. [The documentation and the data schema can be found here.] Remember, the bot authenticates with the access token that was provided back when we created it in the first post. We’ll need to pass that in as a new environment variable into our AppConfig class:

// in config/AppConfig.js
export class AppConfig {
    constructor() {
        // ADD THE BOT'S TOKEN
        this.botToken = process.env['WEBEX_BOT_TOKEN'];
        this.encryptionSecret = process.env['WEBEX_ENCRYPTION_SECRET'];
        this.encryptionAlgorithm = process.env['WEBEX_ENCRYPTION_ALGO'];
        this.encryptionHeader = process.env['WEBEX_ENCRYPTION_HEADER'];
    }
}

Now we can start a new service class, WebexNotifications, in a new file called services/WebexNotifications.js, which will notify our users of what’s happening in the backend.

// in services/WebexNotifications.js

export class WebexNotifications {
    constructor(appConfig) {
        this.botToken = appConfig.botToken;
    }

    // new methods to go here

}

This class is pretty sparse. For the purposes of this demo, we’ll keep it that way. We just need to give our users feedback based on whether or not their request was successful. That can be done with a single method, implemented in our two routers; one to indicate authorization failures and the other to indicate successful end-to-end messaging.

A note on the code below: To stay future-proof, Iʼm using the NodeJS version 17.7, which has fetch enabled using the execution flag –experimental-fetch. If you have an older version of NodeJS, you can use a third-party HTTP request library, like axios, and use that in place of any lines where you see fetch used.

Weʼll start by implementing the sendNotification method, which will take the same messageBody object that weʼre using for our auth checks:

// in services/WebexNotifications.js…
// inside the WebexNotifications.js class

   async sendNotification(messageBody, success=false) {
       // we'll start a response by tagging the person who created the message
       let responseToUser = 
`<@personEmail:${messageBody.data.personEmail}>`;
       // determine if the notification is being sent due to a successful or failed authz check
       if (success === false) {
           responseToUser += ` Uh oh! You're not authorized to make requests.`;
       } else {
           responseToUser += ` Thanks for your message!`;
       }
       // send a message creation request on behalf of the bot
       const res = await fetch("https://webexapis.com/v1/messages", {
           headers: {
               "Content-Type": "application/json",
               "Authorization": `Bearer ${this.botToken}`
           },
           method: "POST",
           body: JSON.stringify({
               roomId: messageBody.data.roomId,
               markdown: responseToUser
           })
       });
       return res.json();
   }

Now it’s just a matter of calling this method from within our route handlers. In routes/auth.js we’ll call it in the event of an authorization failure:

// in routes/auth.js

import express from 'express'
import {AppConfig} from '../config/AppConfig.js';
import {Auth} from "../services/Auth.js";
// ADD THE WEBEXNOTIFICATIONS IMPORT
import {WebexNotifications} from '../services/WebexNotifications.js';

// …

const auth = new Auth(config);
// ADD CLASS INSTANTIATION
const webex = new WebexNotifications(config);

// ...

    if(!isAuthorized) {
        res.statusCode = 403;
        res.send("Unauthorized");
        // ADD THE FAILURE NOTIFICATION
        await webex.sendNotification(messageBody, false);
        return;
    }
// ...

Similarly, we’ll add the success version of this method call to routes/index.js. Here’s the final version of routes/index.js once we’ve added a few more lines like we did in the auth route:

// in routes/index.js

import express from 'express'
// Add the AppConfig import
import {AppConfig} from '../config/AppConfig.js';
// Add the WebexNotifications import
import {WebexNotifications} from '../services/WebexNotifications.js';

const router = express.Router();
// instantiate the AppConfig
const config = new AppConfig();
// instantiate the WebexNotification class, passing in our app config
const webex = new WebexNotifications(config);

router.post('/', async function(req, res) {
  console.log(`Received a POST`, req.body);
  res.statusCode = 201;
  res.end();
  await webex.sendNotification(req.body, true);
});

export default router;

To test this out, I’ll simply comment out my own email address from the approved list and then send a message to my bot. As you can see from the screenshot below, Webex will display the notification from the code above, indicating that I’m not allowed to make the request.

Cisco ChatOps, Cisco Certification, Cisco Learning, Cisco Prep, Cisco Exam Prep, Cisco Career, Cisco Skills, Cisco Jobs, Cisco Guides, Cisco

If I un-comment my email address, the request goes through successfully.

Cisco ChatOps, Cisco Certification, Cisco Learning, Cisco Prep, Cisco Exam Prep, Cisco Career, Cisco Skills, Cisco Jobs, Cisco Guides, Cisco

Source: cisco.com

Saturday, 30 April 2022

ChatOps: How to Build Your First Webex Bot

In this post, you’ll learn how to create a Webex bot, register a Webhook in Webex, and configure your bot to listen to Webhook – all with plenty of code examples. Check back for more as we build new use cases that leverage different aspects of automation using chat-driven interfaces.

In the DevOps world, we’re always looking for new ways to drive automation around communication. When we deploy new code, scale our deployments, or manage our feature flags – we want our teams to know about it. The Webex API makes it easy to build announcement flows triggered by successful events in our infrastructure. However, if we can trigger those events from Webex as well, then we’ve entered the world of ChatOps.

More Info: 300-835: Automating Cisco Collaboration Solutions (CLAUTO)

ChatOps is the use of chat clients like Webex Teams, chatbots, and real-time communication tools to facilitate how software development and operation tasks are communicated and executed. Using Webex APIs, we can build bots that allow us to enter commands that manage our infrastructure, trigger approval workflows, deploy code, and much more.

Security Disclaimer

Security is a top concern here at Cisco. In normal application development, security should always be built into the initial steps of getting code up and running. Today, we’re going to keep it simple and focus on the basics. Then, we’ll cover how to authenticate and authorize Webhook requests. We’ll hold off on security until the next blog post in our ChatOps series, once we’ve proven an end-to-end connection. 

How to create a Webex bot

First, let’s create a Webex bot using the Webex Developer UI.

Cisco ChatOps, Cisco Exam Prep, Cisco Career, Cisco Skills, Cisco Jobs, Cisco Preparation, Cisco Guides, Cisco Preparation Exam

Webex for Developers has a great step-by-step guide here to help you get up and running.

Some important things to consider:

◉ Think about what you want to name your bot. It should be intuitive, but unique. Depending on how you set up your Webhook, you may be typing the bot’s name a lot, so take that into account.

◉ The secret token that’s auto-generated for your bot is used for authenticating with the Webex API. When you use this token, Webex will treat your bot like a real user who can create messages, join rooms, or be tagged by other users.

◉ Will this bot interact with a lot of people? Will it have a very public presence, or will it only communicate with a few users? The answer to that question may have an impact on how you want to name it, what icon you select, etc.

Once you’ve taken all of that into account and filled out the bot creation form, you should see something like this, which includes the all-important access token:

Cisco ChatOps, Cisco Exam Prep, Cisco Career, Cisco Skills, Cisco Jobs, Cisco Preparation, Cisco Guides, Cisco Preparation Exam

How to receive Webhook Events locally


Next, you’ll need to host your bot where it can be accessed by Webex via API calls. If you’re developing locally and want to run a server that’s accessible to the internet, the Webex guide recommends localtunnel.me or ngrok. I went with localtunnel.me for my local environment.

$ npm i -g localtunnel
$ lt --port 3000

The resulting output is the public domain name that you can use to tunnel through to a local port on your machine:

Cisco ChatOps, Cisco Exam Prep, Cisco Career, Cisco Skills, Cisco Jobs, Cisco Preparation, Cisco Guides, Cisco Preparation Exam

Note: If you’re having trouble running localtunnel via the command line after installing (as a few people have reported here), make sure your PATH includes the directory where NPM installs your binaries. For example, on a Mac, that’s /usr/local/bin. This command might help:

$ npm config set prefix /usr/local
$ npm i -g localtunnel
$ lt --port 3000

How to register a Webhook


Once your internet-accessible endpoint has been set up, you now have a domain that you can use to register a Webex Webhook. Your Webex Webhook will listen to specific events that take place within the Webex platform and notify your web service via HTTP POST requests.

There are multiple ways to register a webhook. Under the hood, however, they all boil down to making your own HTTP POST request. I’ve posted a Postman collection that you can use to make this process a little easier. Fill in your own environment’s variables as you go and include the access token used in the header.

This is what my Postman request looks like:

Cisco ChatOps, Cisco Exam Prep, Cisco Career, Cisco Skills, Cisco Jobs, Cisco Preparation, Cisco Guides, Cisco Preparation Exam

Feel free to use whatever technology you like, including good old-fashion CURL:

curl --location --request POST 'https://webexapis.com/v1/webhooks' \
--header 'Authorization: Bearer $BOT_TOKEN \
--header 'Content-Type: application/json' \
--data-raw '{
    "name": "simple-webhook",
    "targetUrl": "https://tidy-falcon-64.loca.lt",
    "resource": "messages",
    "event": "created",
    "filter": "mentionedPeople=me"
}'
What’s important to note, is that Webex will send notifications to the domain that you specify in your POST request. If you’re using a tunnel into your local environment, list the domain that was given to you when you activated your proxy.

A very impactful part of your Webhook will be the filter property. This determines which Webex events are sent to your bot as notifications (and which are filtered out). To keep things simple, my bot is only notified when users send a message that specifically mentions it in a Webex Teams Room:

Cisco ChatOps, Cisco Exam Prep, Cisco Career, Cisco Skills, Cisco Jobs, Cisco Preparation, Cisco Guides, Cisco Preparation Exam

Webex has a nice, convenient tag for this: me uses the authorization token from the request to determine the identity of the user making that request (in this case, our bot), and applies that identity wherever it sees me referenced.

Alternatively, you can set a filter that only triggers notifications for direct messages to your bot, as opposed to mentions in Webex rooms. Since the goal of this post is to broaden visibility into the various processes, these examples show interactions in a Webex Teams Room, however, both are equally viable options.

When you send your POST request, Webex will respond with a body that contains an ID for your Webhook. While you can use the Webex API to GET a list of your Webhooks, it might be a good idea to hold onto this, in case you want to quickly update or delete this Webhook in the future. The Postman collection linked above stores the most recently created Webhook ID in an active_webhook environment variable automatically, which then powers the DELETE call in that collection.

Cisco ChatOps, Cisco Exam Prep, Cisco Career, Cisco Skills, Cisco Jobs, Cisco Preparation, Cisco Guides, Cisco Preparation Exam

How to create your bot server


For simple use cases, you may want to use the Webex Node Bot Framework, which is great for quick implementation. In order to get more familiar with the different components involved in this series, we’ll start from scratch, diving into the step that powers your Webex bot.

Getting Started with Express

Let’s set up a web server that can listen for POST requests from the Webex Webhook that we’ll create in a minute. This doesn’t have to be complicated for now, just something to demonstrate that we’re able to receive requests. For simplicity, we can use the ExpressJS generator, but you can use any web framework or technology that you like.

$ npm i -g express-generator
$ cd where/you/want/your/project
$ express

Since my IDE handles JavaScript Modules a lot better than it handles require statements, I opted to go with a more modern approach for my dependency management. This is totally optional and has no bearing on how you set up your code. However, if you want to follow the code snippets as I’ve laid them out, you’ll want to do the same. The first step is to add the following key/value pair to your package.json file, anywhere in the root of the JSON object:

"type": "module",

A lot of the boilerplate code can be stripped out if you like – we won’t need a favicon, a public/ folder, or a users route handler. Here’s what my code looked like after I stripped a lot of the simple stuff out:

// in app.js

// notice that I changed the require statements to use JS modules import statements
import express from 'express';
import logger from 'morgan';
import indexRouter from './routes/index.js';

const app = express();
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));

app.use('/', indexRouter);

// boilerplate error code didn’t change
// …

// **be sure to remember to set app as the default export at the end of the file**
export default app;

Since I’m using JS Modules, I also had to change the executed file in an Express app www/bin to www/bin.js, and revise the boilerplate require statements there as well to use import syntax:

// in www/bin.js

/**
* Module dependencies.
*/

import app from '../app.js';
import _debugger from 'debug';
const debug = _debugger('chatops-webhook:server');
import http from 'http';

// nothing else in this file needed to change

Adding a Route Handler

That takes care of the majority of the boilerplate. At this point, I only have four files in my codebase, despite how many Express gives me out of the box:

◉ app.js
◉ package.json
◉ bin/www.js
◉ routes/index.js

We’ll want to add a route handler that lets us know when we’ve received a POST request from our Webex Webhook. It can be a simple function that prints the request body to the application console – nothing complicated, just a few lines of code:

// in routes/index.js

import express from 'express'

const router = express.Router();

router.post('/', async function(req, res) {
  console.log(`Received a POST`, req.body);
  res.statusCode = 201;
  res.end();
});

export default router;

Give it a try


You now have all of the important components for receiving message notifications from Webex:

◉ A bot to act as an identity for your Webex interactions
◉ If applicable, a network tunnel to expose your local web service to the public internet
◉ A Webhook set up by your bot to receive Webex notifications
◉ A web service to receive Webex notifications on a POST endpoint

Let’s test it out! To keep things simple for now, create a new room in Webex Teams and add your bot as a member. Next, start typing your message, mentioning your Bot (you can use the @ symbol or type its name) as part of the text. When you hit enter, after a brief pause, you should see a request come through to your running web service, which should log the POST body that it received in its console output:

Cisco ChatOps, Cisco Exam Prep, Cisco Career, Cisco Skills, Cisco Jobs, Cisco Preparation, Cisco Guides, Cisco Preparation Exam

Congratulations, you’ve just set up your very own Webex bot!

What’s next


As promised, our next post will walk through the extremely important aspect of securing our bot. We’ll make sure that only Webex can access it and only authorized users can trigger automation. After that, we’ll move on to new and exciting ways that you can automate everyday workflows right from a Webex Teams Room!

Learn, train, and certify in Cisco Collaboration

As you make your way through this ChatOps series, consider validating your skills with a Cisco Certification.

The 300-835 CLAUTO: Automating and Programming Cisco Collaboration Solutions is a 90-minute exam that counts toward three certifications — the CCNP Collaboration, Cisco Certified DevNet Professional, and Cisco Certified DevNet Specialist – Collaboration Automation and Programmability certifications. Check out the CLAUTO exam topics, and you’ll find that 25% of the exam covers Cloud Collaboration technologies. Before we meet again, take some time to browse through the free CLAUTO Study Materials available on the Cisco Learning Network, which will help you solidify today’s ChatOps focus on building your first Webex bot.

Source: cisco.com