Account Manager 4

Author: Stephen W. Cote

Index

BETA NOTE

Account Manager 4 is currently in beta. This document and related projects are subject to change.

License

Account Manager 4 is made available as-is, without warranty.

  • Introduction
    • About
    • Annotations
    • Dependencies
    • Download
  • Design
    • Schema
    • API
    • API Documentation
  • Setup
    • Important Prerequisites
    • Setup
    • Setup Check
    • Setup Example
    • Mono Build
    • MySQL Setup
  • Products and Organizations
    • Organizations
    • Default Organizations
    • Setting up an Organization
    • Products
    • Product Setup Example
  • Factories
    • Available Factories
    • Factory Class
  • Objects
    • Map Objects
  • Access Layers
    • BETA NOTE
    • Overview
    • Raw Access Layer
    • Secure Access Layer
    • Web Access Layer
  • Security Model
    • BETA NOTE
    • Cryptography Services
    • Participation Access Control
    • Participation Model
    • Roles in PAC
    • Permissions in PAC
  • Permissions, Participations, and Participants
    • Participations
    • Participants
    • Participation Example
    • Permissions
  • Accounts
    • Participation
    • Participant
    • Permissions
  • Groups
    • Participation
    • Participant
    • Permissions
  • Data
    • Participation
    • Participant
    • Permissions
  • Roles
    • Participation
    • Participant
    • Permissions
  • Tags
    • Participation
    • Participant
    • Permissions
  • Forum
  • Cryptography and Security
    • Admissions
    • Keys
    • Replacing Keys
    • Public Sign Key
    • Ship Key
    • Product Key
    • Organization Key
    • Design and Intent of Product, Ship, and Organization Keys
    • Encrypt and Encipher with SecurityManager
    • Example: Obtaining Organization Keys
    • Account Ciphers
    • Vault
    • Summary
  • License Management
    • BETA NOTE
    • Introduction
    • License Key
    • License Generation
    • License Validation
    • Trial Licenses
    • End-User License Agreements (EULA)

Modification History

AuthorDateDescription
Stephen W. Cote09/15/2008Version 4 - Beta 2
Stephen W. Cote03/28/2008Add additional details.
Stephen W. Cote03/25/2008Version 4 - Beta 1

Introduction

About

Account Manager is a drop-in solution for multi-organization and multi-user management. It defines its own accounts (directory services currently not supported), security model, and data organization. A broad methodology is used to define groups, tags, permissions, and roles. AccountManager is in its fourth version. It was written to address a need for a lightweight directory service that could store account information across multiple organizations, user data, and complex permission relationships.

Refer to Account Manager 3 for the previous version.

Annotations

  • Using standard .NET 2.0 crypto libs, and Rijndael AES 192/256
  • CoreLib and integrated SecurityManager adapted from earlier Java versions.
  • Can be used with Mono and MySQL.
  • The Account Manager 4 and supporting database schema were redesigned from Account Manager 3. It is not backwards compatible, and no upgrade tools are provided at this time.

Dependencies

  • .NET 2.0 or Mono Framework. (Not included).
  • SQL Express, SQL Server, or MySQL on one or more computers. (Not included).

Download

[ top ]

Design

Schema

The schema organization is layed out around the following concepts:

  • Organizations are top level descriptors in which everything is created.
  • Accounts are individual user or system accounts.
  • Data is a generic schema describing binary data by name and specific data group, with deterministic compression, and optional and multi-layered encryption. Data relationships are created as DataParticipations.
  • Groups define collections for use with Accounts, Data, or generalized buckets. Group relationships are created as GroupParticipations.
  • Roles define collections for use with Accounts. Role relationships are created as RoleParticipations.
  • Tags define collections for use with Accounts and Data. Tag relationships are created as TagParticipations.
  • Controls are ubiquitous grouping and filtering schemas, and include generic controls, organizations permissions, groups, roles, and participants.
  • Permissions define entities for use with Accounts, Data, Groups, and Roles. Permission relationships are created as Effects applied to participations.
  • Participations are collections for Groups, Data, Roles, and Tags. An object associated with a Participation is known as a Participant.

API

