Code Groups are a key component of Code Access Security (CAS) in the .NET Framework. They are used to organize and assign permissions to code based on its evidence. Code Groups, together with the security policy, define what actions or resources a particular piece of code can access, based on its evidence (such as its location, publisher, or strong name).
In CAS, Code Groups provide a way to categorize code and assign permissions to it based on specific evidence. A code group is a collection of assemblies or code that share a common set of characteristics. These characteristics are determined by the evidence associated with the code (such as URL, strong name, or publisher), and the code group can specify what permissions to grant to all the code it contains.
Evidence-Based Membership:
Permissions Associated with Code Groups:
Code Group Hierarchy:
Policy Levels and Code Groups:
Security Policy:
A code group works by matching evidence of the code against certain criteria defined in the code group, and then granting the associated permissions to the matching code. Here's how this process works:
Assembly Loads into CLR: When an assembly is loaded into the Common Language Runtime (CLR), the CLR collects the evidence of the assembly (such as its location, publisher, or strong name).
Matching Against Code Groups: The CLR then checks if the evidence of the assembly matches any defined code group. If the evidence matches, the assembly is considered a member of that code group.
Granting Permissions: Once the assembly has been placed into a code group, the permission set associated with that code group is granted to the code. The permissions could range from full trust to restricted access to specific resources.
Policy Level Application: The security policy defines the set of code groups and their corresponding permissions at different policy levels (machine, user, application). The CLR checks these policy levels and determines the final permission set based on where the code is running.
Here is an example of how code groups might be configured:
We want to create two code groups:
Machine Policy Code Group (Local): This code group grants full permissions to assemblies loaded from the Local Machine zone (i.e., trusted code running from the local computer).
Example:
Code Group: Local Machine Code Group
Evidence: URL = "file:///*"
Permissions: FullTrust (all permissions granted)
In this case, code loaded from the local machine (file:///*) will be granted FullTrust permissions, meaning it can access system resources such as files, the network, etc.
Internet Code Group: This code group grants restricted permissions to code loaded from the Internet zone, such as code downloaded via HTTP.
Example:
Code Group: Internet Code Group
Evidence: URL = "http://*"
Permissions: ExecutionOnly (no file system access, no network access, etc.)
In this case, code from an HTTP source will have very restricted permissions, such as ExecutionOnly, meaning it can execute code but cannot interact with the file system or network.
In a security policy file (e.g., machine.config), code groups can be nested and structured. A simple structure might look like this:
<securityPolicy>
<policyLevels>
<machine>
<codeGroup class="UnionCodeGroup" version="1" PermissionSetName="FullTrust">
<membershipConditions>
<urlMembershipCondition url="file:///*" />
</membershipConditions>
</codeGroup>
<codeGroup class="UnionCodeGroup" version="1" PermissionSetName="ExecutionOnly">
<membershipConditions>
<urlMembershipCondition url="http://*" />
</membershipConditions>
</codeGroup>
</machine>
</policyLevels>
</securityPolicy>
FullTrust or ExecutionOnly).Here’s an example of how code groups can be used to specify permissions programmatically using attributes in .NET:
[PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
public class TrustedCode
{
public void ExecuteAction()
{
// This code will run only if the assembly has FullTrust permissions
Console.WriteLine("Full Trust granted.");
}
}
[PermissionSet(SecurityAction.Demand, Name = "ExecutionOnly")]
public class RestrictedCode
{
public void ExecuteAction()
{
// This code will run with restricted permissions (e.g., no file access)
Console.WriteLine("Restricted permissions granted.");
}
}
In this example, the TrustedCode class demands FullTrust, meaning it can access all system resources, while RestrictedCode demands ExecutionOnly, limiting what it can do.
Code Groups in .NET's Code Access Security model provide a way to categorize and manage code based on its identity and origin (evidence). By using code groups, developers can assign different permission sets to code depending on where it came from, what its identity is, and what actions it needs to perform. However, with the deprecation of CAS in .NET Core and newer versions, it's important to understand these concepts for working with legacy .NET Framework applications. For modern applications, newer security approaches are used to handle authentication, authorization, and resource access control.
Open this section to load past papers