Category: Networking and firewalls (Page 2 of 2)

Using architectural best practices – Principles of Modern Architecture

Through years of research and experience, vendors such as Microsoft have collected a set of best practices that provide a solid framework for good architecture when followed.

With the business requirements in mind, we can perform a Failure Model Analysis (FMA). An FMA is a process for identifying common types of failures and where they might appear in our application.

From the FMA, we can then start to create a redundancy and scalability plan; designing with scalability in mind helps build a resilient solution and a performant one, as technologies that allow us to scale also protect us from failure.

A load balancer is a powerful tool for achieving scale and resilience. This allows us to build multiple service copies and then distribute the load between them, with unhealthy nodes being automatically removed.

Consider the cost implications of any choices. As mentioned previously, we need to balance the cost of downtime versus the cost of providing protection. This, in turn, may impact decisions between the use of Infrastructure-as-a-Service (IaaS) components such as VMs or Platform-as-a-Service (PaaS) technologies such as web apps, functions, and containers. Using VMs in our solution means we must build out load balancing farms manually, which are challenging to scale, and demand that components such as load balancers be explicitly included. Opting for managed services such as Azure Web Apps or Azure Functions can be cheaper and far more dynamic, with load-balancing and auto-scaling technologies built in.

Data needs to be managed effectively, and there are multiple options for providing resilience and backup. Replication strategies involving geographically dispersed copies provide the best RPO as the data is always consistent, but this comes at a financial cost.

For less critical data or information that does not change often, daily backup tools that are cheaper may suffice, but these require manual intervention in the event of a failure.

A well-defined set of requirements and adherence to best practices will help design a robust solution, but regular testing should also be performed to ensure the correct choices have been made.

Testing and disaster recovery plans

A good architecture defines a blueprint for your solution, but it is only theory until it is built; therefore, solutions need to be tested to validate our design choices.

Work through the identified areas of concern and then forcefully attempt to break them. Document and run through simulations that trigger the danger points we are trying to protect.

Perform failover and failback tests to ensure that the application behaves as it should, and that data loss is within allowable tolerances.

Build test probes and monitoring systems to continually check for possible issues and to alert you to failed components so that these can be further investigated.

Always prepare for the worst—create a disaster recovery plan to detail how you would recover from complete system failure or loss, and then regularly run through that plan to ensure its integrity.

We have seen how a well-architected solution, combined with robust testing and detailed recovery plans, will prepare you for the worst outcomes. Next, we will look at a closely related aspect of design—performance.

Patching – Principles of Modern Architecture

When working with virtual machines (VMs), you are responsible for managing the operating system that runs on them, and attackers can seek to exploit known vulnerabilities in that code.

Regular and timely patching and security updates with anti-virus and anti-malware agents are the best line of defense against this. Therefore, your solution design needs to include processes and tools for checking, testing, and applying updates.

Of course, it is not just third-party code operating systems that are susceptible; your application code is vulnerable too.

Application code

Most cloud services run custom code, in the form of web apps or backend application programming interface (API) services. Hackers often look for programming errors that can open holes in the application. As with other forms of protection, multiple options can be included in your architecture, and some are listed here:

  • Coding techniques: Breaking code into smaller, individually deployed components and employing good development practices such as Test-Driven Design (TDD), paired programming, or code reviews can help ensure code is cleaner and error-free.
  • Code scanners: Code can be scanned before deployment to check for known security problems, either accidental or malicious, as part of a deployment pipeline.
  • Web application firewalls (WAFs): Unlike layer 3 or 4 firewalls that block access based on Internet Protocol (IP) or protocol, WAFs inspect network packet contents, looking for arbitrary code or common exploits such as SQL injection attacks.

Application-level security controls help protect you against code-level exploits; however, new vulnerabilities are uncovered daily, so you still need to prepare for the eventuality of a hacker gaining data access.

Data encryption

If the data you hold is sensitive or valuable, you should plan for the eventuality that your security controls are bypassed by making that data impossible to read. Encryption will achieve this; however, there are multiple levels you can apply. Each level makes your information more secure, but at the cost of performance.

Encryption strategies should be planned carefully—standard encryption at rest is lightweight but provides a basic protection level and should be used for all data as standard.

