This is the multi-page printable view of this section. Click here to print.

Return to the regular view of this page.

Design

A secure solution begins with a good design! Much of the foundation for assessing whether a solution is secure comes from the design phase, where important trade-offs between cost, benefit, and risk must be made.

The articles you find under the topic design on this page will focus on the design process. Although this process may include much more than we have listed, we cover the essentials such as thorough documentation of what is to be built, critical clarifications, and the need for context.

1 - Security Requirements

How can one build security into a solution if there are no well-defined security requirements?

Some requirements are implicit, such as the use of HTTPS/TLS, while others will be explicit and defined by customers or third parties. Even if the customer has no specific requirements, it is still important for the delivery team to create a list of requirements to ensure that the project’s framework is documented.

Most projects must adhere to various requirements from Bouvet, the customer, and external parties. All development teams must have control over the requirements that apply to the delivery:

  • From Bouvet (where applicable)
  • From the customer
  • Legal requirements

Legal requirements can include general requirements related to privacy, but many industries operate with more specific regulations that impose additional requirements.

In many cases, it is clear to both Bouvet and the customer what applies, but it is important that the team verifies this before starting to develop the solution to avoid costly and time-consuming surprises. Regardless of what is defined and where, the team should document the requirements they adhere to so that this information is preserved for the future.

Basic requirements

If no other security requirements have been defined, the security checklist can be a good starting point. It covers the major elements and can be completed by most teams without outside assistance. By using this checklist, the team gets an overview of the delivery status, including potential weaknesses and threats.

If the delivery requires a more thorough checklist, OWASPs Application Verification Standard (ASVS) might be a good alternative. This is a more comprehensive checklist that offers three levels of testing:

  • Level 1: Black box - all testing is done against the running system
  • Level 2: Everything from level 1, with additional checks targeting process, technology and the implementation.
  • Level 3: Thorough assessment covering all previous checks, as well as more detailed testing of the environment, architecture, and more.

Security requirements for AI systems

If the solution includes, or depends on, artificial intelligence (AI), additional requirements are needed beyond standard security requirements. AI systems introduce their own risk dimensions and these should be handled explicitly at the requirements level.

Security requirements for AI systems should cover:

  • Security: What model behavior is acceptable, and how should the system respond to anomalies? How is the system protected against misuse or manipulation?
  • Privacy and data use: What data does the AI system use for training or inference? How is personal data handled, and how do you ensure the system is not used for unintended purposes?
  • Monitoring and misuse: How should the system be monitored for abnormal behavior? What are acceptable use cases, and how is misuse detected?

For detailed implementation guidance, see Using Artificial Intelligence.

More Information

2 - Network Concepts

Network is a fundamental component in everything we create, and it is important to have a basic understanding of how it works and how it can be exploited by others.

Correct network configuration matters in cloud, hybrid and on-prem alike. This page is meant as a short reference for secure network practice in project work.

Zero trust architecture

Zero trust means not blindly trusting internal or external traffic. Use the principle as your default: verify explicitly, grant as little access as possible, and assume compromise.

Minimum overview

Important

Keep track of which IP addresses and ports you expose, and which services are listening on those ports. Check firewall rules, look in the logs and scan your own systems with nmap.

Maintain an up-to-date overview of:

  • exposed IP addresses, ports and protocols
  • who can reach which services
  • why the exposure is necessary (the business need)
  • which rules are temporary, and when they should be removed

Network scanning

Scan regularly to confirm actual exposure. nmap is an established FOSS tool for discovering open ports and services.

Warning

The use of scanner tools such as nmap must always be cleared with the owners of the infrastructure and network. If you sit in a Bouvet office and scan a customer’s Azure environment, you can easily trigger alarms at both Bouvet and the customer, as well as at the ISP.

Isolating services

Important

Use a firewall to limit traffic within systems and between systems and the Internet. Use an allowlist where possible. Filter traffic at the application layer if necessary.