The API is structured in the following manner:

  • Factories provide direct, non-secure access to the Account Manager library. The static Factory class is the access point to all available factory instances.
  • Products are Organization-level units that serve as programmatic comptrollers. Every product includes a ProductUser with that belongs to the AccountAdministratorsRole in the Product Organization (every Organization also has an Admin user). For single-user implementations (eg: Vault), the user's account may be the Product User. For multi-user implementations (eg: Core Web), the Product User is blocked from logging in.
  • Access Layers provide in-direct and referential access to the Factories, and are meant to be used with applications that have more than one user and where permissions and roles and desired:
    • Secure Access Layer (security model incomplete) exposes administrative and account features, and asserts appropriate security checks (eg: does the account have permission to perform the action, etc)
    • Forum Access Layer (security model incomplete) exposes Forum Factory features.
    • Data Access Layer (security model incomplete) exposes Data Factory features.
    • Group Access Layer (security model incomplete) exposes Group Factory features.
    • Product Access Layer (incomplete) exposes Product features.
    • Web Access Layer (incomplete) is a Web Service layer for use in multi-tiered environments.

API Documentation

Refer to the Account Manager 4 API Documentation for details.

[ top ]

Setup

Important Prerequisites

If you plan on using any encryption or licensing features included in Account Manager, you should regenerate all of the keys in CoreLib and LicenseMaster2. Refer to the section on Cryptography and Security for more information about the keys, and how to replace them.

Setup

Setup has been improved from Account Manager 3, and is very easy. Three reference implementations are available that can be used to quickly test an environment: Shell, Core Web, and Vault (a composite application with many random features).

There are four setup steps:

  1. Create a database in SQL or MySQL. The database schema is stored in the Config/ directory of the download, adjacent to the project folders.
  2. Edit the application or Web configuration: specify the correct connection string, and the connection type (SQL = 1, Oracle =2 (not presently supported), MySQL = 3). The default Product organization name, and product account and password can be specified if desired.
  3. If the Factory is not running (Core.Tools.AccountManager.Factory.IsRunning == false), start it (Core.Tools.AccountManager.Factory.Start())
  4. Create a new Product (Core.Tools.AccountManager.Product product). If the product is not setup (product.IsSetup), set it up (product.SetupProduct(root_password, product_name, product_password)).
  5. Optionally, if you want to use the Forum feature, it must be initialized separately once the product is setup (Core.Tools.AccountManager.Factory.InitializeForumFactoryInstance(product.Organization)).

Setup Check

The Global Setup status is determined by a boolean value stored in the ApplicationStatus.xml file, which is serialized within the ApplicationConfig table. The Setup.IsSetup property exposes this boolean value.

Organization Setup status is handled by the Product class. The Product.IsSetup property can be used to check whether or not a particular product is ready for use.

Setup Example

using Core.Tools.AccountManager;

if (Factory.IsRunning == false)
{
   Factory.Start();
   Product product = new Product();
   product.OrganizationName = "Test Organization";
   product.Initialize();
   if (product.IsSetup == false)
   {
      product.SetupProduct(
         "root password",
         "Product Account Name",
         "Product Account Password"
      );
   }
   Factory.InitializeForumFactoryInstance(product.Organization);
}				

Mono Build

Setting up Account Manager when using Mono is the same as when using .NET. However, the build instructions are slightly different. Instead of using a project, make.bat and make.sh files are provided for each project folder. The reference projects Core Web, Shell, and Vault 2 include make files that build the prerequisite assemblies.

MySQL Setup

When using MySQL instead of SQL, set the ConnectionType configuration value to 1 (CoreLib::Core.Data.DbFactory.CONNECTION_TYPE.MYSQL).

[ top ]

Products and Organizations

Organizations

The top-most entity within Account Manager is an Organization. Accounts, Groups, Roles, Tags, and Permissions require an Organization. Data does not; it requires a Group, from which the Organization is inferred.

An Organization is a partition. In most cases it need not and should not be crossed. It is possible to cross Organizations, but this is accompanied by myriad maintenance issues not covered by this document.

When using Account Manager, be concientious of the Organization that is expected.

Default Organizations

The Default Organizations follow, where Public is the default parent for any Product Organization.

  • Global
    • Development
    • Public
      • { Product Organization }
    • System

The Core.Tools.AccountManager.Default class exposes direct access to the Global, Development, Public, and System Organizations. The static class can also be used to hold a default organization other than public, although generally this is better handled using a Product.

Setting up an Organization

Organization setup is encapsulated by using a Product, so there is no need to recreate these steps.

Since each Organization is its own functional business unit, it requires its own minimum set of operating data, depending on how the Organization is going to be used. When a new Organization is added, default DirectoryGroup Groups are created for "Root" and "Home" (parented to "Root").