For more sensitive data such as credit card numbers, personal details, passwords, and so on, additional levels can be applied. Examples of how and where we can apply controls are given here:

  • Databases: Many databases now support Transparent Data Encryption (TDE), whereby the data is encrypted. Applied by the database engine itself, consuming applications are unaware and therefore do not need to be modified.
  • Database fields: Some databases provide field-level encryption that can be applied by the database engine itself or via client software. Again, this can be transparent from a code point of view but may involve additional client software.
  • Applications: Applications themselves can be built to encrypt and decrypt data before it is even sent to the database. Thus, the database is unaware of the encryption, but the client must be built specifically to perform this.
  • Transport: Data can be encrypted when transferring between application components. HyperText Transfer Protocol Secure (HTTPS) using Secure Sockets Layer (SSL) certificates is the most commonly known for end-user websites, but communications between elements such as APIs should also be protected. Other transport layer encryption is also available—for example, SQL database connections or file shares.

Data can be encrypted using either string keys or, preferably, certificates. When using certificates, many cloud vendors, including Azure, offer either managed or customer-supplied keys. With managed keys, the cloud vendors generate, store, and rotate the certificates for you, whereas with customer-supplied keys, you are responsible for obtaining and managing them.

Keys, secrets, and certificates should always be stored in a suitably secure container such as a key vault, with access explicitly granted to the users or services that need them, and access being logged.

As with other security concerns, the variability and ranges of choices mean that you must carefully plan your encryption techniques.

On their own, each control can provide some protection; however, to give your solution the best defense, you need to implement multiple tactics.

How do they hack? – Principles of Modern Architecture

There are, of course, many ways hackers can gain access to your systems, but once you have identified the reason why an attacker may want to hack you, you can at least narrow down the potential methods. The following are some of the more common ones:

  • Researching login credentials: Although the simplest method, this is perhaps one of the most common. If an attacker can get your login details, they can do a lot of damage very quickly. Details can be captured either by researching a user’s social and public profiles, to guess the password or find answers to your security questions.
  • Phishing: Another way of capturing your credentials; you may receive an email notifying you that your account has been locked, with a link to a fake website. The website looks like what you are expecting, and when you enter your details, it merely captures them.
  • Email: Rather than capturing login details, some emails may contain malicious code in the form of an attachment or a link to a compromised site. The purpose is to infect your computer with a virus, Trojan, or similar. The payload could be a keylogger to capture keystrokes (that is, login details) or spread and use more sophisticated attacks to access other systems.
  • Website vulnerabilities: Poorly written code can lead to all sorts of entry points. SQL injection attacks whereby Transact-SQL (T-SQL) statements are posted within a form can update, add, or delete data if the backend is not written to protect against this type of attack. Cross-site scripts that run on the hacker’s website but access the backend on yours can override form posts, and so on.
  • Distributed Denial of Service (DDoS): A DDoS attack seeks to overwhelm your servers and endpoints by flooding them with requests—this can either bring down your applications or potentially trigger other exploits that grant complete access.
  • Vulnerability exploits: Third-party applications and operating systems can also have vulnerable code that hackers seek to exploit in many different ways, from triggering remote execution scripts to taking complete control of the affected system.

Of course, there are many more, but understanding the main reasons why and how hackers hack is the first step in your defense. With this knowledge, we can start to define and plan our strategy.

Defining your strategy

Once we have identified what we need to protect, including any prioritization based on your platform’s characteristics, we can start to define a set of rules that set out how we protect ourselves.

Based on your requirements, which may be solution- and business-led, the strategy will state which elements need protecting, and how. For example, you may have a rule that states all data must be encrypted at rest, or that all logging is monitored and captured.

There are several industry compliance standards, such as ISO27001, National Institute of Standards and Technology (NIST), and the Payment Card Industry Data Security Standard (PCI DSS). These can either form the basis of your internal policies or be used as a reference; however, depending on your business’s nature, you may be required to align with one or more of them.

Information

ISO is the acronym for International Organization for Standardization, which is an international standard-setting body with representatives from multiple other standards organizations.

We can now consider which technologies we will use to implement the various policies; next, we will look at some of the more common ones.

Architecting for security – Principles of Modern Architecture

In the previous chapter, we looked at why architecture is important, what it seeks to achieve, and how it has changed over time. Understanding how we got to where we are today helps us in our role and provides a solid framework for our designs.