Practical ground rules:

  • deny by default on both inbound and outbound traffic
  • open only the necessary ports, protocols and known sources
  • avoid “Any” in rules
  • segment the network between functions and environments
  • use private endpoints or VPN where possible
  • place public services behind relevant security layers (for example WAF or API gateway)

AI services and network control

For AI solutions, your operating model should be evaluated against requirements for ingress and egress control.

  • AI in your own tenant (for example in Azure) usually gives better control over network boundaries, private endpoints, logging, and which systems can send data to and from the service.
  • AI as pure SaaS can provide faster startup, but often less control over network flows, allowed destinations, and traffic boundaries.

Minimum checks for both models:

  • which data can be sent in (ingress), and who can send it
  • which destinations data can be sent to (egress)
  • how traffic is logged, monitored, and blocked when anomalies occur
  • how privacy, data flow, and data residency/geography requirements are documented

Configuration

Network configuration should be automated as far as possible, preferably through CI/CD and infrastructure as code.

  • limit who can change network rules directly
  • use JIT access where possible
  • version the rules in source control
  • scan for deviations from the desired configuration and alert on unknown rules
  • document manual exceptions and put a time limit on them

More Information

3 - Segregation of Environments

Development projects use different environments for various purposes, such as testing deployments in a dedicated dev environment, exposing the test environment to product owners and other key personnel, and the production environment to end users. To avoid incidents in one environment affecting another, we must segregate them at a level that makes sense for the team and the context in which we work.

When we build solutions, we often set up multiple environments, typically for dev, test, and prod, so that we can develop while the product owner tests new functionality and end users use the system in prod. It is important to distinguish between these environments to avoid situations where changes in one environment affect the use of another.

When designing a new solution, we must consider how to separate the environments. For cloud services, a common approach is to use different subscriptions per environment where possible. One subscription cannot affect another unless explicitly configured, but there are other possibilities as well.

Common Segregation Patterns

  • Separate subscriptions per environment:
    • Natural separation unless explicitly defined access
    • More overhead with managing multiple subscriptions
  • Use of separate resource groups:
    • Simplified administration
    • Resource groups share some limitations and access at the subscription level
  • Separate virtual networks:
    • Segregation at the network level
    • Often requires more admin to ensure there is an actual separation

There are other approaches to this as well, but regardless of the solution the team chooses, it is important to consider the overall cost/benefit against the requirements to be met.

Segregation for AI systems

For solutions that include artificial intelligence or machine learning, infrastructure segregation alone is not always enough. Teams should also consciously separate data, models, and rollout practices across environments.

Separation of training, evaluation, and production data

Data used for training, evaluation, and production should be clearly separated. This reduces the risk of validating models on the wrong basis or allowing test and development activity to affect production-adjacent data.

Separation of model versions per environment

Models, weights, and related configuration should be versioned and clearly tied to the right environment. The production model should not be overwritten by experimentation in dev or test.

Gradual rollout of changes

When introducing new models or major changes, teams should consider mechanisms such as feature flags, controlled rollout, or other techniques that allow limited validation before full production rollout.

More Information

4 - Authentication and Authorization

Authentication and authorization check respectively who you are and what you are allowed to do. These are important concepts that must be correctly implemented to ensure the security of a solution.

Authentication and authorization are crucial in all development projects. In short, authentication is about validating that a user represents the identity they claim to represent, typically by checking a username and corresponding password. Authorization is about checking that the user is allowed to do what they are trying to do. These are often abbreviated to authn for authentication and authz for authorization.

Authentication

When validating a user, the most important thing is to not create your own authentication solution! Ensuring that such solutions are actually secure is a huge task, and one should instead use established solutions for this!

Single sign-on is a common solution used to avoid having individual applications handling usernames and passwords in corporate environments. The user authenticates via a central platform or the operating system; every application the user opens will then run in the context of that session so that the users avoid manual logins. The user experience is streamlined as a result, and the users are ’trained’ to not having to log on. Any attempts to phish credentials will then appear as out of the ordinary and suspicious.