If the Organization is intended for non-internal use, it must be setup with Setup::SetupOrganization(). The SetupOrganization method will create an Admin Account, administration roles, and add both the Admin and Root accounts to those roles. Also, default permissions are added to the Organization.

Some system accounts may also be desirable, such as the License Account for managing Organization level licensing.

Products

Where an Organization is a top-level partition of data, a Product is a top-level partition of intent. The Product class encapsulates setup steps and functionality applicable to building a software product with Account Manager.

A Product can only be created with the Root Account. There is an implied hierarchy with Products at the Organization level. The Root Account is created when the Setup::SetupAccountManager method is invoked, which only executes if the product is not already setup. If Account Manager was not setup prior to setting up a product, everything needed is created: the schemas, Organizations, Root account, Admin accounts, License account, and a Product User Account.

The Product User Account is an internal service account with administrative privileges. It is not recommended to allow users to login with this account (Core Web explicitly blocks access).

Creating a Product is the quickest way to get started with Account Manager. The account is also used heavily in the Vault application (where the user context can be that of the Product User) and Core Web (where users cannot login as the product user). This makes it very easy to setup a multi-user application, such as Core Web, that is locked down, but then develop internal tools that conform to different security roles.

Product Setup Example

This is the same as the earlier setup example.

Product product = new Product();
product.OrganizationName = "Test Organization";
product.Initialize();
if (product.IsSetup == false)
{
   product.SetupProduct(
      "root password",
      "Product Account Name",
      "Product Account Password"
   );
}

[ top ]

Factories

Available Factories

Factories are the access point to raw Account Manager data. They reside below the Access Layers that enforce security, and as such, are internal classes not meant to be accessed outside of the assembly.

Most factories inherit from NameIdFactory, which in turn inherits from FactoryBase. Factories include:

  • FactoryBase - base factory for data level access
    • NameIdFactory - inherits FactoryBase, CRUD Map objects.
      • AccountFactory - CRUD Account objects
      • ContactInformationFactory - CRUD ContactInformation objects
      • DataFactory - CRUD Data objects
      • GroupFactory - CRUD Group objects
      • OrganizationFactory - CRUD Organization objects
      • ParticipationFactory - CRUD participations
        • DataParticipationFactory - inherits ParticipationFactory, CRUD DataParticipants
        • GroupParticipationFactory - inherits ParticipationFactory, CRUD GroupParticipants
        • RoleParticipationFactory - inherits ParticipationdFactory, CRUD RoleParticipants
        • TagParticipationFactory - inherits ParticipationFactory; CRUD TagParticipants
      • PermissionFactory - CRUD Permissions
      • RoleFactory - CRUD Roles
      • TagFactory - CRUD Tag objects
  • SpoolFactory - base factory for managed data spools.
    • MessageQueueFactory - inherits SpoolFactory, CRUD managed messages
    • SecurityTokenFactory - inherits SpoolFactory, CRUD security tokens used for page access authentication (used for CSRF block in CoreWeb)
  • SessionFactory - not a NameId factory; handles Account sessions.

Factory Class

The Factory class is the principle access point to instances of the previous factories, and maintains a central operating state; IsRunning. When the Factory is started, and, assuming the database connection is valid, the schema is validated and created if needed, and the other factory objects are accessible.

[ top ]

Objects

Map Objects

The majority of value objects in Account Manager are located in the namespace Core.Tools.AccountManager.Map. The Map designation is intended to convey that the object shares a mapped relationship to the database schema.

Map objects are created from corresponding factories, inherit from the NameId class, and include:

  • Account - a user or system account.
  • AccountGroup - a BaseGroup used to collect Accounts.
  • AccountParticipant - a BaseParticipant
  • AccountPermission - a BasePermission
  • AccountRole - a BaseRole
  • AccountTag - a BaseTag
  • BaseGroup - a representation of a data and user level aggregate
  • BaseParticipant - a representation of object relationship
  • BasePermission - a representation of a permission
  • BaseRole - a representation of a user level aggregate
  • BaseSpool - a representation of a managed data item
  • BaseTag - a representation of an object marker
  • ContactInformation - address and personal information, such as names, email address, web site, etc.
  • Data - byte data. Includes additional logic for decompressing and decrypting as needed.
  • DataComparer - used to sort Data objects.
  • DataParticipant - a BaseParticipant
  • DataPermission - a BasePermission
  • DataTag - a BaseTag used to mark data.
  • DirectoryComparer - used to sort DirectoryGroup objects.
  • DirectoryGroup - a BaseGroup
  • GroupPermission - a BasePermission
  • MapComparer - a base map comparator
  • Message - a BaseSpool representing a managed message body
  • NameId - a representation of an object with an Id-Name relationship
  • Organization - represents the top-most partition of all other objects.
  • PermissionParticipant - a BaseParticipant
  • RoleParticipant - a BaseParticipant
  • RolePermission - a BasePermission
  • SecurityToken - a BaseSpool representing supplemental authentication.