This chapter will look at how we architect systems in general to understand the high-level requirements and potential methods. Split into pillars, we will examine different aspects of each; however, as we will see, they are all interlinked and have some element of dependency on each other.

We will start by looking at security, perhaps one of the essential aspects of architecture, and understand how access to systems is gained and how we prevent it.

Next, we’ll investigate resilience, which is closely related to performance. By understanding the principles of these subjects, we can ensure our designs produce stable and performant applications.

Deployment mechanisms have become far more sophisticated in recent years, and we’ll learn how our decisions around how we build platforms have become entwined with the systems themselves.

Finally, we will see how a well-designed solution must include a suite of monitoring, alerting, and analytics to support the other pillars.

With this in mind, throughout this chapter, we will cover the following topics:

  • Architecting for security
  • Architecting for resilience and business continuity
  • Architecting for performance
  • Architecting for deployment
  • Architecting for monitoring and operations

Architecting for security

As technology has advanced, the solutions we build have become more powerful, flexible, and complex. Our applications’ flexibility and dynamic nature enable a business to leverage data and intelligence at a level previously unknown. The cloud is often touted by many vendors as having near unlimited capacity and processing power that is accessible by anyone.

But power comes at a cost, because it’s not just businesses who wish to leverage the potential of the cloud—hackers also have access to that tooling. Therefore, the architect of any system must keep security at the core of any design they produce.

Knowing the enemy

The first step in ensuring security is to understand the hacker mindset or, at the very least, to think about what they wish to accomplish—why do hackers hack?

Of course, there are lots of reasons, but we’ll state the obvious one—because they can! Some people see hacking a system as a challenge. Because of this, their attack vector could be any security hole they can exploit, even if this didn’t result in any valuable benefit.

The most dangerous attackers are the ones who wish to profit or cause damage from their actions, either directly by selling/releasing private data or by holding their victim to ransom by encrypting data and demanding money to release it.

Some wish to simply disrupt by bringing a system down—depending on the nature of the solution in question, the damage this causes can be reputational or financial.

All of these scenarios highlight some interesting points. The first is that when designing, you need to consider all areas of your solutions that might be vulnerable—authorization, data, application access points, network traffic, and so on.

The second is that, depending on your solution, you can prioritize the areas that would cause you the most damage. For example, if you are a high-volume internet retailer, uptime may be your primary concern, and you might therefore concentrate on preventing attacks that could overload your system. If data is your most valuable asset, then you should think about ways to ensure it cannot be accessed, either by preventing an intrusion in the first place or protecting information if it is accessed via encryption or obfuscation.

Once we have the why, we need to think about the how.

IaC – Architecture for the Cloud

In Azure, components can be created either in the portal using the graphical user interface (GUI) with PowerShell or by using JSON templates. In other words, you can deploy infrastructure in Azure purely with code.

IaC provides many benefits, such as the ability to define VMs, storage, databases, or any Azure component in a way that promotes reusability, automation, and testing.

Tools such as Azure DevOps provide a central repository for all your code that can be controlled and built upon in an iterative process by multiple engineers. DevOps also builds, tests, and releases your infrastructure using automated pipelines—again, in the same way that modern software is deployed.

The DevOps name embodies the fact that operational infrastructure can now be built using development methodologies and can follow the same Agile principles.

DevSecOps takes this even further and includes codifying security components into release pipelines. Security must be designed and built hand in hand with infrastructure and security at every level, as opposed to merely being a perimeter or gateway device.

Cloud architects must, therefore, be fully conversant with the taxonomy, principles, and benefits of Agile, DevOps, and DevSecOps, incorporating them into working practices and designs.

Microsoft provides a range of tools and components to support your role and provides best-in-class solutions that are reliable, resilient, scalable, and—of course—secure.

As we have seen, architecture in the cloud involves many more areas than you might traditionally have gotten involved in. Hopefully, you will appreciate the reasons why these changes have occurred.

From changes in technology to new ways of working, your role has changed in different ways—although challenging, this can also be very exciting as you become involved across various disciplines and work closely with business users.

Summary

During this chapter, we have defined what we mean by architecture in the context of the AZ-304 exam, which is an important starting point to ensure we agree on what the role entails and precisely what is expected for the Azure certification.