Common approaches for handling authentication can be the use of third-party services or protocols that handle authentication against the customer’s AD/Entra. In many cases, we want to use Single Sign-On (SSO) to avoid the user having to enter username and password, especially for internal business applications.

Common solutions for handling login are to use libraries that take care of the entire flow, such as Microsoft.Identity.Web. Other alternatives can be the use of:

  • SAML – An XML-based solution primarily used for Single Sign-On and authorization.
  • OAuth 2.0 – An authorization solution in which an identity provider (IDP) issues access tokens that are then checked and handled by OAuth.
  • OpenID Connect (OIDC) – An authentication layer on top of OAuth that enables retrieval of user and session information from the IDP.
  • Kerberos – An authentication protocol widely used in operating systems.
  • LDAP – An authentication and authorization solution used with various directory services, such as Active Directory.

It is important to understand the needs of the solution and which authentication methods are available and possibly desirable.

Authorization

The distinction between authentication and authorization is that authentication confirms who you are, while authorization checks that you are allowed to perform an action.

Similar to authentication, there are several approaches to how authorization is handled, and one needs to understand the best practices for the language and framework used.

There are still some main principles that should always be brought into the development process:

Default access should always be no access

This is also known as default deny or principle of least privilege, and is used to ensure that, for example, an unauthorized user does not have access to anything beyond what is explicitly allowed.

Authorization should always be checked

If a user attempts to perform an action, it should always be checked whether the user actually has access to this. Remember that this check must be made against the authoritative source for access rights, and never against data that the user can manipulate!

Users should always be given the least possible access

Also known as the principle of least privilege. A user should never be given more access than is needed to perform a specific task. This is done to reduce the attack surface if a user is compromised, so that the scope of damage can be limited.

Role-Based User Access

Using roles, role based access control (RBAC), is a common approach to granting user access. The goal is to define standard roles for an application so that access can be based on these. A common way to handle this, for example, with Entra or AD is to have:

  • access groups with all users. The access groups are added as members in
  • role groups, which are given access in the application.

This provides a better overview of who has access to what compared to users with individual access.

AI and agent access

For solutions with AI agents, it is not enough to control end-user access alone. The agent itself often acts as a separate identity with access to models, data, APIs, and tools. These access rights should be treated as high-risk when they are too broad.

Practical principles:

  • use a dedicated service identity for the agent; do not reuse user or admin accounts
  • apply least privilege per tool (tool access), so the agent can only call functions it actually needs
  • separate read, write, and administrative operations
  • limit access per environment (dev/test/prod) and per dataset or service
  • use time-limited or conditional access where possible

When an agent gets access to external tools or APIs, you should also control which commands, endpoints, and data operations are allowed. This reduces the risk that mistakes, misuse, or compromise have a large operational impact.

For MCP-based integrations (Model Context Protocol), the same principles apply, with extra requirements for clear boundaries:

  • each MCP server should have clear ownership and its own identity/service account
  • tools exposed through MCP should be explicitly scoped and authorized, not given broad, unrestricted access
  • the client should only get access to required MCP servers, and access should be revocable quickly
  • calls to MCP tools should be logged with who/what/why so misuse can be traced

Access management also affects operational risk: broad agent permissions make incidents harder to detect and increase impact. Changes to agent access should therefore be logged and followed up together with normal operational monitoring, see Logging and monitoring.

More Information

5 - Threat Modeling

Threat modeling is an exercise where the goal is to identify threats in and around a solution. This makes it possible to identify and assess risk against the overall security posture of the solution. Based on a threat model, mitigating measures can be identified and implemented to reduce risk.

This is a brief introduction to threat modeling. Methods and tools are mentioned briefly, with links for further reading.

You may have already done simple threat modeling without realizing it. For example, have you ever thought about why the users of the system you’re creating need to log in with a username and password?

When these choices were made, you automatically performed simple threat modeling. You certainly don’t want unauthorized individuals to access data in your system, and you don’t want anyone to see the data transferred between your users and your website.