[ top ]

Access Layers

BETA NOTE

Security via Access Layers is mostly implemented, however, enforcement is not complete.

Overview

In Account Manager 2 and Account Manager 3.x, security was tightly wound into the implementation. In prior versions, AccountFlags compromised a large collection of assorted security checks and utilities. In Account Manager 4, all security matters are abstracted into Layers. Each Layer affords access applicable to the implementation. This approach makes it very easy to develop early versions of software against the library, and then later switch from direct factory access to one of the Layers to apply security.

There are three different types of Access Layers: Raw, Secure, and Web. All types of layers inherit from FactoryAccessLayer.

Raw Access Layer

The Raw Access Layer requires direct access to the Factory object and underlying factory instances. This is only possible in a standalone or single-node implementation.

  • FactoryAccessLayer - Direct access to underlying factories
    • DataAccessLayer - Marshalled access to DataFactory
    • GroupAccessLayer - Marshalled access to GroupFactory
    • ProductAccessLayer - Limited access to certain AccountFactory methods

Secure Access Layer

The Secure Access Layer class applies authorization for specific requests. The AuthorizationUtil class asserts authorization set by SecureAccessLayer. This is the best Layer to use for standalone applications or single-node Web applications.

  • FactoryAccessLayer - Direct access to underlying factories
    • SecureAccessLayer - Marshalled access to AccountFactory and SessionFactory; proxies calls to DataAccessLayer, GroupAccessLayer, and ProductAccessLayer; exposes GroupParticipation and RoleParticipation; exposes easy-access Data, Group, and Role permission application.

Web Access Layer

The Web Access Layer is a Web service that exposes Secure Access Layer to clients. Currently under development.

[ top ]

Security Model

BETA NOTE

The security model in progress, though not fully implemented through the SecureAccessLayer class. It is possible to assert some permission checks through the Core.Tools.AccountManager.Security.AuthorizationUtil class.

Cryptography Services

Cryptographic services are handled by CoreLib::SecurityManager. Refer to Cryptography and Security and Licenses sections for further information.

Participation Access Control

Account Manager uses Participation Access Control (PAC), an interpretation of Roles Based Access Control (RBAC). For comparison, here is a brief introduction to common access controls. Note that these are not necessarily independent of the other.

  • Discretionary Access Control (DAC) defines access to objects at the discretion of the owner.
  • Mandatory Access Control (MAC) extends or replaces Discretionary Access Control, and is a policy governing user access to objects they create, and where users may not change an assigned access level from the one applied by an administrator.
  • Access Control List (ACL) describes privilege separation of a resource as related to a user or group.
  • Roles Based Access Control (RBAC) is closer to an Access Control List (ACL), but differs in that privileges may be assigned at a higher level, such as a role level. RBAC may also be modelled to mimick a Lattice-Based Access Control (LBAC), which is a mathematical structure describing the greatest lower-bound and least upper-bound for a resource pair.

Participation Access Control (PAC) includes elements of RBAC, DAC, and ACL through resource participation. Resource participation is a direct or indirect relationship between two or more entities.

A comparison of PAC to other Access Controls:

  • PAC does not implement sensitivity labels, as is used by MAC.
  • PAC is similar to DAC in that every object must have an owner, and it is different in that every object does not have to have an ACL.
  • PAC is similar to RDAC in that permissions may be assigned to roles, and users may inherit permissions from those roles.
  • PAC requires every object to belong to an Organization, including Organizations (except the top-most organization).
  • PAC requires every object to be owned by an Account, except Organizations.
  • PAC requires every Data object to belong to a Group (of type Directory).

Participation Model

PAC currently exposes a participation model for Data, Groups, Roles, and Tags.

[{Id}-{ParticipationId}] = {Participation} : A participation is a single unique base object. The base object Id is the ParticipationId.

[{ParticipationId}-{ParticipantType}-{ParticipantId}] = {Participant} : A participant is a unique object Id of a specified type to a participation.

