Credential Printer
The credential printer service is an XMLRPC service to convert ABAC credentials encoded as X.509 certificates into a text format. While libabac is widely portable through swig, some programming environments cannot import the library, yet would like to see the contents of credentials. The credential printer provides access.
The example code
Installing the service
We distribute the credential printer as a python application. It depends on the standard installation and the M2Crypto package, available from several places. It also depends on libabac.
Once the prerequisites are installed, download the credential printer source and untar it, change to the cred_printer-1.10
directory and run the standard python install script (as root
):
$ tar xzf cred_printer-1.10.tar.gz $ cd cred_printer-1.10 $ sudo python ./setup.py install
This will install a python egg into your site-packages and two python scripts, cred_server.py
and cred_client.py
into your standard biraries directory (/usr/local/bin
on FreeBSD or Ubuntu).
Because the installation runs as root
, you may need to delete the distribution directory as root
:
$ cd .. $ sudo rm -rf cred_printer-1.10.tar.gz
The source is also in the ABAC git repository. You can get this by:
git clone git://abac.deterlab.net/abac.git
Running the server
The server takes an optional argument, --cert
and a certificate with which to identify itself under SSL/https. If omitted, the server will run under http, unencrypted and unauthenticated. If run under SSL, the server expects clients to supply a certificate, but does not vaildate it's authorization chain. This is for future expansion using ABAC authorization to the server and self-certifying identities. The directions for making a fedid certificate will also create a valid certificate for this use.
The server also takes a --port
argument defining the port to listen on. By default it listens on port 13232.
Assuming that ./cert.pem
contains a certificate and key for the server:
$ cred_server.py --cert ./cert.pem
starts the server under SSL/https listening on port 13232,
$ cred_server.py --port 54321 --cert ./cert.pem
starts the server under SSL/https listening on port 54321
$ cred_server.py --port 54321
starts the server under http listening on port 54321, and
$ cred_server.py
starts the server under http on port 13232.
Running the client
The client is primarily to demonstrate the server functionality, but may prove useful itself. It takes 2 optional parameters and a list of filenames, and prints the decoded credentials on the standard output.
The --url
option points to the server. By default it is http://localhost:13232
. It can be set explicitly by setting this option, or by setting the CRED_URL
environment variable. Using an https URL without the --cert
option will fail.
The --cert
option specifies a file to use for an https exchange. If the option is given, any URL will be traeted as https; if omitted any URL will be treated as http. The directions for making a fedid certificate will also create a valid certificate for this use.
To try the client, start the server as an http server on the default port:
$ cred_server.py
Download the attached example credential directory, and untar it somewhere convenient:
$ tar xvzf experiment_create.tgz x experiment_create/ x experiment_create/Acme_ID.pem x experiment_create/Acme_experiment_create__Acme_partner_experiment_create_attr.xml x experiment_create/Acme_partner__Globotron_attr.xml x experiment_create/Acme_private.pem x experiment_create/Alice_ID.pem x experiment_create/Alice_admin__Bob_attr.xml x experiment_create/Alice_private.pem x experiment_create/Bob_ID.pem x experiment_create/Bob_private.pem x experiment_create/Globotron_ID.pem x experiment_create/Globotron_admin__Alice_attr.xml x experiment_create/Globotron_experiment_create__Globotron_admin_power_user_attr.xml x experiment_create/Globotron_private.pem
and run the client with the contents of the experiment_create directory.
$ cred_client.py experiment_create/*
produces:
000: identity 85613e9e0e09ce3e05a8d4ef38a4b82daf14fa58 Acme 001: attribute 85613e9e0e09ce3e05a8d4ef38a4b82daf14fa58.experiment_create <- 85613e9e0e09ce3e05a8d4ef38a4b82daf14fa58.partner.experiment_create Acme.experiment_create <- Acme.partner.experiment_create 002: attribute 85613e9e0e09ce3e05a8d4ef38a4b82daf14fa58.partner <- 7c49310d78f138cb0d1f2fcdab863b9e30dab426 Acme.partner <- Globotron 003: Error, code -1 004: identity 85818428a71f18f8eb1e0d52f427a75101a912d6 Alice 005: attribute 85818428a71f18f8eb1e0d52f427a75101a912d6.power_user <- c5ca272947b3d7664c4e6e1db734dfab0291eba4 Alice.power_user <- Bob 006: Error, code -1 007: identity c5ca272947b3d7664c4e6e1db734dfab0291eba4 Bob 008: Error, code -1 009: identity 7c49310d78f138cb0d1f2fcdab863b9e30dab426 Globotron 010: attribute 7c49310d78f138cb0d1f2fcdab863b9e30dab426.admin <- 85818428a71f18f8eb1e0d52f427a75101a912d6 Globotron.admin <- Alice 011: attribute 7c49310d78f138cb0d1f2fcdab863b9e30dab426.experiment_create <- 7c49310d78f138cb0d1f2fcdab863b9e30dab426.admin.power_user Globotron.experiment_create <- Globotron.admin.power_user 012: Error, code -1
Credentials that represent identities, such as the first entry (001) above are marked as identity certificates and both the keyid (a SHA1 hash of the key as described in RFC 3280, and the certificate CN (common name) are displayed. Certificates created through Creddy put a human-readable name in the certificate CN.
Credentials that represent attribute assignments are rendered as in line 002. The attribute identifier is printed and the certificate presented in RT0 format both with keyids and human-readable names.
For data that does not represent either an identity or an attribute, the error line is printed. The code is a libabac return code. The errors in this example come from the private key files and README files in that example directory.
More verbose output that breaks down the contents of the credentials in detail is generated by using --verbose
:
produces:
000: identity 85613e9e0e09ce3e05a8d4ef38a4b82daf14fa58 Acme 001: attribute 85613e9e0e09ce3e05a8d4ef38a4b82daf14fa58.experiment_create <- 85613e9e0e09ce3e05a8d4ef38a4b82daf14fa58.partner.experiment_create Acme.experiment_create <- Acme.partner.experiment_create head: pretty_principal: Acme principal: 85613e9e0e09ce3e05a8d4ef38a4b82daf14fa58 role: experiment_create tail: pretty_principal: Acme principal: 85613e9e0e09ce3e05a8d4ef38a4b82daf14fa58 role: experiment_create linked_role: 85613e9e0e09ce3e05a8d4ef38a4b82daf14fa58.partner 002: attribute 85613e9e0e09ce3e05a8d4ef38a4b82daf14fa58.partner <- 7c49310d78f138cb0d1f2fcdab863b9e30dab426 Acme.partner <- Globotron head: pretty_principal: Acme principal: 85613e9e0e09ce3e05a8d4ef38a4b82daf14fa58 role: partner tail: pretty_principal: Globotron principal: 7c49310d78f138cb0d1f2fcdab863b9e30dab426 003: Error, code -1 004: identity 85818428a71f18f8eb1e0d52f427a75101a912d6 Alice 005: attribute 85818428a71f18f8eb1e0d52f427a75101a912d6.power_user <- c5ca272947b3d7664c4e6e1db734dfab0291eba4 Alice.power_user <- Bob head: pretty_principal: Alice principal: 85818428a71f18f8eb1e0d52f427a75101a912d6 role: power_user tail: pretty_principal: Bob principal: c5ca272947b3d7664c4e6e1db734dfab0291eba4 006: Error, code -1 007: identity c5ca272947b3d7664c4e6e1db734dfab0291eba4 Bob 008: Error, code -1 009: identity 7c49310d78f138cb0d1f2fcdab863b9e30dab426 Globotron 010: attribute 7c49310d78f138cb0d1f2fcdab863b9e30dab426.admin <- 85818428a71f18f8eb1e0d52f427a75101a912d6 Globotron.admin <- Alice head: pretty_principal: Globotron principal: 7c49310d78f138cb0d1f2fcdab863b9e30dab426 role: admin tail: pretty_principal: Alice principal: 85818428a71f18f8eb1e0d52f427a75101a912d6 011: attribute 7c49310d78f138cb0d1f2fcdab863b9e30dab426.experiment_create <- 7c49310d78f138cb0d1f2fcdab863b9e30dab426.admin.power_user Globotron.experiment_create <- Globotron.admin.power_user head: pretty_principal: Globotron principal: 7c49310d78f138cb0d1f2fcdab863b9e30dab426 role: experiment_create tail: pretty_principal: Globotron principal: 7c49310d78f138cb0d1f2fcdab863b9e30dab426 role: power_user linked_role: 7c49310d78f138cb0d1f2fcdab863b9e30dab426.admin 012: Error, code -1
The Interface
The server expects an XMLRPC array of XMLRPC structs containing the credentials to represent. In the input, each struct has two fields:
- id
- a string used to map from input to output credentials
- credential
- a Binary object holding the credential bits
The ids are free form strings used to map the input to the output. The credential bits are also returned, but matching ids can be easier. {{{cred_client.py}} uses 3 digit serial numbers (the first line of the output), but an application can use any unique identifier. In fact, the server never confirms their uniqueness, but matching input to output can be tricky without it.
The server validates and translates the credentials into text and returns them in a more complex array of structs. Notice that the credentials must be validated. To decode an attribute certificate, the identity credential of the issuer must be included in the request.
The output is an array of structs with the following members:
- id
- a string used to map from input to output credentials (identical to input)
- credential
- a Binary object holding the credential bits (identical to input)
- type
- a string indicating what the credential encodes. Will be one of be "identity", "attribute", or "unknown".
- str
- a string, the representation of the attribute or identity in terms of keyids
- auxstr
- a string, the representation of the attribute or identity in terms of hunam-readable names (CNs). If CNs are missing or unresolvable, the keyids will be used.
- errcode
-
an integer, the libabac return code of the attempted conversion. If this is non-zero, the str and auxstr contents are undefined. (
cred_server.py
sets them to the empty string, but do not rely on that.)
Attribute certificates include two additional fields containing the parsed contents of the head and tail of the credential. These are in struct fields head and tail. Each of those structs containe between 2 and 4 of these fields, corresponding the the analogous Creddy fields:
- principal
- the keyid of the principal (always prsent)
- pretty_principal
- the human-readable name of the principal (CN) if known, or the keyid if not (always present)
- role
- simple role (no dots). Present if a role is being assigned
- linked_role
- linked role, present if a this is a linking role
The output array is not guaranteed to be in the same order as the input array (and generally will not be). Use the id member to match input and output.
Just for concreteness, here is the python encoding for a simple request and response:
Request
[ {'credential': <xmlrpclib.Binary instance at 0x803667cb0>, 'id': '000'}, {'credential': <xmlrpclib.Binary instance at 0x803667cf8>, 'id': '001'}, {'credential': <xmlrpclib.Binary instance at 0x803667d40>, 'id': '002'}, {'credential': <xmlrpclib.Binary instance at 0x803667d88>, 'id': '003'} ]
Four dicts/structs are encoded with a serial number as id and the binary of the credential (the keyids differ in this example).
Response
[ {'auxstr': 'Acme', 'credential': <xmlrpclib.Binary instance at 0x803667cb0>, 'errcode': 0, 'id': '000', 'str': 'bb2f2f3544daa44f9f8f3b5cd2d8d71f6dc2974d', 'type': 'identity'}, {'auxstr': 'Acme.buy_rockets <- Acme.preferred_customer', 'credential': <xmlrpclib.Binary instance at 0x803667cf8>, 'errcode': 0, 'head': {'pretty_principal': 'Acme', 'principal': 'bb2f2f3544daa44f9f8f3b5cd2d8d71f6dc2974d', 'role': 'buy_rockets'}, 'id': '001', 'str': 'bb2f2f3544daa44f9f8f3b5cd2d8d71f6dc2974d.buy_rockets <- bb2f2f3544daa44f9f8f3b5cd2d8d71f6dc2974d.preferred_customer', 'tail': {'pretty_principal': 'Acme', 'principal': 'bb2f2f3544daa44f9f8f3b5cd2d8d71f6dc2974d', 'role': 'preferred_customer'}, 'type': 'attribute'}, {'auxstr': 'Acme.preferred_customer <- 9b2c1d0949e667a2264b200602aba5f3560e8404', 'credential': <xmlrpclib.Binary instance at 0x803667d40>, 'errcode': 0, 'head': {'pretty_principal': 'Acme', 'principal': 'bb2f2f3544daa44f9f8f3b5cd2d8d71f6dc2974d', 'role': 'preferred_customer'}, 'id': '002', 'str': 'bb2f2f3544daa44f9f8f3b5cd2d8d71f6dc2974d.preferred_customer <- 9b2c1d0949e667a2264b200602aba5f3560e8404', 'tail': {'pretty_principal': '9b2c1d0949e667a2264b200602aba5f3560e8404', 'principal': '9b2c1d0949e667a2264b200602aba5f3560e8404'}, 'type': 'attribute'}, {'auxstr': '', 'credential': <xmlrpclib.Binary instance at 0x803667d88>, 'errcode': -1, 'id': '003', 'str': '', 'type': 'unknown'} ]
The first dict/struct is an identity, the second and third are attributes, and the fourth an invalid certificate.
Attachments (4)
-
cred_printer-1.00.tar.gz (7.2 KB) - added by 14 years ago.
credential printer distribution
-
cred_printer-1.01.tar.gz (7.7 KB) - added by 13 years ago.
Version 1.01
-
cred_printer-1.10.tar.gz (7.7 KB) - added by 12 years ago.
Credential Printer source (Version 1.10)
-
experiment_create.tgz (10.4 KB) - added by 12 years ago.
Sample expriment directory
Download all attachments as: .zip