The whole point of threat modeling is to think like an attacker.

Identifying Threats

There are several ways to identify threats to a system. In practice, the most important thing is to involve the right roles, define what needs protection, and systematically review how the solution could be attacked or misused. Some threats may already be handled, while others require new measures. The process should be repeated when the solution, data flows, or usage patterns change.

A simple workflow is:

  • define the system boundaries and critical assets
  • identify threats and misuse scenarios
  • prioritize risk and decide on measures
  • verify that measures actually work
  • update the model regularly

Method Selection

Threat modeling is more important than which method you choose. Pick an approach your team can use consistently.

Threat modeling for AI systems

For solutions with AI, looking at application code alone is often not enough. The threat model should also cover the model itself, prompt flow, data sources, evaluation basis, and how the system is used in operations.

Typical questions include:

  • which data enters the model, and who controls it?
  • which parts of the context are trusted, and which come from users or external sources?
  • what is the worst-case outcome if the model gives incorrect answers or is manipulated?
  • which security mechanisms exist around model calls, logging, access, and monitoring?

Some AI-specific threats that should be assessed explicitly:

  • Prompt injection: Input or documents attempt to override instructions or make the model perform unintended behavior.
  • Data poisoning: Training data, reference data, or evaluation data is manipulated so the model learns the wrong things or produces weaker decision support.
  • Model misuse: The system is used for purposes it was not designed for, or in contexts where error margins are unacceptable.
  • Leakage: Sensitive information leaks through prompts, outputs, logs, weight files, or surrounding integrations.

For AI solutions, it is also important to describe misuse scenarios, not only direct attacks. A model can be technically available and functioning, but still represent high risk if it is used for decision support without sufficient human control points.

From threat model to requirements and follow-up

A threat model has limited value if it is created once and then put away. Findings should be used to define concrete security requirements, testing needs, and operational controls.

For example, an identified threat can lead to a need for:

  • stronger authentication or access control
  • additional logging and alerting
  • validation of input and output
  • explicit limitations on use of a model or agent
  • regular review of datasets, prompt flows, or integrations

For AI systems, the threat model should also be used when assessing changes to models, data sources, prompt templates, evaluation sets, and monitoring. Changes here can introduce new threats even if application code is unchanged.

The threat model must be versioned and kept up to date. Once threats have been identified, countermeasures must be described, and their effectiveness assessed. A common approach is to give the threat a value indicating severity, for example, 1-10 where 10 is the worst. Countermeasures are assessed similarly but with the opposite scale where 1 has little effect and 10 (or up to criticality) has the highest effect. The sum of these gives a residual risk that indicates the remaining risk:

Identified Threats          Criticality     Countermeasures Residual Risk
Threat  1                   8               8               0
Threat  2                   2               0               2
Threat  3                   4               3               1
Total                       14              11              3

When a risk is identified, it is important that the risk owner is involved, as they are responsible for ensuring that the project delivers quality in line with expectations and requirements.

It is important that countermeasures are validated for them to be effective. The threat model should be reviewed regularly to see how the situation has changed, and if the total criticality or residual risk exceeds a threshold, consider measures to reduce them.

For systems in active operation, the threat model should also be used when deciding which events to log, what to monitor, and which deviations should trigger alerts. This is especially important for AI systems, where misuse, degradation, or unexpected model behavior can develop gradually over time.

More Information

Tools

  • Microsoft Threat Modeling Tool gives you a kick-start by describing common threats for various services. This tool is especially useful if you operate in Microsoft Azure.
  • OWASP Threat Dragon is a similar open-source tool worth checking out.
  • Draw.io with this package drawio-threatmodeling is a tool available both on the web and in common clients.
  • OWASP pytm is an open-source framework for threat modeling as code in Python, useful for teams that want to version models together with source code.

