Tag: access controls

  • Access Controls

    Access Controls

    Access Control is a security technique that regulates who or what can view, use, or interact with resources in a system, thereby protecting it against unauthorized access. It involves defining and enforcing policies that determine permissions based on user roles, attributes, or contexts, ensuring that only authorized entities can perform specific actions. Common models include Discretionary Access Control (DAC), Mandatory Access Control (MAC), and Role-Based Access Control (RBAC), each offering different levels of granularity and security. By restricting access to sensitive data and critical systems, access control minimizes risks, supports compliance, and upholds the confidentiality, integrity, and availability of information.


    Attribute-based Access Control (ABAC)

    Attribute-Based Access Control (ABAC) is an access control model that grants or denies access to resources based on a combination of attributes associated with users, resources, actions, and the environment. Attributes can include factors such as a user’s role, department, security clearance, location, time of access, or even device type. ABAC policies use logical rules to evaluate these attributes and determine whether access should be permitted, making it highly flexible and context-aware. Unlike role-based models, ABAC allows more fine-grained control, enabling organizations to enforce dynamic and situation-specific access decisions that strengthen security and compliance.

    • User attributes
    • Object attributes
    • Environment conditions

    Example

    user_attrs = { # dictionary storing attributes for each user
        “john”: {“role”: “admin”, “department”: “IT”}, # john is admin in IT department
        “jane”: {“role”: “dev”, “department”: “Sales”} # jane is developer in Sales department
     }

    resource_attrs = { # dictionary storing attributes for each resource
        “apache.log”: {“department”: “IT”, “sensitivity”: “high”}, # IT log file with high sensitivity
         “report.txt”: {“department”: “Sales”, “sensitivity”: “low”} # Sales report with low sensitivity
    }

    def check_access(user, resource): 
        user_attrs.get(user) # attempt to fetch user attributes (unused redundant line)
        if not user_attrs.get(user) or not resource_attrs.get(resource): # check if user or resource exists
            return False # deny access if either is missing
        if user_attrs.get(user)[“department”] == resource_attrs.get(resource)[“department”]: # check department match
            return True # allow access if user and resource belong to same department
        if user_attrs.get(user)[“role”] == “admin”: # check if user has admin role
            return True # allow access if user is admin
        return False # deny access if no rules matched

    print(check_access(“john”, “apache.log”)) # test access for john to apache.log (Will be successful)
    print(check_access(“jane”, “apache.log”)) # test access for jane to apache.log (will fail)

    user_attrs = {
      "john": {"role": "admin", "department": "IT"},
      "jane": {"role": "dev", "department": "Sales"}
    }
    resource_attrs = {
      "apache.log": {"department": "IT", "sensitivity": "high"},
      "report.txt": {"department": "Sales", "sensitivity": "low"}
    }

    def check_access(user, resource):
        user_attrs.get(user)
        if not user_attrs.get(user) or not resource_attrs.get(resource):
            return False
        if user_attrs.get(user)["department"] == resource_attrs.get(resource)["department"]:
            return True
        if user_attrs.get(user)["role"] == "admin":
            return True
        return False

    print(check_access("john", "system_logs"))
    print(check_access("jane", "system_logs"))

    Output

    True
    False

    Discretionary Access Control (DAC)

    Discretionary Access Control (DAC) or Owner-based Access Control is an access control model in which the owner of a resource has the authority to decide who can access it and what level of access is granted. This model relies on Access Control Lists (ACLs), which are used to specify the permissions for individual users or groups, such as read, write, or execute rights. DAC provides flexibility by allowing owners to manage access to their resources directly, but it can also introduce security risks if permissions are misconfigured or broadly shared. It is widely used in operating systems and file systems, where individual users control access to their own files while maintaining a balance between usability and security.

    • The data owner of an organization determines the level of access

    Example

    files = {  # dictionary storing file ownership and permissions
            “report.txt”: { # file name key in the system
                “owner”: “alice”, # user who owns the file (has highest control in DAC)
                “permissions”: { # permission rules for users and others
                    “alice”: “rw”, # owner permissions: read and write
                    “sales”: “r”, # sales group can only read the file
                    “others”: “r” # default permissions for all other users
                }
            }
        }

    def can_access(user, file, action):
        if not files.get(file): # check if the requested file exists in the system
            return False # deny access if file is not found
        if user in files.get(file)[“permissions”] and action in files.get(file)[“permissions”][user]: # check if user has explicit permission
            return True # allow access if user has matching permission for the action
        return action in files.get(file)[“permissions”][“others”] # fallback to “others” permission if no user-specific rule exists

    print(can_access(“alice”, “report.txt”, “r”)) # owner access (expected True because alice has rw)
    print(can_access(“alice”, “report.txt”, “x”)) # invalid action for owner (expected False because “x” not in rw)
    print(can_access(“salse”, “report.txt”, “r”)) # salse has read permission (expected True)
    print(can_access(“test”, “report.txt”, “r”)) # unknown user treated as “others” (expected True because others = r)

    files = {
      "report.txt": {
          "owner": "alice",
          "permissions": {
              "alice": "rw",
              "sales": "r",
              "others": "r"
          }
      }
    }

    def can_access(user, file, action):
        if not files.get(file):
            return False
        if user in files.get(file)["permissions"] and action in files.get(file)["permissions"][user]:
            return True
        return action in files.get(file)["permissions"]["others"]

    print(can_access("alice", "report.txt", "r"))
    print(can_access("alice", "report.txt", "x"))
    print(can_access("sales", "report.txt", "r"))
    print(can_access("test", "report.txt", "r"))

    Output

    True
    False
    True
    True

    Graph-based Access Control (GBAC)

    Graph-Based Access Control (GBAC) is an access control model that determines permissions based on the relationships between data, users, and resources within a system. In GBAC, entities and their interactions are represented as nodes and edges in a graph, allowing access decisions to be made by analyzing these connections. For example, a user’s access to a document might depend on their relationship to the document’s owner or their position within an organizational network. This model provides fine-grained, context-aware control, enabling organizations to enforce dynamic policies that reflect complex real-world relationships, making it particularly useful in social networks, collaborative environments, and interconnected data systems.

    • Using an organizational query language (john -> admin_role -> IT_access -> apache.log)

    Example

    graph = { # GBAC graph showing relationships between users, roles, and resources

        “john”: [“admin_role”], # john is assigned to admin role
        “jane”: [“sales_role”], # jane is assigned to sales role

        “admin_role”: [“IT_access”, “Security_access”], # admin role grants IT and security access
        “sales_role”: [“Salesforce_access”], # sales role grants Salesforce access

        “IT_access”: [“apache.log”, “system_logs”], # IT access allows system logs and apache logs
        “Security_access”: [“security.log”], # security access allows security logs
        “Salesforce_access”: [“report.txt”, “app_code”] # salesforce access allows reports and code access
    }

    def check_access(user, resource): # function to check access using graph traversal
        def depth_first_search(node, target, visited=None): # depth-first search to traverse graph
            if visited is None:
                visited = set() # track visited nodes to avoid loops
            if node == target: # if target resource is reached
                return True # access is allowed
            visited.add(node) # mark current node as visited
            for neighbor in graph.get(node, []): # explore connected nodes
                if neighbor not in visited: # avoid revisiting nodes
                    if depth_first_search(neighbor, target, visited): # recursive search
                        return True # access granted if path found
            return False # no valid path found
        return depth_first_search(user, resource) # start search from user node

    print(check_access(“john”, “apache.log”)) # True (john -> admin_role -> IT_access -> apache.log)
    print(check_access(“jane”, “app_code”)) # True (jane -> sales_role -> Salesforce_access -> app_code)
    print(check_access(“jane”, “security.log”)) # False (no path from jane to security.log)

    graph = {
        "john": ["admin_role"],
        "jane": ["sales_role"],
        "admin_role": ["IT_access", "Security_access"],
        "sales_role": ["Salesforce_access"],
        "IT_access": ["apache.log", "system_logs"],
        "Security_access": ["security.log"],
        "Salesforce_access": ["report.txt", "app_code"]
    }

    def check_access(user, resource):
        def depth_first_search(node, target, visited=None):
            if visited is None:
                visited = set()
            if node == target:
                return True
            visited.add(node)
            for neighbor in graph.get(node, []):
                if neighbor not in visited:
                    if depth_first_search(neighbor, target, visited):
                        return True
            return False
        return depth_first_search(user, resource)

    print(check_access("john", "apache.log"))
    print(check_access("jane", "app_code"))
    print(check_access("jane", "security.log"))

    Output

    True
    True
    False

    History-Based Access Control (HBAC)

    History-Based Access Control (HBAC) is an access control model that determines whether a user, system, or object can access a resource based on the evaluation of their past activities or behavior. Unlike static models, HBAC dynamically considers a history of actions (such as previous logins, transaction patterns, or resource usage) to make real-time access decisions. For example, a user who has performed unusual or risky actions in the past may be temporarily restricted from sensitive operations. By leveraging behavioral history, HBAC enhances security, helps prevent misuse, and enables more context-aware, adaptive access control that responds to potential threats or anomalies as they occur.

    • A user declined access to sensitive info because of past behavior

    Example

    user_history = { # stores past actions performed by each user
        “john”: [“success_login”, “read_log”, “write_log”], # john’s activity history
        “jane”: [“success_login”, “failed_login”, “read_report”] # jane’s activity history
    }

    restricted_actions = [“failed_login”, “security_violation”] # actions that indicate risky or bad behavior

    def check_access(user, action): # function to decide access based on user history
        history = user_history.get(user, []) # get user history or empty list if user not found
        for event in history: # loop through each past action in user’s history
            if event in restricted_actions: # check if any action is considered risky
                return False # deny access if bad behavior is found in history
        return True # allow access if no restricted actions are found

    print(check_access(“john”, “access_log”)) # check access for john (expected True)
    print(check_access(“jane”, “access_log”)) # check access for jane (expected False due to failed_login)

    user_history = {
        "john": ["success_login", "read_log", "write_log"],
        "jane": ["success_login", "failed_login", "read_report"]
    }

    restricted_actions = ["failed_login", "security_violation"]

    def check_access(user, action):

        history = user_history.get(user, [])
        for event in history:
            if event in restricted_actions:
                return False
        return True

    print(check_access("john", "access_log"))
    print(check_access("jane", "access_log"))

    Output

    True
    False

    Identity-Based Access Control (IBAC)

    Identity-Based Access Control (IBAC) is an access control model in which access to resources is granted or denied based on the specific identity of an individual user rather than a group or role. Each user is assigned explicit permissions that define what actions they can perform on particular resources, ensuring precise, user-specific control. This model provides a high level of granularity and accountability, as every action can be traced directly to a single identity. IBAC is particularly useful in environments where individualized access policies are required, such as sensitive data systems, administrative applications, or scenarios demanding strict auditing and compliance.

    • A specific user has access to sensitive information

    Example 

    access_list = { # dictionary mapping user identity to allowed resources
        “john”: [“apache.log”, “system_logs”], # john can access apache.log and system_logs
        “jane”: [“report.txt”] # jane can only access report.txt
    }

    def check_access(user, resource): 
        allowed_resources = access_list.get(user, []) # get list of resources allowed for the user
        if resource in allowed_resources: # check if requested resource is in user’s allowed list
            return True # allow access if resource is found
        return False # deny access if resource is not found

    print(check_access(“john”, “apache.log”)) # True (john has access)
    print(check_access(“john”, “report.txt”)) # False (john not allowed)
    print(check_access(“jane”, “report.txt”)) # True (jane has access)

    access_list = {
        "john": ["apache.log", "system_logs"],
        "jane": ["report.txt"]
    }

    def check_access(user, resource):
        allowed_resources = access_list.get(user, [])
        if resource in allowed_resources:
            return True
        return False

    print(check_access("john", "apache.log"))
    print(check_access("john", "report.txt"))
    print(check_access("jane", "report.txt"))

    Output

    True
    False
    True

    Mandatory Access Control (MAC)

    Mandatory Access Control (MAC) is an access control model in which access to resources is strictly regulated by policies set by a central authority rather than by individual users. In MAC, every user and resource is assigned a classification or security label, and access decisions are made based on these labels according to predefined rules. Users cannot change permissions on the resources they own, ensuring that access is enforced consistently and in compliance with organizational or regulatory requirements. This model is commonly used in highly secure environments, such as government, military, and critical infrastructure systems, where strict control and data confidentiality are paramount.

    • A user must demonstrate a need for the information before granting access

    Example

    security_labels = { # dictionary assigning security clearance levels to users
        “john”: “secret”, # john has secret-level clearance
        “jane”: “confidential” # jane has confidential-level clearance
    }

    resource_labels = { # dictionary assigning classification levels to resources
        “apache.log”: “secret”, # apache.log is classified as secret
        “report.txt”: “confidential” # report.txt is classified as confidential
    }

    levels = { # mapping of security levels to numeric values for comparison
        “public”: 1, # lowest security level
        “confidential”: 2, # medium security level
        “secret”: 3 # highest security level
    }

    def check_access(user, resource): # function to evaluate MAC policy
        user_level = levels.get(security_labels.get(user, “public”)) # get numeric clearance level of user
        resource_level = levels.get(resource_labels.get(resource, “public”)) # get numeric classification level of resource
        if user_level >= resource_level: # MAC rule: user must have equal or higher clearance than resource
            return True # allow access if condition is satisfied
        return False # deny access if clearance is too low

    print(check_access(“john”, “apache.log”)) # True (secret >= secret)
    print(check_access(“jane”, “apache.log”)) # False (confidential < secret)
    print(check_access(“jane”, “report.txt”)) # True (confidential >= confidential)


    security_labels = {
        "john": "secret",
        "jane": "confidential"
    }

    resource_labels = {
        "apache.log": "secret",
        "report.txt": "confidential"
    }

    levels = {
        "public": 1,
        "confidential": 2,
        "secret": 3
    }

    def check_access(user, resource):
        user_level = levels.get(security_labels.get(user, "public"))
        resource_level = levels.get(resource_labels.get(resource, "public"))
        if user_level >= resource_level:
            return True
        return False

    print(check_access("john", "apache.log"))
    print(check_access("jane", "apache.log"))
    print(check_access("jane", "report.txt")) 

    Output

    True
    False
    True

    Role-Based Access Control (RBAC)

    Role-Based Access Control (RBAC) is an access control model in which access to resources and permissions is granted based on a user’s role within an organization rather than on an individual basis. Each role is assigned specific access rights that correspond to the responsibilities and tasks associated with that role, and users are then assigned to one or more roles. This approach simplifies administration by allowing permissions to be managed collectively for roles instead of individually for each user, reduces the risk of excessive privileges, and supports the principle of least privilege. RBAC is widely used in enterprise systems to enforce consistent security policies, streamline user management, and maintain compliance with regulatory standards.

    • Job title

    user_roles = { # dictionary mapping each user to a role
        “john”: “admin”, # john is assigned the admin role
        “jane”: “developer” # jane is assigned the developer role
    }

    role_permissions = { # dictionary mapping roles to allowed resources
        “admin”: [“apache.log”, “report.txt”], # admin role can access both resources
        “developer”: [“report.txt”] # developer role can only access report.txt
    }

    def check_access(user, resource): # function to check access based on role
        role = user_roles.get(user) # get the role assigned to the user
        if not role: # check if user has a valid role
            return False # deny access if no role is assigned
        allowed_resources = role_permissions.get(role, []) # get resources allowed for that role
        if resource in allowed_resources: # check if resource is allowed for the role
            return True # allow access if resource is in role permissions
        return False # deny access if resource is not permitted

    print(check_access(“john”, “apache.log”)) # True (admin has access)
    print(check_access(“jane”, “apache.log”)) # False (developer does not have access)
    print(check_access(“jane”, “report.txt”)) # True (developer has access)

    user_roles = {
        "john": "admin",
        "jane": "developer"
    }

    role_permissions = {
        "admin": ["apache.log", "report.txt"],
        "developer": ["report.txt"]
    }

    def check_access(user, resource):
        role = user_roles.get(user)
        if not role:
            return False
        allowed_resources = role_permissions.get(role, [])
        if resource in allowed_resources:
            return True
        return False

    print(check_access("john", "apache.log"))
    print(check_access("jane", "apache.log"))
    print(check_access("jane", "report.txt"))

    Output

    True
    False
    True

    Rule-Based Access Control (RAC)

    Rule-Based Access Control (RAC) is an access control model in which access to resources is determined by a predefined set of rules or conditions established by the system or administrator. These rules evaluate factors such as time of access, location, device type, or specific actions being attempted to decide whether access should be granted or denied. Unlike role-based or identity-based models, RAC enforces dynamic policies that can automatically adapt to context or system states, making it suitable for environments that require flexible, policy-driven control. By using clearly defined rules, RAC helps maintain security, ensure compliance, and reduce the risk of unauthorized access while allowing automated, consistent decision-making.

    • Allowing access to a resource using ip, time and role

    Example

    def check_access(user, resource, hour, ip): # function to evaluate access based on system rules
        if hour < 8 or hour > 17: # rule: allow access only during business hours (8 AM to 5 PM)
            return False # deny access if outside allowed time window
        if not ip.startswith(“10.1.”): # rule: allow only trusted internal network IP range
            return False # deny access if IP is not from trusted subnet
        if resource == “apache.log” and user != “admin”: # rule: only admin can access sensitive log file
            return False # deny access if non-admin tries to access apache.log
        return True # allow access if all rules pass

    print(check_access(“admin”, “apache.log”, 9, “10.1.1.10”)) # True (admin, valid time, trusted IP)
    print(check_access(“jane”, “apache.log”, 9, “10.1.1.10”)) # False (not admin)
    print(check_access(“admin”, “report.txt”, 9, “10.2.0.5”)) # False (untrusted IP)

    def check_access(user, resource, hour, ip):
        if hour < 8 or hour > 17:
            return False
        if not ip.startswith("10.1."):
            return False
        if resource == "apache.log" and user != "admin":
            return False
        return True

    print(check_access("admin", "apache.log", 9, "10.1.1.10"))
    print(check_access("jane", "apache.log", 9, "10.1.1.10"))
    print(check_access("admin", "report.txt", 9, "10.2.0.5"))

    Output

    True
    False
    True

    Responsibility-Based Access Control (ReBAC)

    Responsibility-Based Access Control (ReBAC) is an access control model in which access to resources is granted based on the specific responsibilities assigned to a user or group of users. Unlike role-based models that focus on general job roles, ReBAC ties permissions directly to the duties or tasks a user is expected to perform, ensuring that access is closely aligned with operational responsibilities. This approach enforces the principle of least privilege, as users receive only the access necessary to fulfill their assigned duties. ReBAC is particularly useful in complex or task-oriented environments, where security and accountability must be balanced with operational efficiency.

    • Data engineer has access to a backup management interface

    Example

    responsibilities = { # maps users to the tasks they are responsible for
        “john”: [“incident_6998”, “server_backup”], # john is responsible for incident handling and backups
        “jane”: [“ticket_3467”, “report_review”] # jane is responsible for ticket handling and report review
    }

    task_resources = { # maps each task to the resource it controls
        “incident_6998”: “apache.log”, # incident task gives access to apache log
        “ticket_3467”: “report.txt”, # ticket task gives access to report file
        “server_backup”: “backup.log”, # backup task gives access to backup logs
        “report_review”: “report.txt” # report review task gives access to report file
    }

    def check_access(user, resource): # function to check access based on responsibilities
        user_tasks = responsibilities.get(user, []) # get all tasks assigned to the user
        for task in user_tasks: # loop through each responsibility/task
            if task_resources.get(task) == resource: # check if task maps to requested resource
                return True # allow access if match is found
        return False # deny access if no responsibility matches the resource

    print(check_access(“john”, “apache.log”)) # True (john is responsible for incident_6998)
    print(check_access(“jane”, “apache.log”)) # False (jane has no matching responsibility)
    print(check_access(“jane”, “report.txt”)) # True (jane responsible for ticket_3467 or report_review)

    responsibilities = {
        "john": ["incident_6998", "server_backup"],
        "jane": ["ticket_3467", "report_review"]
    }

    task_resources = {
        "incident_6998": "apache.log",
        "ticket_3467": "report.txt",
        "server_backup": "backup.log",
        "report_review": "report.txt"
    }

    def check_access(user, resource):
        user_tasks = responsibilities.get(user, [])
        for task in user_tasks:
            if task_resources.get(task) == resource:
                return True
        return False

    print(check_access("john", "apache.log"))
    print(check_access("jane", "apache.log"))
    print(check_access("jane", "report.txt"))

    Output

    True
    False
    True