We have walked through a brief history of business computing and how this has changed architecture over the years, from monolithic systems through to the era of personal computing, virtualization, the web, and ultimately to the cloud. We examined how each period changed the responsibilities and design requirements for the solutions built on top.

Finally, we had a brief introduction to modern working practices with IaC and project management methodologies, moving from waterfall to Agile, and how this has also changed how we as architects must think about systems.

In the next chapter, we will explore specific areas of architectural principles, specifically those aligned to the Microsoft Azure Well-Architected Framework.

Moving from Waterfall to Agile projects – Architecture for the Cloud

As we move into the cloud, other new terms around working practices come to the fore. DevOps, DevSecOps, and Agile are becoming ingrained in those responsible for building software and infrastructure.

If you come from a software or a DevOps background, there is a good chance you already understand these concepts, but if not, it helps to understand them.

Waterfall

Traditional waterfall project delivery has distinct phases to manage and control the build. In the past, it has often been considered crucial that much effort goes into planning and designing a solution before any engineering or building work commences.

A typical example is that of building a house. Before a single brick is laid, a complete architectural blueprint is produced. Next, foundations must be put in place, followed by the walls, roof, and interiors. The idea is that should you change your mind halfway through, it would be challenging to change anything. If you decide a house needs to be larger after the roof is built, you would need to tear everything down and start again.

With a waterfall approach, every step must be well planned and agreed at the outset. The software industry developed a bad reputation for delivering projects late and over budget. Businesses soon realized that this was not necessarily because of mismanagement but because it is difficult to articulate a vision for something that does not yet exist and, in many cases, has never existed before.

If we take the building metaphor, houses can be built as they are because, in many cases, they are merely copying elements of another house. Each house has a lot in common—walls, floors, and a roof, and there are set ways of building each of these.

The following diagram shows a typical setup of a waterfall project, with well-defined steps completed in turn:

Figure 1.7 – Typical waterfall process

With software, this is not always the case. We often build new applications to address a need that has never been considered or addressed before. Trying to follow a waterfall approach has led to many failed projects, mainly because it’s impossible to design or even articulate the requirements upfront fully.

Agile

Thus, Agile was born. The concept is to break down a big project into lots of smaller projects that each deliver a particular facet of the entire solution. Each mini-project is called a sprint, and each sprint runs through a complete project life cycle—design, plan, build, test, and review.

The following diagram shows that in many ways, Agile is lots of mini-waterfall projects:

Figure 1.8 – Agile process

Sprints are also short-lived, usually 1 or 2 weeks, but at the end of each one, something is delivered. A waterfall project may last months or years before anything is provided to a customer—thus, there is a high margin for error. A small misunderstanding of a single element along the way results in an end state that does not meet requirements.

A particular tenet of Agile is “fail fast”—it is better to know something is wrong and correct it as soon as possible than have that problem exacerbate over time.

This sprint-led delivery mechanism can only be achieved if solutions are built in a particular manner. The application must be modular, and those modules designed in such a way that they can be easily swapped out or modified in response to changing requirements. An application architect must consider this when designing systems.

At this point, you may be wondering how this relates to the cloud. Agile suits software delivery because solutions can be built in small increments, creating lots of small modules combined into an entire solution. To support this, DevOps tooling provides automated mechanisms that deploy code in a repeatable, consistent manner.

As infrastructure in the cloud is virtualized, deployments can now be scripted and therefore automated—this is known as Infrastructure as Code (IaC).

Understanding infrastructure and platform services – Architecture for the Cloud

One of the big differences between IaaS and PaaS is about how the responsibility of components shifts.

The simplest examples of this are with websites and Structured Query Language (SQL) databases. Before we look at IaaS, let’s consider an on-premise implementation.

When hosted in your own data center, you might have a server running IIS, upon which your website is hosted, and a database server running SQL. In this traditional scenario, you own full responsibility for the hardware, Basic Input/Output System (BIOS) updates, operating system (OS) patching, security updates, resilience, inbound and outbound traffic—often via a centralized firewall—and all physical security.

IaaS

The first step in migrating to cloud might be via a lift-and-shift approach using virtual networks (VNETs) and VMs—again, running IIS and SQL. Because you are running in Microsoft’s data centers, you no longer need to worry about the physical aspects of the underlying hardware.

Microsoft ensures their data centers have all the necessary physical security systems, including personnel, monitoring, and access processes. They also worry about hardware maintenance and BIOS updates, as well as the resilience of the underlying hypervisor layer that all the VMs run on.