Data, Groups and Roles can optionally be Affected. Affect types (word choice aside) currently include granting and denying permission to the participation.

Participations may not transcend the organization level.

Roles in PAC

Roles in PAC are achieved by creating an AccountRole and adding Accounts to that role.

For example, to create a role that includes one or more accounts:

  • Create a new AccountRole, "Test Role"
  • Create a RoleParticipant using the new AccountRole and an existing Account.
  • Add the RoleParticipant with the SecureAccessLayer or the RoleParticipationFactory.

Three principle roles govern administrative authorization within an organization:

  • DataAdministrators - full control over data and directory groups, regardless of permissions or ownership, within the specific organization.
  • AccountAdministrators - full control over accounts, roles, and account groups, regardless of permissions or ownership, within the specific organization.
  • SystemAdministrators - For administrating application features and status.

For example, to test whether an account is a DataAdministrator:

Map.Account account_to_test = ...;
Map.Organization current_org = ...;
Map.AccountRole admin_role = SecureAccessLayer.GetDataAdministratorRole(current_org);
bool is_admin = SecureAccessLayer.GetIsAccountInRole(admin_role, account_to_test);

Permissions in PAC

Permissions in PAC affect participations, and may be granted or denied to an Account, Role, or Group in Data, Role, or Group participations. The SecureAccessLayer aggregates permission settings across the participation factories and uses the AuthorizationUtil class.

There are four primary permissions - create, view, edit, delete - explicitly named for accounts, roles, groups, and data. For example, the account permissions are: AccountView, AccountEdit, AccountCreate, and AccountDelete.

[ top ]

Permissions, Participations, and Participants

Participations

Participations is the general term for the application of participants and affects. This relationship is: Object of Type A to NObject of Type B with NAffect of Type C. Classes supporting participations include:

  • Data
  • Groups
  • Roles
  • Tags

Participations are implied by the corresponding factory, and as such there is not a Participation object. Instead, a participation is implied by the presence of one or more *Participant objects for a specified Participant Type and, optionally, Affect.

Participants

Participants are objects that may be included in the aggregate. Supported participants follow:

  • AccountParticipant - with Groups, Roles, Tags
  • DataParticipant - with Tags
  • RoleParticipant

Participation Example

For example, consider tagging an Image A with labels Tag 1, Tag 2, and Tag 3.

Map.Data ImageA = ...
Map.DataTag Tag1 =
   Factory.TagFactoryInstance.GetDataTagByName("Tag 1", {organization});
Map.DataTag Tag2 = 
   Factory.TagFactoryInstance.GetDataTagByName("Tag 2", {organization});
Map.DataTag Tag3 = 
   Factory.TagFactoryInstance.GetDataTagByName("Tag 3", {organization});
May.DataParticipant TagParticipant1 =
   Factory.TagParticipationFactoryInstance.NewDataTagParticipation(Tag1, ImageA);
Map.DataParticipant TagParticipant2 =
   Factory.TagParticipationFactoryInstance.NewDataTagParticipation(Tag2, ImageA);
Map.DataParticipant TagParticipant3 =
   Factory.TagParticipationFactoryInstance.NewDataTagParticipation(Tag3, ImageA);

The Participation is that data ImageA is a Participant of Tag 1, Tag 2, and Tag 3. As such, there are two different venues for referencing this relationship.

  1. Retrieve all Participants of Tag 1. In this case, there is only one: Image A.
  2. Retrieve all Participations for Image A. In this case, there are three: Tage 1, Tag 2, and Tag 3.

Permissions

Permissions are implemented as an affect to participants. Ultimately, this implementation resolves to an equivalent of an Access Control List (ACL), but is designed to support more detailed profiling and entitlements; effectively chaining relationships and permissions together. Account Manager is easily extended to include custom permissions. It's as simple as adding a new permission using the PermissionFactory, and then implementing that permission as a participant affect.

Using permissions is straight forward when implemented with the SecureAccessLayer.

For example, the following code shows how to set a permission allowing YourUser to change MyData.

Map.Account MyUser = ...;
Map.Account YourUser = ...;
Map.Data MyData = ...
SecureAccessLayer.EnableChangeData(MyUser, YourUser, MyData);

/// To verify authorization:
///
bool IsAuthorized = AuthorizationUtil.CanChangeData(YourUser, MyData)

SecureAccessLayer implements internal Switch* methods in the AuthorizationUtil class to verify one account is authorized to change the permission for the second account on the target object. The following example shows the implementation for switching the previous data permission.