Cards and Workshop Aids

  • LINDDUN GO is an accessible card-based method for privacy threats, with a free PDF deck and digital version.
  • OWASP Cornucopia is an established, free card deck for deriving security requirements in development projects.
  • Elevation of Privilege (EoP) is a classic threat modeling card deck by Adam Shostack, available as open resources.
  • The Security Cards from the University of Washington is a practical brainstorming set with printable cards.

Courses and Lectures

Other Sources

6 - System diagrams and drawings

It’s important to have a good foundation when building quality solutions, and drawings and diagrams showing the infrastructure, data flow, networks, and access control are crucial elements. Without this information, it is difficult to validate if the implementation matches the intended design.

When designing a solution, it’s essential to have clear and comprehensive drawings and diagrams that show the planned design. This is already done by many development teams without necessarily being a formal requirement, but it’s still worth mentioning here.

System diagrams should provide enough information to:

  • Validate that the implementation matches the design
  • Use them for threat modeling, pentesting, or similar activities
  • Be used by those managing the solution to get a good overview of components and data flow
  • Be used by the delivery team for onboarding new colleagues or handover to other teams

Although there is a lot that can be documented here, we focus on the most important aspects:

  • High-level system sketch with the main logical components
  • Detailed network diagram with resources, services, and networks
  • Data flow diagram showing how data flows between components in the solution
  • IAM diagram showing identities, accesses, and roles and where they are sourced from
  • Important dependencies – overview of other systems, services, resources, on-prem/cloud

Use of AI components

If the solution includes artificial intelligence or machine learning models, these should be explicitly documented in the system documentation:

  • In the data flow diagram: Show where training data and inference input come from, and how results continue through the system
  • In the network diagram: Document where the model runs (cloud API, edge device, on-prem server) and related network connectivity
  • In the dependencies list: Include model ownership, versioning, and where updates happen
  • In the IAM diagram: Show who can deploy, update, or monitor the model

Without this information, it is difficult to maintain a clear overview of risk, data flow, and compliance around AI components.

Examples

Below are examples of the points listed above. The diagrams you produce do not need to be identical; the most important thing is that they contain enough information to be used for their intended purpose and are understandable to the team.

To easily get started with designing diagrams and sketches, tools like Miro or Draw.io can be used. The latter is free and offers storage of drawings in the browser, locally on the machine as XML, and much more.

Keep in mind:

The diagrams do not need to be perfect or contain every conceivable detail. Assess the need and work on gradual improvements over time.

High-level System Diagram

This diagram should be a high-level introduction to the solution, showing all the major components and interactions between them.

High-level system sketch The frontend talks to the backend. The backend reads from two databases, On-prem SQL and Azure SQL, and exchanges data with the company data platform, which is a dependency outside the solution. The backend also feeds Power BI Reports, which additionally reads from the data platform. Frontend Backend Power BI Reports Company data platform (dependency) On-prem SQL Azure SQL
Example of a high-level system sketch. It shows only the largest components and how they relate to each other. Dependencies outside the solution are dashed, so it is easy to see what the team controls itself.

Network Diagram

The goal of the network diagram is to show the network topology, with all the various virtual networks, subnets and resources or servers and firewall openings between them. A good network diagram visualizes the data flow between points for everyone to see, not just developers.

Network diagram for a development environment An internal user reaches an Azure Firewall over HTTPS 443. The firewall passes traffic on to the Frontend-dev subnet (10.0.0.0/27), which holds an app service and a key vault, and to the Dev workspace reporting area with two reports. Both continue to an Azure WAF, which lets traffic into the Backend-dev subnet (10.0.0.32/27). That subnet holds two app services and an ingress factory, all of which use the same SQL database and key vault. The ingress factory pulls data from the datalake-somedata-prod01 data lake in the company data platform, which sits outside the environment. Internal user HTTPS 443 Azure Firewall Frontend-dev 10.0.0.0/27 frontend-dev-appsvc 10.0.0.2 frontend-dev-keyvault Dev workspace Report 1 Report 2 HTTPS 443 HTTPS 443 Azure WAF HTTPS 443 Backend-dev 10.0.0.32/27 backend-dev-appsvc01 10.0.0.36 backend-dev-appsvc02 10.0.0.37 ingress-factory-dev-01 10.0.0.43 backend-dev-sql01 10.0.0.40 backend-dev-keyvault 10.0.0.50 HTTPS 443 Company data platform (dependency) datalake-somedata-prod01 10.10.10.10
Example network diagram for a development environment. Every subnet is labelled with its address range, every resource has its own address, and the arrows show the direction of traffic and which port is open. The reporting workspace reaches the backend API through the same WAF as the frontend. The dashed box is a dependency outside the team's own environment.
Keep in mind:

Network diagrams should be created for all environments, providing necessary information on all resources in all environments, as well as connections between them.

Data Flow Diagram

The data flow diagram shows the data flow of the solution. This should include all direct dependencies not part of the project, so that it is possible to understand where data originates and all the nodes it interacts with.

Data flow diagram for a development environment The data comes from two sources: the production-sql-01 database on separate hardware, where three views are in use, and the datalake-somedata-prod01 container in the company data platform. Both are loaded by ingest-factory-dev-01, which runs four pipelines. From there the data is written to the CurrentData and HistoricalData schemas in backend-dev-sql01. HistoricalData is read by Report01 and Report02 in dev-workspace, CurrentData by Report03. Sources production-sql-01 on-prem Views used v_get_all_production_data v_get_production_summary_12mth v_get_products_info Company data platform (dependency) Container datalake-somedata-prod01/ production-data-container Ingestion ingest-factory-dev-01 Pipelines Copy_production_data Copies production data Update_production_summary Updates the summary Refresh_products_info Updates the product index Copy_datalake_data Reads from the data lake Storage backend-dev-sql01 Schemas CurrentData HistoricalData Reporting dev-workspace Reports Report01 Report02 Report03
Example of a data flow diagram. It follows the data from source to report and names the views, pipelines and schemas actually in use at each step. That naming is what makes the diagram useful when a discrepancy has to be traced back.

IAM Diagram

An IAM-diagram describes where users originate, and the roles and permissions assigned to users, services and devices on the various resources.

IAM diagram for a development environment On the left are the identities in Entra ID: a service principal for Azure DevOps, the managed identities of Backend and ingest-factory, a developer and an application user. On the right is Dev Subscription with the resources backend-dev-sql01 and dev-keyvault, the resource groups Backend and Frontend, and production-sql-01, which runs on separate hardware outside the subscription. The service principal is Owner on the subscription and the developer is Contributor. The developer is also Key Vault Secrets Officer on dev-keyvault and SQL Admin on both backend-dev-sql01 and production-sql-01. The managed identities are Key Vault Secrets User on dev-keyvault and db_datareader on backend-dev-sql01. The application user holds a user role on Frontend. Entra ID Users and service principals Dev Subscription Subscription Owner Contributor SQL Admin db_datareader Key Vault Secrets Officer Key Vault Secrets User User role SQL Admin Service principal Azure DevOps Managed identities Backend, ingest-factory Developer Application user backend-dev-sql01 Azure SQL dev-keyvault Key Vault Backend Resource group Frontend Resource group production-sql-01 On-prem, outside the subscription
Example of an IAM diagram. Identities are on the left, scopes on the right, and every arrow is one role assignment labelled with the role name. Arrows ending on the edge of the subscription box are assigned at subscription level and inherit down to everything inside it; arrows ending on a resource apply to that resource only. The point is that no access goes undocumented.

Dependencies

This can also be drawn, but often a simple list is enough. This should contain all direct dependencies of the solution being developed, with a brief summary containing descriptions of what the team depend on.

  • On-prem database server production-sql-01
    • Uses three views maintained by the team
    • Data is imported via ADF
  • Company’s data platform, datalake datalake-somedata-prod01
    • Consumes datasets in the container production-data-container
    • Lineage is visible in Purview
    • Uses only datasets approved by the data owner

More Information