You must still, however, maintain the software and operating systems of those VMs. You need to ensure they are patched regularly with the latest security and improvement updates. You must architect your solution to provide application-level resilience, perhaps by building your SQL database as a failover cluster over multiple VMs; similarly, your web application may be load-balanced across a farm of IIS servers.

Microsoft maintains network access in general, through its networking and firewall hardware. However, you are still responsible for configuring certain aspects to ensure only the correct ports are open to valid sources and destinations.

A typical example of this split in responsibility is around access to an application. Microsoft ensures protection around the general Azure infrastructure, but it provides the relevant tools and options to allow you to set which ports are exposed from your platform. Through the use of network security groups (NSGs) and firewall appliances, you define source and destination firewall rules just as you would with a physical firewall device in your data center. If you misconfigure a rule, you’re still open to attack—and that’s your responsibility.

PaaS

As we move toward PaaS, accountability shifts again. With Azure SQL databases and Azure web apps, Microsoft takes full responsibility for ensuring all OS-level patches are applied; it ensures the platforms that run Azure SQL databases and Azure web apps are resilient against hardware failure.

Your focus now moves toward the configuration of these appliances. Again, for many services, this includes setting the appropriate firewalls. However, depending on your corporate governance rules, this needs to be well planned.

By default, communications from a web app to a backend Azure SQL database are over the public network. Although it is, of course, contained within Microsoft’s network, it is technically open. To provide more secure connectivity, Azure provides the option to use service connections—direct communication over its internal backbone—but this needs specifically configuring at the web app, the SQL service, and the VNET level.

As the methods of those who wish to circumvent these systems become increasingly sophisticated, further controls are required. For web applications, the use of Web Application Firewall (WAF) is an essential part of this—as the architect, you must ensure they are included in your designs and configured correctly; they are not included by default.

Important note

Even though Microsoft spends billions of dollars a year on securing the Azure platform, unless you carefully architect your solutions, you are still vulnerable to attack. Making an incorrect assumption about where your responsibility lies leads to designing systems that are exposed—remember, many cloud platforms’ networking is open by default; it has to be, and you need to ensure you fully understand where the lines are drawn.

Throughout this chapter, we have covered how changing technologies have significantly impacted how we design and build solutions; however, so far, the discussion has been around the technical implementation.

As software and infrastructure become closely aligned, teams implementing solutions have started to utilize the same tools as developers, which has changed the way projects are managed.

This doesn’t just affect the day-to-day life of an architect; it has yet another impact on the way we design those solutions as well.

Virtualization – Architecture for the Cloud

As the software that ran on servers started to become more complex and take on more diverse tasks, it began to become clear that having a server that ran internal emails during the day but was unused in the evening and at the weekend was not very efficient.

Conversely, a backup or report-building server might only be used in the evening and not during the day.

One solution to this problem was virtualization, whereby multiple servers—even those with a different underlying operating system—could be run on the same physical hardware. The key was that physical resources such as random-access memory (RAM) and compute could be dynamically reassigned to the virtual servers running on them.

So, in the preceding example, more resources would be given to the email server during core hours, but would then be reduced and given to backup and reporting servers outside of core hours.

Virtualization also enabled better resilience as the software was no longer tied to hardware. It could move across physical servers in response to an underlying problem such as a power cut or a hardware failure. However, to truly leverage this, the software needed to accommodate it and automatically recover if a move caused a momentary communications failure.

From an architectural perspective, the usual issues remained the same—we still used a single user database directory; virtual servers needed to be able to communicate; and we still had the physically secure boundary of a network.

Virtualization technologies presented different capabilities to design around—centrally shared disks rather than dedicated disks communicating over an internal data bus; faster and more efficient communications between physical servers; the ability to detect and respond to a physical server failing, and moving its resources to another physical server that has capacity.

In the following diagram, we see that discrete servers such as databases, file services, and email servers run as separate virtual services, but now they share hardware. However, from a networking point of view, and arguably a software and security point of view, nothing has changed. A large role of the virtualization layer is to abstract away the underlying complexity so that the operating systems and applications they run are entirely unaware:

Figure 1.3 – Virtualization of servers

We will now look at web apps, mobile apps, and application programming interfaces (APIs).

Newer posts »