/// Access Layer
///
Security.AuthorizationUtil.SwitchData(
   admin, account, data,
   Security.AuthorizationUtil.GetEditDataPermission(data.Organization),
   true
);
/// AuthorizationUtil Implementation
///
internal static bool SwitchData(
   Map.Account admin,
   Map.Account account,
   Map.Data data,
   Map.BasePermission permission,
   bool enable
){
   if (!CanChangeData(admin, data)) return false;
   
   /// Asserts GRANT_PERMISSION if not specified
   ///
   Map.BaseParticipant bp =
      GetDataPermissionParticipant(
         account,
         data,
         permission
       );
   bool out_bool = false;
   if (enable)
   {
      if (bp != null) return true;
      bp = Factory.DataParticipationFactoryInstance.NewAccountDataParticipation(
         data, account, permission, AffectType.GRANT_PERMISSION
      );
      out_bool = Factory.DataParticipationFactoryInstance.AddParticipant(bp);
   }
   else
   {
      if (bp == null) out_bool = true;
      else out_bool = Factory.DataParticipationFactoryInstance.DeleteParticipant(bp);
   }
   return out_bool;
}

The AccountManagerShell reference implementation includes the TestSecurityLayerAction class, which is used to validate permission support.

[ top ]

Accounts

Accounts are the programmatic representation of a real or system user, including login credentials and additional descriptive detail.

Each account is intended to be a self-sufficient entity. Implementations requiring multiple users per account may easily replicate this behavior using the PAC.

Participation

Accounts do not support direct participation. For permissions, is not possible to directly apply a permission, such as AccountCreate, to an Account.

Participant

Accounts may participate in Roles, Groups, and Tags. At present, accounts do not support participations.

Permissions

Account level permissions are managed with the build in AccountAdministrators role.

Accounts may be affected with Data and Group permissions. Note: Accounts are not affected with Role permissions, rather, an Account participates in a role, and that role affects the role target with a permission.

[ top ]

Groups

Groups are used to create hierachical structures of Data (directories), Accounts, or Buckets (non-directory data aggregate).

Participation

Roles and Accounts may participate in Groups. Data must belong to a DirectoryGroup, and is a logic group instead of a participatory group.

Participant

Groups may participate in Roles and Groups.

Permissions

Group level permissions are managed with the build in DataAdministrators role.

Groups may be affected with Data, Role, and Group permissions.

[ top ]

Data

Data are normalized blobs of bytes, compressed if supported, and encrypted if specified.

Participation

Data does not support direct participation, except for a specific DirectoryGroup.

Participant

Data may participate in Roles, Groups, and Tags.

Permissions

Data level permissions are managed with the build in DataAdministrators role. Data permissions are marshalled through ownership, the admin role, or group or role affects.

[ top ]

Roles

Roles are used to aggregate accounts and other roles.

Participation

Accounts and Roles may participate in Roles.

Participant

Roles may participate in Roles and Groups.

Permissions

Role level permissions are managed with the build in AccountAdministrators role.

Roles may be affected with Data, Role, and Group permissions.

[ top ]

Tags

Tags are used to collect objects in abstracted groups.

Participation

Accounts and Data may participate in Tags.

Participant

Tags may not be used as participants in other participations.

Permissions

Tags may not be affected with permissions.

[ top ]

Forum

Forums are Groups and Data accessible by Accounts participating in applicable Roles. Forum Users (Accounts that participate) may add Data, or respond to posted Data.

[ top ]

Cryptography and Security

Admissions

Cryptography is not security, and encrypting data does not directly translate into secure data. Account Manager does not include any customized or re-imagined cryptographic libraries. It uses existing .NET cryptographic libraries, and Rijndael AES 192/256.

The cryptographic features in Account Manager provide easy-of-use and reuse, and combined symmetric and asymmetric encryption. All cryptographic features are exposed through the CoreLib::SecurityManager class and related interfaces and factories. There is no direct and indirect expectation that any included or generated keys are more or less secure than otherwise may be afforded by following best practices.

To encourage the use of best security practices, the AccountManager::Vault class uses the SecurityManager class to encrypt and/or encipher the AccountManagerObjects::Data class against a tertiary private key that is intentially saved outside of the program and database, and which itself may be enciphered. The Data class may also be enciphered against a volatile ciphertext which is stored in memory, but never to disk, in code, or in the database.

These features are provided to help developers and organizations follow best security practices, and are in no way meant to replace them. Please consult a qualified security expert before using this library is going to be used in a PCI and/or SOX compliant environment.

