Using dynamic permissions in an internal developer portal

July 23, 2024

Using dynamic permissions in an internal developer portal

Ready to start?

Today, we want to dive into the ability to create dynamic permissions in Port for both executing and approving self-service actions. This is a powerful feature that lets you deliver permissions that change based on role, status (e.g. on-call), time of day and more, so that the way your internal developer portal is used and accessed matches any policy you wish to implement. And the best part: dynamic permissions are based on a user-friendly interface, and require no coding.

RBAC in internal developer portals

Role-based access control is used for security reasons, but in a portal it is also used to deliver personalized experiences. It allows you to control who sees what in the software catalog and who can perform or approve self-service actions, and this creates abstractions and personalization on top of security, reducing cognitive load.

RBAC also plays a role in when and how permissions are granted. This post is about how to use dynamic permissions in an internal developer portal, making portal functionality even more powerful. 

Why permissions matter more than you think

Permission management is a core capability in an internal developer portal. Let's explore why permissions matter:

  1. Security and compliance: The use of granular permissions decreases the risk of data breaches and ensures regulatory compliance, by allowing only authorized individuals to access sensitive data and perform critical actions.
  2. Personalized experiences: Using permissions customizes access according to each user's roles and responsibilities. The side effect is that users only see what they need in the portal, creating abstractions that reduce the amount of “noise” in the portal. For example, members of a specific team will only see their software assets and their associated dashboards. Only actions relevant to their jobs, such as deploying code, viewing logs, or managing environments, will be available to them, making it easier for users to find the information and tools they need to do their jobs effectively.
  3. Enforcement of company policies: Using permissions you can define and enforce consistent compliance with company policies by incorporating them directly into the workflow rather than maintaining stale wikis that no one looks at. As an example, a policy that requires that only a team lead can deploy a new feature to all-users can become an built-in part of the deployment process, defined and enforced through the use of permissions.

Beyond Static permissions: embracing dynamic permissions

Traditional permissions are static—a user either has access or they don't. However, static permissions may be too rigid for some real-world scenarios. Dynamic permissions, on the other hand, allow access rights to change based on various factors, such as users/teams properties, time of day or even state of a system, and still be compliant with your policies. 

Here are two examples:

  • Static permissions: Team A members always have the right to deploy Service A to production. If Service A is no longer owned by Team A, an admin would have to manually update the permissions for the service, a time-consuming and error-prone process.
  • Dynamic permissions: A member can only deploy to production services that belong to the business unit they are in, with the prerequisite that they have completed mandatory security training.

To enable this level of granularity, context is needed. This means detailed information about:

  • users (e.g. their roles, teams, certifications)
  • and teams (e.g. their business units, associated services). 

This information needs to be verifiable in real-time, ensuring that permissions stay strictly within policy limits. 

Examples of how to use dynamic permissions in an internal developer portal

Imagine these scenarios made possible with dynamic permissions in Port:

  • Incident Management: On-call engineers can get automatic access to production environments during their shift, but only outside of regular business hours.
  • Feature Flags: Only the product manager for a specific service can toggle on a feature flag for a new service.
  • Ephemeral Environments: Junior developers (less than a year with the company) can spin up two temporary environments per month. For more, they need their team lead's approval.
  • Onboarding: Only members of a specific team can request licenses for certain software types.
  • FinOps: Only director-level employees can approve budget overruns.

How does Port make this possible?

Port's dynamic permissions leverage the concept of blueprints, which define the schema of each entity within the catalog. Importantly, in Port, users and teams are also blueprints, allowing you to manage them just like any other resource in your catalog. This provides the flexibility to add custom properties, such as "Business Unit," to users for example.

A user blueprint
A user blueprint

With this in place, Port's RBAC engine lets you create sophisticated permissions based on these properties. You could define a rule stating, "A user can deploy a service if their 'Business Unit' property matches the 'Business Unit' property of the service”. This mechanism enables a wide range of dynamic permission scenarios, tailored to your unique organizational structure and needs.

Want to try it for yourself? Check out our documentation.

{{cta_1}}

Check out Port's pre-populated demo and see what it's all about.

Check live demo

No email required

{{cta_2}}

Contact sales for a technical product walkthrough

Let’s start
{{cta_3}}

Open a free Port account. No credit card required

Let’s start
{{cta_4}}

Watch Port live coding videos - setting up an internal developer portal & platform

Let’s start
{{cta_5}}

Check out Port's pre-populated demo and see what it's all about.

(no email required)

Let’s start
{{cta_6}}

Contact sales for a technical product walkthrough

Let’s start
{{cta_7}}

Open a free Port account. No credit card required

Let’s start
{{cta_8}}

Watch Port live coding videos - setting up an internal developer portal & platform

Let’s start
{{cta-demo}}
{{reading-box-backstage-vs-port}}

Example JSON block

{
  "foo": "bar"
}

Order Domain

{
  "properties": {},
  "relations": {},
  "title": "Orders",
  "identifier": "Orders"
}

Cart System

{
  "properties": {},
  "relations": {
    "domain": "Orders"
  },
  "identifier": "Cart",
  "title": "Cart"
}

Products System

{
  "properties": {},
  "relations": {
    "domain": "Orders"
  },
  "identifier": "Products",
  "title": "Products"
}

Cart Resource

{
  "properties": {
    "type": "postgress"
  },
  "relations": {},
  "icon": "GPU",
  "title": "Cart SQL database",
  "identifier": "cart-sql-sb"
}

Cart API

