src/Auth/IAuthorizationResolver.cs (33 lines of code) (raw):
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
using Azure.DataApiBuilder.Config.ObjectModel;
using Microsoft.AspNetCore.Http;
namespace Azure.DataApiBuilder.Auth;
/// <summary>
/// Interface for authorization decision-making. Each method performs lookups within a
/// structure representing permissions defined in the runtime config.
/// </summary>
public interface IAuthorizationResolver
{
/// <summary>
/// Representation of authorization permissions for each entity in the runtime config.
/// </summary>
public Dictionary<string, EntityMetadata> EntityPermissionsMap { get; }
/// <summary>
/// Checks for the existence of the client role header in httpContext.Request.Headers
/// and evaluates that header against the authenticated (httpContext.User)'s roles
/// </summary>
/// <param name="httpContext">Contains request headers and metadata of the authenticated user.</param>
/// <returns>True, if client role header exists and matches authenticated user's roles.</returns>
public bool IsValidRoleContext(HttpContext httpContext);
/// <summary>
/// Checks if the permissions collection of the requested entity
/// contains an entry for the role defined in the client role header.
/// </summary>
/// <param name="entityIdentifier">Entity from request. This could be the name of the entity or it could be the GraphQL type name, depending on the entry point.</param>
/// <param name="roleName">Role defined in client role header</param>
/// <param name="operation">Operation type: Create, Read, Update, Delete</param>
/// <returns>True, if a matching permission entry is found.</returns>
public bool AreRoleAndOperationDefinedForEntity(string entityIdentifier, string roleName, EntityActionOperation operation);
/// <summary>
/// Any columns referenced in a request's headers, URL(filter/orderby/routes), and/or body
/// are compared against the include/excluded column permission defined for the entityName->roleName->operation
/// </summary>
/// <param name="entityName">Entity from request</param>
/// <param name="roleName">Role defined in client role header</param>
/// <param name="operation">Operation type: Create, Read, Update, Delete</param>
/// <param name="columns">Compiled list of any column referenced in a request</param>
/// <returns></returns>
public bool AreColumnsAllowedForOperation(string entityName, string roleName, EntityActionOperation operation, IEnumerable<string> columns);
/// <summary>
/// Method to return the list of exposed columns for the given combination of
/// entityName, roleName, operation.
/// </summary>
/// <param name="entityName">Entity from request</param>
/// <param name="roleName">Role defined in client role header</param>
/// <param name="operation">Operation type: Create, Read, Update, Delete</param>
/// <returns></returns>
public IEnumerable<string> GetAllowedExposedColumns(string entityName, string roleName, EntityActionOperation operation);
/// <summary>
/// Helper function to fetch the database policy associated with the current request based on the entity under
/// action, the role defined in the the request and the operation to be executed.
/// When no database policy is found, no database query predicates need to be added.
/// 1) _entityPermissionMap[entityName] finds the entityMetaData for the current entityName
/// 2) entityMetaData.RoleToOperationMap[roleName] finds the roleMetaData for the current roleName
/// 3) roleMetaData.OperationToColumnMap[operation] finds the operationMetadata for the current operation
/// 4) operationMetaData.databasePolicy finds the required database policy
/// </summary>
/// <param name="entityName">Entity from request.</param>
/// <param name="roleName">Role defined in client role header.</param>
/// <param name="operation">Operation type: create, read, update, delete.</param>
/// <returns>Policy string if a policy exists in config.</returns>
public string GetDBPolicyForRequest(string entityName, string roleName, EntityActionOperation operation);
/// <summary>
/// Retrieves the policy of an operation within an entity's role entry
/// within the permissions section of the runtime config, and tries to process
/// the policy.
/// </summary>
/// <param name="entityName">Entity from request.</param>
/// <param name="roleName">Role defined in client role header.</param>
/// <param name="operation">Operation type: Create, Read, Update, Delete.</param>
/// <param name="httpContext">Contains token claims of the authenticated user used in policy evaluation.</param>
/// <returns>Returns the parsed policy, if successfully processed, or an exception otherwise.</returns>
public string ProcessDBPolicy(string entityName, string roleName, EntityActionOperation operation, HttpContext httpContext);
/// <summary>
/// Get list of roles defined for entity within runtime configuration.. This is applicable for GraphQL when creating authorization
/// directive on Object type.
/// </summary>
/// <param name="entityName">Name of entity.</param>
/// <returns>Collection of role names.</returns>
public IEnumerable<string> GetRolesForEntity(string entityName);
/// <summary>
/// Returns the collection of roles which can perform {operation} the provided field.
/// Applicable to GraphQL field directive @authorize on ObjectType fields.
/// </summary>
/// <param name="entityName">EntityName whose operationMetadata will be searched.</param>
/// <param name="field">Field to lookup operation permissions</param>
/// <param name="operation">Specific operation to get collection of roles</param>
/// <returns>Collection of role names allowed to perform operation on Entity's field.</returns>
public IEnumerable<string> GetRolesForField(string entityName, string field, EntityActionOperation operation);
/// <summary>
/// Returns whether the httpVerb (GET, POST, PUT, PATCH, DELETE) is allowed to be performed
/// on the stored procedure (represented by entityName) for the role: roleName.
/// </summary>
/// <param name="entityName"></param>
/// <param name="roleName"></param>
/// <param name="httpVerb"></param>
/// <returns>True if the execution of the stored procedure is permitted. Otherwise, false.</returns>
public bool IsStoredProcedureExecutionPermitted(string entityName, string roleName, SupportedHttpVerb httpVerb);
/// <summary>
/// Returns a list of roles which define permissions for the provided operation.
/// i.e. list of roles which allow the operation 'Read' on entityName.
/// </summary>
/// <param name="entityName">Entity to lookup permissions</param>
/// <param name="operation">Operation to lookup applicable roles</param>
/// <returns>Collection of roles. Empty list if entityPermissionsMap is null.</returns>
public static IEnumerable<string> GetRolesForOperation(
string entityName,
EntityActionOperation operation,
Dictionary<string, EntityMetadata>? entityPermissionsMap)
{
if (entityName is null)
{
throw new ArgumentNullException(paramName: nameof(entityName));
}
if (entityPermissionsMap is not null &&
entityPermissionsMap[entityName].OperationToRolesMap.TryGetValue(operation, out List<string>? roleList) &&
roleList is not null)
{
return roleList;
}
return new List<string>();
}
}