Keys

Account Manager ships with a default set of encryption keys:

  • (CoreLib) PublicSignKey - The public half of the PrivateSignKey.
  • (CoreLib) ShipKey - A global set of asymmetric and symmetric keys signed by PrivateSignKey.
  • (CoreLib) ProductKeys - 50 pregenerated keys, all signed with PrivateSignKey, and with private keys encrypted by Ship Key.
  • (LicenseMaster2) PrivateSignKey - The asymmetric private key used to sign the shipped keys, and also used for generating licenses. DO NOT PUBLISH THIS KEY (Yes, there is an irony to not publishing this key, and yet, an example is included in the download).

Replacing Keys

Replacing keys in an existing installation will result in unrecoverable data.

To replace the keys:

  1. Build the License Master 2 solution (no Mono build at present), and run License Master 2.
  2. Click Generate Product Keys to create the new key pairs.
  3. Copy the PublicSignKey, ShipKey, and ProductKeys C# files to CoreLib2/Core/Tools/Security/Keys
  4. Copy the PrivateSignKey C# file to LicenseMaster2/Core/Tools/Security/Keys
  5. Close the License Master 2 application, and rebuild CoreLib2 and LicenseMaster2.
  6. Run LicenseMaster2 again, and click Generate Trial License Class.
  7. Copy the TrialLicense C# file to CoreLib2/Core/Tools/License
  8. Rebuild all related projects.

Public Sign Key

The Public Sign Key is used to validate data against a supplied signature, where the data was signed with the Private Sign Key.

Ship Key

The Ship Key is accessible from SecurityManagerFactory.ShipKey, and is primarily used for the ProductKey ring, and can be used for the most basic confirmations, and, optionally, for confirming Trial Licenses.

Product Key

When Account Manager is first started, a CoreLib::ApplicationContext object is created. The ApplicationContext object emits its own startup configuration, and will randomly select a product key if one wasn't selected. From that point forward, all subordinate encryption will be first passed through the selected product key.

Like the Ship Key, the randomly selected Product Key serves a specific purpose as a signatory, and for some limited encryption.

Organization Key

When a new Organization is created in Account Manager, a new pair of asymmetric and symmetric keys are generated. The new key pair is encrypted with the randomly selected Product Key, which in turn is encrypted by the Ship Key. The new key pair is stored in the database.

Encryption at the Organization level starts with the Organization encryption keys.

Design and Intent of Product, Ship, and Organization Keys

Individually, the Product, Ship, and Organization keys provide little more than obfuscation because anyone with access to the hardware or database could retrieve the keys and decrypt data. By encrypting the Organization key with the Product key, someone would need access to both the database and the application, or need runtime access to the application memory, to decrypt anything. Breaching the database or the server file system is not enough to obtain the requisite keys. Both database and application server would have to be breached, or the the application memory would have to be attacked.

These attack vectors are possible, and certainly not new. By following best practices in setting access rights to the database and application server, the risks are mitigated.

Encrypt and Encipher with SecurityManager

The SecurityManager class includes both symmetric (private, public, or both) and asymmetric keys. By default, the asymmetric key is encrypted with the symmetric key.

  • The Encrypt method uses the public asymmetric key.
  • The Decrypt method uses the private asymmetric key, if available.
  • The Encipher method uses the encrypted symmetric key, decrypting it beforehand if the private key is available.
  • The Decipher method uses the symmetric key, same as Encipher.

Account Manager uses Encipher and Decipher to encrypt data, and uses Encrypt and Decrypt to protect the asymmetric key.

Example: Obtaining Organization Keys

The Product exposes the Organization level keys through the SecurityManager property.

   Product product = ...;
   ISecurityManager sm = product.SecurityManager;
   byte[] plain_data = ...;
   byte[] enciphered_data = sm.Encipher(plain_data);

Account Ciphers

Account Manager supports specifying a volatile cipher at the Account level. However, it does not include any mechanism to store the cipher.

Vault

BETA NOTE: Vault is currently tied with the Product.ProductUser account, and needs to be refactored.

The AccountManager::Vault class is at the bottom of the myriad encryption keys and ciphers. The Vault class was created from work done on the original Vault application (latest version: Vault 2).