{
 "identifier": "CartAPI",
 "title": "Cart API",
 "blueprint": "API",
 "properties": {
   "type": "Open API"
 },
 "relations": {
   "provider": "CartService"
 },
 "icon": "Link"
}

Core Kafka Library

{
  "properties": {
    "type": "library"
  },
  "relations": {
    "system": "Cart"
  },
  "title": "Core Kafka Library",
  "identifier": "CoreKafkaLibrary"
}

Core Payment Library

{
  "properties": {
    "type": "library"
  },
  "relations": {
    "system": "Cart"
  },
  "title": "Core Payment Library",
  "identifier": "CorePaymentLibrary"
}

Cart Service JSON

{
 "identifier": "CartService",
 "title": "Cart Service",
 "blueprint": "Component",
 "properties": {
   "type": "service"
 },
 "relations": {
   "system": "Cart",
   "resources": [
     "cart-sql-sb"
   ],
   "consumesApi": [],
   "components": [
     "CorePaymentLibrary",
     "CoreKafkaLibrary"
   ]
 },
 "icon": "Cloud"
}

Products Service JSON

{
  "identifier": "ProductsService",
  "title": "Products Service",
  "blueprint": "Component",
  "properties": {
    "type": "service"
  },
  "relations": {
    "system": "Products",
    "consumesApi": [
      "CartAPI"
    ],
    "components": []
  }
}

Component Blueprint

{
 "identifier": "Component",
 "title": "Component",
 "icon": "Cloud",
 "schema": {
   "properties": {
     "type": {
       "enum": [
         "service",
         "library"
       ],
       "icon": "Docs",
       "type": "string",
       "enumColors": {
         "service": "blue",
         "library": "green"
       }
     }
   },
   "required": []
 },
 "mirrorProperties": {},
 "formulaProperties": {},
 "calculationProperties": {},
 "relations": {
   "system": {
     "target": "System",
     "required": false,
     "many": false
   },
   "resources": {
     "target": "Resource",
     "required": false,
     "many": true
   },
   "consumesApi": {
     "target": "API",
     "required": false,
     "many": true
   },
   "components": {
     "target": "Component",
     "required": false,
     "many": true
   },
   "providesApi": {
     "target": "API",
     "required": false,
     "many": false
   }
 }
}

Resource Blueprint

{
 “identifier”: “Resource”,
 “title”: “Resource”,
 “icon”: “DevopsTool”,
 “schema”: {
   “properties”: {
     “type”: {
       “enum”: [
         “postgress”,
         “kafka-topic”,
         “rabbit-queue”,
         “s3-bucket”
       ],
       “icon”: “Docs”,
       “type”: “string”
     }
   },
   “required”: []
 },
 “mirrorProperties”: {},
 “formulaProperties”: {},
 “calculationProperties”: {},
 “relations”: {}
}

API Blueprint

{
 "identifier": "API",
 "title": "API",
 "icon": "Link",
 "schema": {
   "properties": {
     "type": {
       "type": "string",
       "enum": [
         "Open API",
         "grpc"
       ]
     }
   },
   "required": []
 },
 "mirrorProperties": {},
 "formulaProperties": {},
 "calculationProperties": {},
 "relations": {
   "provider": {
     "target": "Component",
     "required": true,
     "many": false
   }
 }
}

Domain Blueprint

{
 "identifier": "Domain",
 "title": "Domain",
 "icon": "Server",
 "schema": {
   "properties": {},
   "required": []
 },
 "mirrorProperties": {},
 "formulaProperties": {},
 "calculationProperties": {},
 "relations": {}
}

System Blueprint

{
 "identifier": "System",
 "title": "System",
 "icon": "DevopsTool",
 "schema": {
   "properties": {},
   "required": []
 },
 "mirrorProperties": {},
 "formulaProperties": {},
 "calculationProperties": {},
 "relations": {
   "domain": {
     "target": "Domain",
     "required": true,
     "many": false
   }
 }
}
{{tabel-1}}

Microservices SDLC

  • Scaffold a new microservice

  • Deploy (canary or blue-green)

  • Feature flagging

  • Revert

  • Lock deployments

  • Add Secret

  • Force merge pull request (skip tests on crises)

  • Add environment variable to service

  • Add IaC to the service

  • Upgrade package version

Development environments

  • Spin up a developer environment for 5 days

  • ETL mock data to environment

  • Invite developer to the environment

  • Extend TTL by 3 days

Cloud resources

  • Provision a cloud resource

  • Modify a cloud resource

  • Get permissions to access cloud resource

SRE actions

  • Update pod count

  • Update auto-scaling group

  • Execute incident response runbook automation

Data Engineering

  • Add / Remove / Update Column to table

  • Run Airflow DAG

  • Duplicate table

Backoffice

  • Change customer configuration

  • Update customer software version

  • Upgrade - Downgrade plan tier

  • Create - Delete customer

Machine learning actions

  • Train model

  • Pre-process dataset

  • Deploy

  • A/B testing traffic route

  • Revert

  • Spin up remote Jupyter notebook

{{tabel-2}}

Engineering tools

  • Observability

  • Tasks management

  • CI/CD

  • On-Call management

  • Troubleshooting tools

  • DevSecOps

  • Runbooks

Infrastructure

  • Cloud Resources

  • K8S

  • Containers & Serverless

  • IaC

  • Databases

  • Environments

  • Regions

Software and more

  • Microservices

  • Docker Images

  • Docs

  • APIs

  • 3rd parties

  • Runbooks

  • Cron jobs

Starting with Port is simple, fast and free.

Let’s start