= ABAC = [[TOC]] The ABAC project has designed and implemented tools for using Attribute-Based Access Control, a scalable authorization system based on formal logic. It maps principals to attributes and uses the attribute to make an authorization decision, e.g., if user1 has the login attribute the login program will alllow them to log in. This library, libabac, is a base on which to build those tools. It is in use in the [http://fedd.deterlab.net DETER federation system] and being integrated with the [http://geni.net GENI network testbed]. If you are new to ABAC, you may find the [http://groups.geni.net/geni/wiki/TIEDABACModel introductory material] from our [http://groups.geni.net/geni/wiki/TIED TIED project] helpful. That material summarizes the power and semantics of ABAC and links to [http://groups.geni.net/geni/wiki/TIEDABACDemo examples of ABAC policy] illustrated using an early example of [CrudgeDocs the Crudge ABAC policy browser]. The latest ABAC RT0 version is [http://abac.deterlab.net/src/abac-0.1.4.tar.gz ABAC 0.1.4] ([http://abac.deterlab.net/src/abac-0.1.4.tar.gz.asc signature]). == What's Included == The core libabac distribution includes: * libabac, a linkable C/C++ library * Perl and Python bindings to libabac * A standalone java implementation * creddy, a command line credential management tool These ABAC tools use libabac * [CrudgeDocs crudge] a visual editor for ABAC policies and proofs * [http://abac.deterlab.net/java/crudge.jnlp webstart link] * [CredPrinterDocs credential printer] an XMLRPC service to convert credentials to a text representation == Getting started: Installing libabac == Installing libabac is a straightforward {{{configure}}}, {{{make}}}, {{{make install}}} sequence. There are a few things to be careful of depending on your operating system. === Software Dependencies === Libabac depends on openssl and the [http://www.aleksey.com/xmlsec/ xmlsec1 digital signature library]. Most unix-like operating systems have openssl installed and have xmlsec1 as a standard package. The perl and python bingings are generated by [http://www.swig.org/ swig] 1.3, and the build system uses automake and some autoconf macros. To set up Ubuntu for building libabac: {{{ $ sudo apt-get -y install autoconf-archive automake g++ git-core libtool python-dev swig libxmlsec1-dev }}} Under FreeBSD, use the ports system to install the following packages: {{{ devel/libtool devel/automake devel/autoconf-archive devel/swig13 devel/pkg-config security/xmlsec1 lang/perl lang/python }}} If you plan to build the java implementation on Ubuntu you should also {{{ $ apt-get -y install openjdk-7-jdk ant ant-optional }}} Similarly in FreeBSD install {{{ devel/apache-ant java/openjdk6 }}} We have seen no differences under the various JDKs. === Installation === Then get the [http://abac.deterlab.net/src/abac-0.1.4.tar.gz source], untar it, change to the {{{abac-0.1.4}}} directory and do the standard install sequence: {{{ # Ubuntu users: ./configure --prefix=/usr $ ./configure $ make $ sudo make install }}} To confirm that your install succeeded: {{{ $ cd examples $ make }}} Libabac uses the standard GNU install prefix of {{{/usr/local}}}. '''If you are on Ububtu or another distribution that does not search /usr/local/lib for shared libraries, make sure you use ./configure --prefix=/usr''' === Tracking Development === Current released [http://abac.deterlab.net/src/abac-0.1.4.tar.gz source] [http://abac.deterlab.net/src/abac-0.1.4.tar.gz.asc signature] If you would like to track the libabac development, you can pull code from out publically available git repository: {{{ $ git clone git://abac.deterlab.net/abac.git }}} Current sources can be [/browser browsed on the web]. === Releases === See the [source:/doc/ChangeLog ChangeLog] for details about each release * 2013-05-20: ABAC 0.1.4 released * 2011-04-11: Crudge 1.0 released * 2011-03-30: ABAC 0.1.3 released * 2010-10-01: ABAC 0.1.2 released * ~~2010-09-17~~ 2010-09-20: ABAC 0.1.1 released * '''Update:''' We fixed a one-line bug in creddy. If you downloaded this over the weekend, please fetch it again. Old releases are at [http://abac.deterlab.net/src/ http://abac.deterlab.net/src/] == Using libabac == Libabac allows developers to import signed ABAC statements about principals and attributes and prove that certain principals have those attributes ([http://groups.geni.net/geni/wiki/TIEDABACModel more detail about ABAC logic]). The basic structures that libabac uses to support those operations are identities, attributes, and a context for those. The [/browser/doc/API?tag=0.1.4 API document] lists all the interfaces to the library, but this section is intended to impart some meaning to the various structures. The java interface is slightly different in detail, but uses the same constructs. These examples use python so that the interested user can basically type along with the descriptions. Our native java implementation, [JavaSupport jabac] follows the same API, but differs in some details. Full [http://abac.deterlab.net/javadoc/index.html javadocs] are available for jabac, and the examples below are easily translated into that interface. === Identities === An identity in ABAC is a principal who has issued or can issue attributes (valid ABAC statements). libabac allows one to create new principals and to import identities from X.509 identity certificates. To create a principal from scratch that resides in memory: {{{ import ABAC id = ABAC.ID("newGuy", 5*365*3600*24) }}} The first parameter is a common name to use for the identity and the second parameter is the validity. Associated with this identity is a public/private key pair that can be used to sign new ABAC attributes. In ABAC statements the principal is referred to an identifier derived from its public key. You can access that identitfer using the keyid() method: {{{ import ABAC id = ABAC.ID("newGuy", 5*365*3600*24) print id.keyid() }}} prints something like: {{{ 481365b6eced33c0b06674d506b92f01f69e05fd }}} The other way to initialize an identity is to read the contents from an X.509 certificate file, or from the contents of such a file (referred to as a chunk). The number of parameters determines the constructor in use between the in-memory constructor above (2 parameters) and the from-a-file constructor below (2 parameters). The chunk constructor also takes one parameter, but has a different name ({{{ID_chunk}}}). {{{ import ABAC id1 = ABAC.ID("./newGuy.pem") try: f = open("./newGuy.pem") id2 = ABAC.ID_chunk(f.read()) f.close() except: pass print "%s %s" % (id1.keyid(), id2.keyid()) }}} The {{{write_cert}}} and {{{write_cert_file}}} methods write the X.509 certificate from an identity. The private keys can similarly be written using {{{write_privkey_file}}} and {{{write_privkey}}} and loaded with {{{load_privkey}}}. The following snippet creates an identity, writes it to 2 files and reads it from those files printing the results. The output files will not contain the private key. {{{ import ABAC id = ABAC.ID("newGuy", 5*365*3600*24) id.write_cert_file("./newGuy.pem") id1 = ABAC.ID("./newGuy.pem") try: f = open("./newGuy.pem") id2 = ABAC.ID_chunk(f.read()) f.close() except: pass print "%s %s %s" % (id.keyid(), id1.keyid(), id2.keyid()) }}} Libabac generates self-signed certificates and does not check the signatures of imported certificates. Use an external library to do that. === Attributes === Attributes are the signed ABAC statements that make up proofs. libabac can import them from files and generate new ones. This section describes creating them. [http://groups.geni.net/geni/wiki/TIEDABACModel As we have seen], an ABAC statement assigns an attribute (signed by an identity) to another identity or set of identities with a given attribute. Here is how libabac constructs an attribute encoding {{{A.admin <- B}}}. That attirbute means that identity A is assigning identity B the {{{admin}}} attribute for use in later proofs. {{{ import ABAC a = ABAC.ID("A", 24 * 3600 * 365 * 20) b = ABAC.ID("B", 24 * 3600 * 365 * 20) attr = ABAC.Attribute(a, "admin", 24 * 3600 * 365 * 20) attr.principal(b.keyid()) attr.bake() attr.write_file("attr.xml") }}} The Attribute constructor takes the issuing identity, the attribute being assigned and the validity period of the assertion (in seconds). This code assigns a principal to that class using the {{{principal}}} member. The {{{role}}} member and {{{linking_role}}} members can be used to construct the other kinds of attributes. The {{{bake}}} member finalizes the attribute and creates a signed format for export, which one can write using the {{{write}}} and {{{write_file}}} members, that are analogous to {{{write_cert}}} and {{{write_cert_file}}} members of identities. Though applications may treat them as opaque, the current format is a [http://groups.geni.net/geni/wiki/TIEDABACCredential signed XML format]. The {{{bake}}} method exists so that Attributes can contain conjunctions. If identity A wants to state that friendly admins are admins who are friendly ({{{A.friendly_admin <- A.friendly & A.admin}}}), this code will make it: {{{ import ABAC a = ABAC.ID("A", 24 * 3600 * 365 * 20) attr = ABAC.Attribute(a, "friendly_admin", 24 * 3600 * 365 * 20) attr.role(a.keyid(), "friendly") attr.role(a.keyid(), "admin") attr.bake() attr.write_file("attr.xml") }}} === Contexts and Proofs === An ABAC Context contains all the identities and assertions that are known in a specific authorization domain. Given a Context, a programmer loads the identities that are trusted to issue attributes and the attributes. A Context can load either of these from files or data chunks. In python and perl data chunks are strings/scalars while in C and C++ they are simple structs. IDs and Attributes export the {{{cert_chunk}}} method to support the translation. Here is an example of generating credentials and loading them into the a Context. This shows the A principal loading the ({{{A.friendly_admin <- A.friendly & A.admin}}} Attribute and then assigning {{{friendly}}} and {{{admin}}} attributes t identity B and C. {{{ import ABAC ctxt = ABAC.Context() a = ABAC.ID("A", 24 * 3600 * 365 * 20) b = ABAC.ID("B", 24 * 3600 * 365 * 20) c = ABAC.ID("C", 24 * 3600 * 365 * 20) attr = ABAC.Attribute(a, "friendly_admin", 24 * 3600 * 365 * 20) attr.role(a.keyid(), "friendly") attr.role(a.keyid(), "admin") attr.bake() ctxt.load_id_chunk(a.cert_chunk()) ctxt.load_attribute_chunk(attr.cert_chunk()) attr = ABAC.Attribute(a, "friendly", 24 * 3600 * 365 * 20) attr.principal(b.keyid()) attr.bake() ctxt.load_attribute_chunk(attr.cert_chunk()) attr = ABAC.Attribute(a, "admin", 24 * 3600 * 365 * 20) attr.principal(b.keyid()) attr.bake() ctxt.load_attribute_chunk(attr.cert_chunk()) attr = ABAC.Attribute(a, "admin", 24 * 3600 * 365 * 20) attr.principal(c.keyid()) attr.bake() ctxt.load_attribute_chunk(attr.cert_chunk()) }}} Asking the question is done using {{{ctxt.query()}}}. The following asks if b is an A.friendly_admin: {{{ # Same code as above to initialize the ids and load the context ok, proof = ctxt.query(a.keyid() + ".friendly_admin", b.keyid()) }}} The first parameter to {{{Context.query}}} is the attribute of interest and the second is the keyid of an identity. A tuple is returned holding (success, proof) where success is true if the identity has the attribute and proof is a list of abac statements that make up the proof. === Credentials and Roles === Credentials are the abstraction of ABAC statements and Roles are the abstraction of the terms of an ABAC statement. A Credential is made up of two Roles, a head and a tail that make the two sides of the ABAC statement. There are a set of accessors to parse the contents of a role, described in the [/browser/doc/API?tag=0.1.4 API docs], and roles are primarily of interest in printing and exploring the proof. Credentials are useful in communicating proof contents outside the program. In addition to {{{head}}} and {{{tail}}} accessors that access the Roles, a Credential has a {{{attribute_cert()}}} method that returns the exportable content of the assertion and an {{{issuer_cert()}}} that returns the issuer's X.509 certificate (sans private key). These outputs are chunks, useful for writing to files or importing into other contexts. The following code prints the proof of our earlier successful question and saves it to files. This is not exemplary python file handling, but the point is to see the accessors: {{{ import sys # Same code as above to initialize the ids and load the context ok, proof = ctxt.query(a.keyid() + ".friendly_admin", b.keyid()) if not ok: sys.exit(1) for i, c in enumerate(proof): print "%s <- %s" % (c.head().string(), c.tail().string()) open("./id%d.pem" % i, "w").write(c.issuer_cert()) open("./attr%d.xml" % i, "w").write(c.attribute_cert()) }}} == Next Steps == In addition to the [/browser/doc/API?tag=0.1.4 API description] the code for the [CredPrinterDocs credential printer] is [/browser/cred_printer available]. It is a fairly complete example of using python and libabac. There are [NewStuff new features] being worked on in the git repository. == Contacts == * [http://lists.deterlab.net/listinfo/abac-dev devevelopers mailing list] * Ted Faber faber@ISI.EDU * Mei-Hui Su mei@ISI.EDU * Steve Schwab schwab@ISI.EDU