Vault uses an asymmetric key pair that is encrypted with the Organization level key, optionally enciphered by a cipher text, and saved elsewhere on the computer. Instead of using the same symmetric key to encrypt data, it generates a new symmetric key, encrypts it, and saves that to the database at the Account level, once more splitting the keys apart. Vault creates new symmetric keys every time it is successfully instantiated (meaning the private key must be decrypted and deciphered), and optionally everytime it is instructed to rotate the current key.

Summary

The approach taken to cryptography in Account Manager was not to take one at all: use industry and community tested libraries.

The approach taken to security of the cryptographic keys was to assume that everything is breachable, and to mitigate that risk by splitting up the keys and offering an entry level safeguard for those keys. However, if sensitive data needs to be encrypted, it is important to consult a qualified security consultant to make sure your implementation is compliant relative to the sensitive data.

[ top ]

License Management

BETA NOTE

Licensing works in Account Manager, but there is currently no multi-user reference implementation that validates licenses. Refer to Vault (included in download) for a detailed implementation.

Introduction

Account Manager includes built-in licensing for application and web-based products. Licenses are deliverable as serialized encrypted files that are signed with the Private Sign Key (refer to Cryptography and Security section). The purpose of the License is to authorize accessibility.

If you plan on using the License Master 2 implementation (included in download), follow the steps in Cryptography and Security::Replace Keys. It will serve no purpose to use the example keys included in the download to create licenses, only to have everyone else be able to spoof them.

The Vault application includes an Organization-level license generation tool, and can also export limited key sets for custom licensing. This implementation generates a new master license key pair and is ideal to use one Account Manager product to serve licenses to another Account Manager product, or for Web products where the licensed user is on the same system as the license owner (or, in otherwords, where the license can be validated).

Its easier to use License Master 2, which is more of a reference implementation. However, the Vault approach is much more configurable and extensible.

License Key

License keys encapsulate meta data about accessibility and authorization. The keys are only meaningful to you, the developer, and the CoreLib::LicenseManager deserializer. It doesn't matter whether anyone else knows what the key includes because the key itself includes no security measures. License key security is handled by encrypting and signing the key. This means if customers ever need to receive a license, it will be an ugly XML monstrosity. However, depending on the implementation, they may never need to see it.

There are two versions of the license key: 1) the full version, and 2) a shorter public version which masks dates and some meta data.

The full license key is a 56-character string with 47 data points. The key template is: PPP-FFffLLll-VVVV-CCCCCC-AAA-DDD-GGGGGGGG-EEEEEEEE-S-UUU

  • P = (char) product identifier
  • F = (int) First major version
  • f = (int) First minor version
  • L = (int) Last major version
  • l = (int) Last minor version
  • V = (int) Vendor
  • C = (int) Customer/ Purchase Id
  • A = (char; IL1 | TRI) Access Level
  • D = (int) Access Level Data
  • G = (int / yyyyMMdd) Grant Date
  • E = (int / yyyyMMdd) Expire Date
  • S = (char; U | D | S | M) Consumption Type
  • U = (int) Max consumption level, based on type

License Generation

The Vault application uses the CoreForms::NewLicense and CoreForms::LicenseConfig forms to generate licenses, and is a good example. Another less refined example is in License Master 2.

A new license is constructed by building the key according to the template. The key is encrypted with the Ship Key, and signed with the Private Sign Key. The deliverable license includes the signature and encrypted text.

License Validation

A license is always expected to be in the serialized and encrypted format. Having only the license key is not enough.

The serialized license and signature are used to instantiate a new License object. The License class is sealed and only exposes read-only properties. The only way to create a License class is to provide the encrypted key, the signature, and optionally, the signatory (a SecurityManager reference).

Within the License initialization is a signature validation. If it fails, the license is entirely rejected. If the license does not follow the template format exactly, it is likewise rejected. Afterwards, the license is validated against the expiry and consumption type.

Trial Licenses

If desired, trial licenses can be used. Trial licenses are handled differently from regular licenses. When constructed, they as volatile and otherwise unusable as a volatile license is invalid. To be valid, the trial license must be confirmed by using the LicenseManager::ConfirmTrialLicense method. After confirmation, a new temporary license is created.

Trial licenses are ideal for setting up temporary and possibly restricted access.

End-User License Agreements (EULA)

BETA NOTE: Currently implemented for stand-alone applications, and not for Web applications.

LicenseManager includes support for signing EULA and License agreements for later reference. The signed agreements are saved to disk, and can be confirmed when starting an application to assert that an end-user has agreed to any terms and conditions. This also provides accountability when determining whether or not an end user read and agreed to the terms and conditions.

[ top ]