Changes between Initial Version and Version 1 of UniformClearinghouseAPIV2


Ignore:
Timestamp:
11/12/13 09:03:54 (10 years ago)
Author:
mbrinn@bbn.com
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • UniformClearinghouseAPIV2

    v1 v1  
     1[[PageOutline(1-2, Table of Contents)]]
     2== GENI Federation API’s ==
     3Marshall Brinn, GPO
     4
     5API Version 2  *** UNDER CONSTRUCTION ***
     6Revised: November 12, 2013
     7
     8
     9== Introduction ==
     10
     11
     12
     13This document proposes a set of standard API’s that any GENI-compatible Federation should or may provide. The document describes what is required and what is optional in the calls and responses to these APIs.
     14
     15The GENI Software Architecture rests on the interaction between different entities:
     16
     17''' Aggregates ''' : Collections of resources managed and presented in accordance with the AM API
     18
     19''' Members ''' : Experimenters or other human consumers of aggregate resources
     20
     21''' Authorities ''' : Services that manage assertions about members and their permissions with respect to aggregate resources.
     22
     23There are two fundamental authority types in GENI:
     24
     25 * '' Member Authority '' [MA]: Manages and asserts attributes about particular members
     26 * '' Slice Authority '' [SA]: Manages slice objects and generates credentials for members with respect to slices.
     27
     28A '' Federation '' is a collection of Authorities and Aggregates that establish mutual trust and common policies to facilitate the sharing of resources among members. A Registry is a software service representing a given Federation, providing lists of Slice Authorities, Member Authorities and aggregates associated with that federation, and providing a set of PKI certificates that any aggregate belonging to a given federation accepts as trust roots. The relationship of Federations to Registries is 1:1.
     29
     30The Authorities of any given Federation are free to implement their own Authorization (AuthZ) scheme. The API’s allow for passing credentials to the calls, but an Authority may choose to allow or disallow calls using logic and policies that are internal to that Federation. There is no universal (cross-Federation) requirement for any particular policy regarding Authority AuthZ.
     31
     32Authorities are fundamentally independent of one another. The objects defined at one Authority are not necessarily entitled to any services provided by another Authority. Each aggregate may choose to trust or not trust any particular Authority. Likewise, any Authority may chose to trust or not trust any other Authority.  A Registry may choose to advertise or not advertise any particular aggregate, regardless of whether that aggregate trusts the Authorities advertised by that Registry. Similarly, a given Slice Authority or Member Authority may be advertised by a single Registries or by multiple Registries. Registry API calls are unprotected. There is no notion of trust between Registries or between Registries and Authorities or Aggregates.
     33
     34This document describes the APIs of the Registry as well as the MA and SA. It is expected that a well-behaved GENI-compatible tool will allow for interacting with any Registry and Authority that implement the standard API’s described in this document.
     35
     36
     37
     38
     39
     40
     41
     42
     43
     44
     45== API General Properties ==
     46
     47The APIs described here share some common properties, which should be assumed for the rest of this document:
     48 * The wire-protocol is XML/RPC. It is thus language independent on both client and server side of the API calls.
     49 * Most calls are protected, running over SSL and thus requiring the caller to use its certificate and private key. Certain calls are unprotected and can be accessed with no requirement for a validated client-side certificate . Such calls will noted in the API documentation below.
     50 * Each call takes an ‘options’ argument, a dictionary allowing for passing specific non-standard/optional arguments
     51 * Each protected method takes a ‘credentials’ argument, a list of type/credential tuples that help the Registry or Authority invoke whatever AuthZ logic it may choose. As noted above, the Registry or Authority may choose to use or disregard these credentials. Unprotected methods do not take a ‘credentials’ argument.
     52 * Each Registry or Authority provides a get_version method, which describes the version number of the API provided, credential types supported, supplementary object fields and other data for interpreting API call returns.
     53 * A Registry or Authority is free to implement additional methods beyond those specified in this document.
     54 * The URN is the fundamental identifier in all Federation API’s. URN’s are globally unique at any given time, though not necessarily unique over time. Disambiguation for entities with the same URN over time may be provided by an optional UUID argument for certain API methods. The format of URN's is documented at http://groups.geni.net/geni/wiki/GeniApiIdentifiers.
     55
     56These API’s are provided in pseudo-code (i.e. language independent) format, with inputs and outputs (optional and required) described by comments, e.g.
     57
     58{{{
     59#!python
     60# Perform method fed_func
     61#
     62# Arguments:
     63#  argl : ...
     64#  credentials : list of {type : credential} tuples representing credentials provided by caller to support AuthZ on method call.
     65#      [NB: This argument will be omitted in descriptions below. ]
     66#  options : … [ Recognized options: ….]
     67#
     68# Return:
     69#  E.g. a list of dictionaries with these fields mandatory (…) and these fields optional (…)
     70def fed_func (arg1, arg2, credentials, options)
     71}}}
     72
     73
     74== API 'get_version' methods ==
     75
     76Different Federation Authorities will provide different sets of methods bundled into services. Further, they will manage different kinds of objects and support different details for these objects.
     77
     78Each Registry or Authority API provides a ‘get_version’ method, which provides information to the caller (or a tool composing calls for a tool user) about versions and options supported by that API. The call takes no argument and is unguarded (anyone can call it). The return from the get_version call will be a dictionary including the following entries (by key):
     79 * VERSION: A string with the version number of the Federation API (e.g. “10.0.7”). Note: this is the version of the API not the version of the implementation. This field is mandatory for all services.
     80 * SERVICES: The set of services the given URL supports   
     81 * CREDENTIAL_TYPES: A list of recognized credential types (e.g. [ABAC, SFA]) and list of supported credential versions on protected API methods.  ''[Authorities only]''
     82 * ROLES : A list of recognized roles for slice/project membership (optional for those Slice Authorities supporting membership).  ''[SA only]''
     83 * FIELDS: A dictionary of '''''supplementary''''' object field names (i.e. in additional to the required fields) and associated attributes including:
     84     * “OBJECT” provides the object to which the field belongs (if not the default authority object, i.e. SLICE for Slice Authority, MEMBER for Member Authority, Service for Registry). This field is mandatory for any field listed.
     85     * “TYPE” may be one of “URN”, “UID”, “STRING”, “DATETIME”, “EMAIL”, “KEY”,“BOOLEAN”, “CREDENTIAL”, “CERTIFICATE”. [NB. This set of types subject to change. See Appendix for more information on these data types.] This field is mandatory for any field listed.
     86     * “CREATE” attributes may be specified as “REQUIRED”, “ALLOWED” or “NOT ALLOWED” (default = “NOT ALLOWED”). These indicate whether the given supplementary field is required, allowed or prohibited in create calls. This attribute is optional for listed fields.
     87     * "MATCH" attributes may be specified as booleans TRUE or FALSE (default = TRUE). These indicate whether a given field may be specified in an match option of a lookup call. This attribute is optional for listed fields.
     88     * “UPDATE” attributes may be specified as booleans TRUE or FALSE (default = FALSE). These indicate whether the given field may be specified in an update call. This attribute is optional for listed fields.
     89     * “PROTECT” attributes may be labeled as “PUBLIC”, “PRIVATE” or “IDENTIFYING”. These are for the Member Authority Only to differentiate between public, identifying and private data fields on members. The default, if not provided, is "PUBLIC", and thus this attribute is optional.
     90
     91The FIELDS element of the get_version is optional for all services, as it only contains supplementary fields (which may not exist for a given service).
     92
     93Supplementary field names should be placed in a distinct namespace by a prefix unique to that federation, and starting with an underscore (e.g _GENI_,  _OFELIA_ , _FED4FIRE_ or _PROTOGENI_ etc.).
     94
     95The return from the get_version call will be used to construct and validate options to Registry and Authority API calls, as described in subsequent sections.
     96
     97The following page provides some example returns from different get_version calls.
     98
     99== Example get_version returns: ==
     100
     101The following is an example of a return from a get_version for an SA. The responses are all dictionaries via XMLRPC into the native implementation. They are shown here in JSON-like syntax:
     102
     103{
     104
     105“VERSION”: “10.0.7”,
     106
     107“SERVICES”: [“SLICE”, “PROJECT”, “SLICE_MEMBER”, “PROJECT_MEMBER”],
     108
     109"OBJECTS": [ "PROJECT" ],
     110
     111“CREDENTIAL_TYPES”: {“SFA”: [ "1" ]}, “ABAC” : ["1", "2"]},
     112
     113“ROLES” : [“LEAD”, “ADMIN”, “MEMBER”, “AUDITOR”, “OPERATOR” ],
     114
     115“FIELDS”: {
     116     
     117     "_GENI_PROJECT_UID": {"TYPE" : "UID", "UPDATE" : FALSE},
     118
     119     “_GENI_SLICE_EMAIL”: {“TYPE”: “EMAIL”, “CREATE”: “REQUIRED”, “UPDATE”: TRUE},
     120     
     121     “_GENI_PROJECT_EMAIL”: {“TYPE”: “EMAIL”, “CREATE”: “REQUIRED”, “UPDATE”: TRUE, “OBJECT”: “PROJECT”}
     122       
     123      }
     124
     125}
     126
     127The following is an example of a return from a get_version for an MA, provided in JSON-like syntax:
     128
     129{
     130
     131      “VERSION”: “10.0.7”,
     132
     133      “CREDENTIAL_TYPES”: [“SFA”, “ABAC”],
     134
     135      "SERVICES": ["MEMBER", "KEY"],
     136
     137      "OBJECTS": [ "KEY" ],
     138
     139      “FIELDS”: {
     140   
     141              “MEMBER_DISPLAYNAME”: {“TYPE”: “STRING”, “CREATE”: “ALLOWED”, “UPDATE”,
     142
     143TRUE, “PROTECT”: “IDENTIFYING”},
     144
     145      “MEMBER_AFFILIATION”: {“TYPE”: “STRING”, “CREATE”: “ALLOWED”, “UPDATE”:
     146
     147TRUE, “PROTECT”: “IDENTIFTYING”},
     148
     149      “MEMBER_SSL_PUBLIC_KEY”: {“TYPE”: “SSL_KEY”},
     150
     151      “MEMBER_SSL_PRIVATE_KEY”: {“TYPE”: “SSL_KEY”, “PROTECT”: “PRIVATE”},
     152
     153      “MEMBER_SSH_PUBLIC_KEY”: {“TYPE”: “SSH_KEY”},
     154
     155      “MEMBER_SSH_PRIVATE_KEY”: {“TYPE”: “SSH_KEY”, “PROTECT”: “PRIVATE”},
     156
     157      “MEMBER_ENABLED”: {“TYPE”: “BOOLEAN”, “UPDATE”: TRUE}
     158    }
     159
     160}
     161
     162The following is an example of a return from a get_version from a Registry, provided in JSON-like syntax:
     163
     164{
     165      “VERSION”: “10.0.7”,
     166
     167      “FIELDS”: {
     168
     169              “SERVICE_PROVIDER”: {“TYPE”: “STRING”}}
     170
     171     }
     172
     173}
     174
     175== API Error Handing ==
     176
     177All method calls return a tuple [code, value, output]. What is described as ‘Return’ in the API’s described below is the ‘value’ of this tuple in case of a successful execution. ‘Code’ is the error code returned and ‘output’ is the returned text (e.g. descriptive error message).
     178
     179Each Registry and Authority is free to define and return its own specific error codes. However we suggest the following essential set of error codes to report on generic conditions:
     180
     181|| ''' CODE_NAME ''' || ''' CODE_VALUE ''' || ''' DESCRIPTION ''' ||
     182|| NONE || 0 || No error encountered – the return value is a successful result. An empty list form a query should be interpreted as ‘nothing found matching criteria’. ||
     183|| AUTHENTICATION_ERROR || 1 || The invoking tool or member did not provide appropriate credentials indicating that they are known to the Federation or that they possessed the private key of the entity they claimed to be ||
     184|| AUTHORIZATION_ERROR || 2 || The invoking tool or member does not have the authority to invoke the given call with the given arguments ||
     185|| ARGUMENT_ERROR || 3 || The arguments provided to the call were mal-formed or mutually inconsistent. ||
     186|| DATABASE_ERROR || 4 || An error from the underlying database was returned. (More info should be provided in the ‘output’ return value] ||
     187|| DUPLICATE_ERROR || 5 || An error indicating attempt to create an object that already exists ||
     188|| NOT_IMPLEMENTED_ERROR || 100 || The given method is not implemented on the server. ||
     189|| SERVER_ERROR || 101 || An error in the client/server connection ||
     190
     191== API Method Conventions ==
     192
     193Each Registry and Authority manages the state of or access to objects. Some conventions apply to similar methods across Registry or Authority services.
     194
     195''' Create_*Method ''' : Creates a new instance of the given object with a ‘fields’ option specifying particular field values that are to be associated with the object. These may only include those fields specified as ‘ALLOWED or ‘REQUIRED’ in the ‘Creation’ column of the object descriptions below or in the “CREATE’ key in the supplemental fields in the get_version specification for that object. If successful, the call returns a dictionary of the fields associated with the newly created object.
     196
     197''' Update_* Method ''' : Updates an object instance specified by URN with a ‘fields’ option specifying the particular fields to update. Only a single object can be updated from a single update call. The fields may include those specified as ‘Yes’ in the ‘Update’ column of the object descriptions below, or ’TRUE’ in the ‘UPDATE’ key in the supplemental fields provided by the get_version call. Note: There may be more than one entity of a given URN at an authority, but only one ‘live’ one (any other is archived and cannot be updated).
     198
     199''' Lookup_* Method ''' : This call takes a set of ‘match’ criteria provided in the ‘options’ field, and returns a dictionary of dictionaries of object attributes keyed by object URN matching these criteria. If a ‘filter’ option is provided, only those attributes listed in the ‘filter’ options are returned. The requirements on match criteria supported by a given service are service-specific; however it is recommended that policies restrict lookup calls to requests that are bounded to particular sets of explicitly listed objects (and not open-ended queries).
     200
     201Specifically, the options argument to the lookup_* call is a dictionary. It contains an entry with key ‘match’ that contains a dictionary of name/value pairs. The names are of fields listed in the get_version for that object. The values are values for those fields to be matched. The semantics of the match is to be an “AND” (all fields must match).
     202
     203The value in the dictionary of a ‘match’ option can be a list of scalars, indicating an “OR”. For example, a list of URNs provided to the SLICE_URN key would match any slice with any of the listed URNs.
     204
     205The options argument may include an additional dictionary keyed “filter” which is a list of fields associated with that object type (again, as specified in the get_version entry for that object). No “filter” provided means all fields are to be returned; a 'filter' provided with an empty list returns an empty set of fields (i.e. a dictionary of URN's pointing to empty dictionaries).
     206
     207The return of the call will be a dictionary of dictionaries, one per matching object indexed by URN, of fields matching the filter criteria. If the query found no matches, an empty dictionary is returned (i.e. no error is reported, assuming no other error was encountered in processing).
     208
     209If a lookup method asks for information about objects whose disclosure is prohibited to the requestor by policy, the method must not return the data. It is implementation specified as to whether the call should return an error, return a dictionary with the URN key pointing to an empty dictionary, or have no URN key in the returned dictionary.
     210
     211== API Method Examples: ==
     212
     213A Member Authority (MA) manages information about member objects. The MA method lookup_member could take an options argument such as
     214
     215{
     216
     217      "match”: {“MEMBER_LASTNAME”: “BROWN”},
     218     
     219      "filter”: [“MEMBER_EMAIL”, “MEMBER_FIRSTNAME”]
     220
     221Such a call would find any member with last name Brown and return a dictionary keyed by the member URN containing a dictionary with their email, and first name.
     222
     223''' { '''
     224
     225      “urn:publicid:IDN+mych+user+abrown” :
     226     
     227            {“MEMBER_EMAIL”: abrown@williams.edu,
     228           
     229            “MEMBER_FIRSTNAME”: “Arlene”},
     230     
     231      “urn:publicid:IDN+mych+user+mbrown” :
     232
     233            {“MEMBER_EMAIL”: mbrown@umass.edu,
     234
     235            “MEMBER_FIRSTNAME”: “Michael”},
     236
     237      “urn:publicid:IDN+mych+user+sbrown” :
     238
     239            {“MEMBER_EMAIL”: sbrown@stanford.edu,
     240
     241            “MEMBER_FIRSTNAME”: “Sam”}
     242
     243}
     244
     245A Slice Authority (SA) manages information about slice objects. The SA method update_slice could take an options ‘update’ argument such as to change the slice description and extend the slice expiration:
     246
     247{
     248
     249      “fields” : { “SLICE_DESCRIPTION”: “Updated Description”,
     250
     251                 “SLICE_EXPIRATION”: “2013-07-29T13:15:30Z” } 
     252
     253}
     254
     255An example of lookup_slice that wanted to retrieve the slice names for a list of slice URNs could specify options:
     256
     257{“match”: {
     258
     259      “SLICE_URN”: [
     260
     261             “urn:publicid+IDN+this_sa:myproject+slice+slice1”,
     262
     263             “urn:publicid+IDN+this_sa:myproject+slice+slice2”,
     264
     265             “urn:publicid+IDN+this_sa:myproject+slice+slice3”
     266
     267       ]},
     268
     269“filter”: [“SLICE_NAME”]
     270
     271}
     272 
     273
     274== API Method Examples (cont.): ==
     275
     276An example of create_slice call would specify required options e.g.:
     277
     278{
     279 
     280      ‘fields’ : {
     281
     282            “SLICE_NAME”: “TEST_SLICE”,
     283           
     284            “SLICE_DESCRIPTION”: “My Test Slice”,
     285
     286            “SLICE_EMAIL”: myemail@geni.net,
     287
     288            “PROJECT_URN”: “urn:publicid+IDN+this_sa+project+myproject”
     289
     290       }
     291
     292}
     293
     294and receive a return dictionary looking like:
     295
     296{
     297
     298       “SLICE_URN”: “urn:publicid+IDN+this.sa+slice+TESTSLICE”,
     299
     300       “SLICE_UID”: “…”,
     301
     302       “SLICE_NAME”: “TESTSLICE”,
     303
     304       “SLICE_CREDENTIAL”: “.....”,
     305
     306       “SLICE_DESCRIPTION”: “My Test Slice”,
     307
     308       “PROJECT_URN”: “urn:publicid+IDN+this_sa+project+myproject”,
     309
     310       “SLICE_EXPIRATION”: “2013-08-29T13:15:30Z”,
     311
     312       “SLICE_EXPIRED”: “FALSE”,
     313
     314       “SLICE_CREATION”: “2013-07-29T13:15:30Z”,
     315
     316       “SLICE_EMAIL”: myemail@geni.net
     317
     318}
     319
     320== API Authentication ==
     321
     322This document suggests that the Authentication required for the Federation APIs is implicit in the SSL protocol: the invoker of the call must have its cert and private key to have a valid SSL connection. Moreover, the cert must be signed by a member of the trust chain recognized by the Federation.
     323
     324== Support for Speaks-for API Invocations ==
     325
     326Best practices dictate that individuals should speak as themselves: that is, the entity on the other side of an SSL connection is the one referred to by the certificate on the connection. Obviously, people typically use tools or software interfaces to create these connections. When a tool is acting directly on a user’s desktop using the user’s key and cert with the user’s explicit permission, it may be acceptable to consider the tool as speaking as the user. But for many tools, the tool is acting on behalf of the user in invoking Federation or AM API calls. In this case, it is important for the tool to not speak as the user but to speak for the user, and to have the service to whom the tool is speaking handle the authorization and accountability of this request accordingly.
     327
     328Accordingly, a Registry and associated Authorities should support speaks-for API transactions. These API transactions use the same signatures as the calls described in this document, with these enhancements:
     329
     330- A 'speaking-for' option containing the URN of the user being spoken for
     331
     332- A speaks-for credential in the list of credentials: a statement signed by the user indicating that the tool has the right to speak for the user, possibly limited to a particular scope (e.g. slice, project, API call, time window).
     333
     334The service call is then required to determine if the call is being made in a speaks-for context or not (that is, the ‘speaking-for’ option provided). If so, the call must determine if the tool is allowed to speak for the user by checking for the presence of a valid speaks-for credential and the spoken-for user’s cert. If so, the call should validate if the user is authorized to take the proposed API action. If so, the action is taken and accounted to the user, with identity of the speaking-for tool logged. If the call is ‘speaks-for’ but any of these additional criteria are not met, the call should fail with an authorization error. If the call is not a ‘speaks-for’, then the normal authorization is performed based on the identity (certificate) provided with the SSL connection.
     335
     336Aggregates are also encouraged to support speaks-for authentication and authorization, but this is an aggregate-internal policy and implementation decision, and outside the scope of this document.
     337
     338== Registry API ==
     339
     340The Registry provides a list of Slice Authorities, Member Authorities and Aggregates associated with a given Federation. The URL for accessing these methods (i.e. the URL of the Registry) is to be provided out-of-band (i.e. there is no global service for gaining access to Registry addressees).
     341
     342All Registry calls are unprotected; they have no requirement for passing a client-side cert or validating any client-cert cert that is passed.
     343
     344The Registry implements the SERVICE service and supports the SERVICE object.
     345
     346The following table describes the default fields for services (aggregates and authorities) provided by Registry API calls:
     347
     348
     349|| ''' Name ''' || ''' Type ''' || ''' Description ''' || ''' Required ''' ||
     350|| SERVICE_URN || URN || URN of given service || Yes ||
     351|| SERVICE_URL ||URL || URL by which to contact the service || Yes ||
     352|| SERVICE_CERT || Certificate || Public certificate of service || No ||
     353|| SERVICE_NAME || String || Short name of service || Yes ||
     354|| SERVICE_DESCRIPTION || String || Descriptive name of service || No ||
     355
     356{{{
     357#!python
     358# Provide a structure detailing the version information as well as details of accepted options for Registry API calls.
     359#
     360# Arguments:
     361#   None
     362#
     363# Return:
     364#   get_version structure information as described above
     365def get_version()
     366}}}
     367
     368{{{
     369#!python
     370# Return information about all aggregates associated with the Federation
     371#
     372# Arguments:
     373#  options: 'match' and 'filter' options   as described in standard lookup methods
     374#
     375# Return:
     376 #  List of dictionaries of name/value pairs for each returned AM
     377def lookup_aggregates(options)
     378}}}
     379
     380{{{
     381#!python
     382#
     383# Return information about all MA’s associated with the Federation#
     384#
     385# Arguments:
     386#  options: 'match' and 'filter' options   as described in standard lookup methods
     387#
     388#Return:
     389#  List of dictionaries of name/value pairs for each returned MA
     390def lookup_member_authorities(options)
     391}}}
     392
     393{{{
     394#!python
     395# Return information about all SA’s associated with the Federation
     396#
     397# Arguments:
     398#   options: 'match' and 'filter' options   as described in standard lookup methods
     399#
     400# Return:
     401#   List of dictionaries of name/value pairs for each returned SA
     402def lookup_slice_authorities(options)
     403}}}
     404
     405
     406The following method maps object URN's to authority URN's. Note that the transformation from the URN's of objects (e.g. slice, project, member) to the URN's of their authority is a simple one, for example:
     407
     408|| '''Type''' || '''Object URN''' || '''Authority URN''' ||
     409|| Slice || urn:publicid:IDN+sa_name+slice+slice_name || urn:publicid:IDN+sa_name+authority+sa ||
     410|| Member || urn:publicid:IDN+ma_name+user+user_name || urn:publicid:IDN+ma_name+authority+ma ||
     411
     412{{{
     413#!python
     414# Lookup the authorities for a given URNs
     415#
     416# There should be at most one (potentially none) per URN.
     417#
     418# This requires extracting the authority from the URN and then looking up the authority in the Registry's set of services.
     419#
     420# Arguments:
     421#   urns: URNs of entities for which the authority is requested
     422#
     423# Return:
     424#   List of dictionaries {urn : url} mapping URLs of Authorities to given URN's
     425def lookup_authorities_for_urns(urns)
     426}}}
     427
     428{{{
     429#!python
     430# Return list of trust roots (certificates) associated with this Federation.
     431#
     432# Often this is a concatenatation of the trust roots of the included authorities.
     433#
     434# Arguments:
     435#   None
     436#
     437# Return:
     438#   List of certificates representing trust roots of this Federation.
     439def get_trust_roots()
     440}}}
     441
     442== Slice Authority API ==
     443
     444The Slice Authority API provides services to manage slices and their associated permissions. To support its AuthZ policies, a particular SA may choose to manage objects and relationships such as projects and slice/project membership. The SA API is thus divided into a set of services, each of which consists of a set of methods. Of these, only the SLICE service is required, the others are optional. If an SA implements a given service, it should implement the entire service as specified. All available SA service methods are available from the same SA URL. The get_version method should indicate, in the ‘SERVICES’ tag, which services the given SA supports.
     445
     446All SA calls are protected; passing and validating a client-side cert is required.
     447
     448The following is a list of potential SA services.
     449
     450
     451|| ''' Service ''' || ''' Description ''' || ''' Required ''' || ''' Object ''' ||
     452|| SLICE || Managing generation, renewal of slice credentials and slice lookup services || YES || SLICE ||
     453|| SLICE_MEMBER ||Defining and managing roles of members with respect to slices || NO || ||
     454|| SLIVER_INFO || Providing information about what Aggregates have reported having slivers for a given slice. Non-authoritative/advisory || NO || SLIVER_INFO ||
     455|| PROJECT || Defining projects (groupings of slices) and project lookup services || NO || PROJECT ||
     456|| PROJECT_MEMBER || Defining and managing roles of members with respect to projects || NO || ||
     457
     458== Slice Service Methods ==
     459
     460The Slice Authority manages the creation of slices, which are containers for allocating resources. It provides credentials (called slice credentials) which aggregates may use to make authorization decisions about allocating resources to a particular user to a particular slice. These slice credentials are one of the fields that may be provided from the create_slice call or requested in the lookup_slices call.
     461
     462The credentials passed to SA Slice Service methods are SA-specific. But a common case is for a tool to want to pass additional information about a user, obtained from the MA, to the SA to allow the SA to make informed authorization decisions. These credentials may be in the form of an SFA-style User Credential or ABAC credential. Common useful information from the MA to the SA about users would be slice-independent (the SA should know all slice-specific information about users) information about roles and attributes of that user. Two conventional roles are:
     463 * PI: The user has a PI lead and is typically considered appropriate for creating projects or slices (if there are no projects)
     464 * ADMIN: The user has special 'admin' privileges and can perform operations not otherwise authorized.
     465
     466Note that renewal of slice expiration is handled in the update_slice call (with “SLICE_EXPIRATION” specified as the options key. The semantics of slice expiration is that slice expiration may only be extended, never reduced. Further restrictions (relative to project expiration or relative to slice creation, e.g.) are SA-specific.
     467
     468The following table contains required fields for slice objects and whether they are allowed in lookup ‘match’ criteria, required at creation or allowed at update:
     469
     470|| ''' Name ''' || ''' Type ''' || ''' Description ''' || ''' Match ''' || ''' Creation ''' || ''' Update ''' ||
     471|| SLICE_URN || URN || URN of given slice || Yes || No || No ||
     472|| SLICE_UID ||UID || UID (unique within authority) of slice || Yes || No || No ||
     473|| SLICE_CREATION || DATETIME || Creation time of slice || No || No || No ||
     474|| SLICE_EXPIRATION || DATETIME || Expiration time of slice || No || Allowed || Yes ||
     475|| SLICE_EXPIRED || BOOLEAN || Whether slice has expired || Yes || No || No ||
     476|| SLICE_NAME || STRING || Short name of Slice|| No || Required || No ||
     477|| SLICE_DESCRIPTION || STRING || Description of Slice || No || Allowed || Yes ||
     478|| SLICE_PROJECT_URN || URN || URN of project to which slice is associated (if SA supports project) || Yes || Required (if SA supports project) || No ||
     479
     480To clarify the semantics of the SLICE_PROJECT_URN field, it is a required field for those SAs that support the PROJECT service (and in this context may be matched and is required at creation time, but not updatable). In SAs that do not support projects, the field is not meaningful and should not be supported.
     481
     482NB: SLICE_NAME must adhere to the restrictions for slice names in the Aggregate Manager (AM) API, namely that it must be <= 19 characters, only alphanumeric plus hyphen, no leading hyphen.
     483
     484{{{
     485#!python
     486# Provide details on the version, services and options supported by this SA
     487#
     488# Arguments:
     489#    Options:
     490#
     491# Return:
     492#   get_version structure information as described above
     493def get_version()
     494}}}
     495
     496{{{
     497#!python
     498# Create a new slice, optionally within a project. See generic create_* method description above.
     499#
     500# Arguments:
     501#
     502#   Options:
     503#       'fields', a dictionary field/value pairs for object to be created
     504#
     505# Return:
     506#   Dictionary of field/value pairs for created slice (e.g. slice URN, slice UUID, expiration and slice credential)
     507#
     508# Should return DUPLICATE_ERROR if creating a slice for which a non-expired slice of same name exists.
     509def create_slice (credentials, options)
     510}}}
     511
     512{{{
     513#!python
     514# Lookup slice detail for slices matching ‘match’ options.
     515#
     516# ‘filter’ options indicate what detail to provide. See generic lookup_* method description above.
     517#
     518# Arguments:
     519#    options: What details to provide (filter options) for which slices (match options)
     520#
     521# Return: List of dictionaries with field/value pairs for each returned slice
     522#
     523def lookup_slices (credentials, options)
     524}}}
     525
     526{{{
     527#!python
     528# Update fields in given slice object. See generic update_* method description above.
     529#
     530# Arguments:
     531#   slice_urn: URN of slice to update
     532#
     533#    Options: Contains ‘fields’ key referring dictionary of name/value pairs to update
     534# Return: None
     535#
     536def update_slice(slice_urn, credentials, options)
     537}}}
     538
     539{{{
     540#!python
     541# Provide list of credentials for the invoking member relative to the given slice. If the invocation is in a speaks-for context, the credentials will be for the ‘spoken-for’ member, not the invoking tool.
     542#
     543# For example, this call may return a standard SFA Slice Credential and some ABAC credentials indicating the role of the member with respect to the slice.
     544#
     545# Note: When creating an SFA-style Slice Credential, the following roles typically allow users to operate at known GENI-compatible aggregates: "*" (asterisk) or the list of "refresh", "embed", "bind", "control" "info".
     546#
     547# Arguments:
     548#   slice_urn: URN of slice for which to get member’s credentials
     549#   options: Potentially contains ‘speaking-for’ key indicating a speaks-for invocation (with certificate of the accountable member in the credentials argument)
     550# Return:
     551#   List of credential in “CREDENTIALS” format, i.e. a list of credentials with type information suitable for passing to aggregates speaking AM API V3.
     552def get_credentials(slice_urn, credentials, options)
     553}}}
     554
     555== Slice Member Service Methods ==
     556
     557Slices may have a set of members associated with them in particular roles. Certain SA may have policies that require certain types of membership requirements (exactly one lead, never empty, no more than a certain number of members, etc.). To that end, we provide a single omnibus method for updating slice membership in a single transaction, allowing any authorization or assurance logic to be supported at a single point in SA implementations.
     558
     559The set of recognized role types (e.g. LEAD, ADMIN, MEMBER, OPERATOR, AUDITOR) are to be listed in the get_version for a given Slice Authority.
     560
     561{{{
     562#!python
     563# Modify slice membership, adding, removing and changing roles of members with respect to given slice
     564#
     565# Arguments:
     566#   Slice_urn: URN of slice for which to modify membership
     567#   Options:
     568#       members_to_add: List of member_urn/role tuples for members to add to slice of form {‘SLICE_MEMBER’ : member_urn, ‘SLICE_ROLE’ : role}
     569#       members_to_remove: List of member_urn of members to remove from slice
     570#       members_to_change: List of member_urn/role tuples for members whose role should change as specified for given slice of form {‘SLICE_MEMBER’ : member_urn, ‘SLICE_ROLE’ : role}
     571#
     572# Return:
     573#   None
     574def modify_slice_membership(slice_urn, credentials, options)
     575}}}
     576
     577{{{
     578#!python
     579# Lookup members of given slice and their roles within that slice
     580#
     581# Arguments:
     582#   slice_urn: URN of slice for which to provide current members and roles
     583#
     584# Return:
     585#    List of dictionaries of member_urn/role pairs [{‘SLICE_MEMBER’: member_urn, ‘SLICE_ROLE’: role }...] where ‘role’ is a string of the role name
     586def 'lookup_slice_members(slice_urn, credentials, options)
     587}}}
     588
     589{{{
     590#!python
     591# Lookup slices for which the given member belongs
     592#
     593# Arguments:
     594#   Member_urn: The member for whom to find slices to which it belongs
     595#
     596# Return:
     597#    List of dictionary of slice_urn/role pairs [(‘SLICE_URN’ : slice_urn, ‘SLICE_ROLE’ : role} ...] for each slice to which a member belongs, where role is a string of the role name
     598def lookup_slices_for_member(member_urn, credentials, options)
     599}}}
     600
     601== Sliver Info Service Methods ==
     602
     603Sliver information is authoritatively held in aggregates: aggregates know which slivers are in which slices at that aggregate. As a convenience to tools, aggregates are encouraged to register with the SA which slices they have information about. In this way, tools can reference only certain aggregates and not all known aggregates to get a useful (if not authoritative) set of sliver details for a slice.
     604
     605It is expected that the register_aggregate and remove_aggregate calls will be restricted to aggregates (in which case no speaks-for credential is required). That said, SAs may implement authorization policies of their choosing on these calls.
     606
     607The following table contains the required fields for sliver info objects and whether they are allowed in lookup 'match' criteria, required at creation or allowed at update:
     608
     609|| '''Name''' || '''Type''' || '''Description''' || '''Match''' || '''Creation''' || '''Update''' ||
     610|| SLIVER_INFO_SLICE_URN || URN || URN of slice for registered sliver || Yes || Required || No ||
     611|| SLIVER_INFO_URN || URN || URN of registered sliver || Yes || Required || No ||
     612|| SLIVER_INFO_AGGREGATE_URN || URN || URN of aggregate of registered sliver || Yes || Required || No ||
     613|| SLIVER_INFO_CREATOR_URN || URN || URN of member/tool that created the registered sliver || Yes || Required || No ||
     614|| SLIVER_INFO_EXPIRATION || DATETIME || Time of sliver expiration || No || Allowed || Yes ||
     615|| SLIVER_INFO_CREATION || DATETIME || Time of sliver creation || No || Allowed || No ||
     616
     617{{{
     618#!python
     619# Create a record of a sliver creation
     620#
     621# Arguments:
     622#   options: 'fields' containing the fields for the sliver info  being registered at SA
     623#
     624# Return:
     625# Dictionary of name/value pairs for created sliver_info record
     626def create_sliver_info(credentials, options)
     627}}}
     628
     629{{{
     630#!python
     631# Delete a sliver_info record
     632#
     633# Arguments:
     634#    sliver_urn: urn of sliver whose record is to be deleted
     635#
     636# Return:
     637#   True if succeeded
     638#
     639#Should return ARGUMENT_ERROR if no such sliver urn is registered
     640def delete_sliver_info(sliver_urn, credentials, options)
     641}}}
     642
     643{{{
     644#!python
     645# Update the details of a sliver_info record
     646#
     647#Arguments:
     648#   sliver_urn: urn of sliver for which to update
     649#   options: 'fields' containing fields for sliver_infos that are permitted for update
     650#
     651# Return:
     652#   None
     653#
     654# Should return ARGUMENT_ERROR if no such sliver_urn is found
     655def update_sliver_info(sliver_urn, credentials, options)
     656}}}
     657
     658{{{
     659#!python
     660# Lookup sliver_info for given match criteria return fields in given filter criteria
     661#
     662# Arguments:
     663#   options: 'match' for query match criteria, 'filter' for fields to be returned
     664#
     665# Return:
     666#    Dictionary (indexed by sliver_urn) of dictionaries containing name/value pairs for all sliver_infos registered at this SA matching given criteria.
     667def lookup_sliver_info(credentials, options)
     668}}}
     669
     670== Project Service Methods ==
     671
     672Projects are groupings of slices and members for a particular administrative purpose. Some SA;s will chose to create and manage projects and apply policies about the invocation of SA methods (e.g. the creation of slice credentials based on roles or memberships in projects).
     673
     674The following table contains required fields for project objects and whether they are allowed in lookup ‘match’ criteria, required at creation or allowed at update:
     675
     676|| ''' Name ''' || ''' Type ''' || ''' Description ''' || ''' Match ''' || ''' Creation ''' || ''' Update ''' ||
     677|| PROJECT_URN || URN || URN of given project || Yes || No || No ||
     678|| PROJECT_UID ||UID || UID (unique within authority) of project || Yes || No || No ||
     679|| PROJECT_CREATION || DATETIME || Creation time of project || No || No || No ||
     680|| PROJECT_EXPIRATION || DATETIME || Expiration time of project || No || Allowed || Yes ||
     681|| PROJECT_EXPIRED || BOOLEAN || Whether project has expired || Yes || No || No ||
     682|| PROJECT_NAME || STRING || Short name of Project || No || Required || No ||
     683|| PROJECT_DESCRIPTION || STRING || Description of Project || No || Allowed || Yes ||
     684
     685{{{
     686#!python
     687# Create project with given details. See generic create_* description above.
     688#
     689# Arguments:
     690#   Options: 'fields', a dictionary of name/value pairs for newly created project.
     691#
     692# Return:
     693#   Dictionary of name/value pairs of newly created project including urn
     694#
     695#Should return DUPLICATE_ERROR if creating a project for which a project of same name exists.
     696def create_project(credentials, options)
     697}}}
     698
     699{{{
     700#!python
     701# Lookup project detail for projects matching ‘match options.
     702# ‘filter options indicate what detail to provide.
     703#
     704# Arguments:
     705#    options: What details to provide (filter options) for which members (match options)
     706#
     707# Return:
     708#    Dictionary of name/value pairs from ‘filter’ options for each project matching ‘match’ option criteria.
     709def lookup_projects(credentials, options)
     710}}}
     711
     712{{{
     713#!python
     714# Update fields in given project object, as allowed in Get_version advertisement. See generic update_* description above.
     715#
     716# Arguments:
     717#    project_urn: URN of project to update
     718#    Options: Contains ‘fields’ key referencing dictionary of key/value pairs to update project
     719#
     720# Return: None
     721def update_project(project_urn, credentials, options)
     722}}}
     723
     724== Project Member Service Methods ==
     725
     726Projects may have members associated with them in particular roles. See the Slice Member Service Methods above for more description.
     727
     728{{{
     729#!python
     730# Modify project membership, adding, removing and changing roles of members with respect to given project
     731#
     732# Arguments:
     733#   project_urn: Name of project for which to modify membership
     734#   Options:
     735#      members_to_add: List of member_urn/role tuples for members to add to project of form {‘PROJECT_MEMBER’: member_urn, ‘PROJECT_ROLE’ : role}
     736#      members_to_remove: List of member_urn of members to remove from project
     737#      members_to_change: List of member_urn/role tuples for members whose role should change as specified for given project of form {‘PROJECT_MEMBER’ : member_urn, ‘PROJECT_ROLE’ : role}
     738#
     739# Return:  None
     740def modify_project_membership(project_urn, credentials, options)
     741}}}
     742
     743{{{
     744#!python
     745# Lookup members of given project and their roles within that project
     746#
     747# Arguments:
     748#    project_urn: project_urn for which to provide current members and roles
     749#
     750#Return:
     751#   List of dictionaries of member_urn/role pairs of form [{‘PROJECT_MEMBER’: member_urn, ‘PROJECT_ROLE’: role}...]
     752def lookup_project_members (project_urn, credentials, options)
     753}}}
     754
     755{{{
     756#!python
     757# Lookup projects for which the given member belongs
     758#
     759# Arguments:
     760#    Member_urn: The member for whom to find project to which it belongs
     761#
     762# Return:
     763#    Dictionary of slice_urn/role pairs (‘PROJECT_URN’ : project_urn, ‘PROJECT_ROLE’ : role} where role is a string of the role name
     764def lookup_projects_for_member(member_urn, credentials, options)
     765}}}
     766
     767== Member Authority API ==
     768
     769The Member Authority API provides services to manage information about federation members including public and potentially private or identifying information.
     770
     771As noted above, this document does not specify required policies for Federations. A given MA is free to implement its own policies. That said, the management of member private information is a subject for particular attention and care.
     772
     773All MA calls are protected; passing and validating a client-side cert is required.
     774
     775 While each MA is free to implement its own authorization policy, reasonable security policy should allow calls to succeed only if the following criteria are met:
     776
     777 * The user/tool cert is signed by someone in the Federation's trust chain
     778 * If the cert is held by a tool, then the call must contain a user cert and a ‘speaks-for’ credential and the tool is trusted by the Federation to perform speaks-for.
     779 * The requestor is asking for their own identifying info or has privileges with respect to the people about whom they are asking for that identifying info.
     780 * Access to private info (SSL or SSH keys) should be restricted only to the user’s own keys for ordinary users.
     781
     782Like the Slice Authority, the Member Authority provides a set of services each consisting of a set of methods. Some services are required for any MA implementation, others are optional, as indicated by this table:
     783
     784|| '''Service''' || '''Description''' || '''Required''' || '''Object'''
     785|| MEMBER || Services to  lookup and update information about members || YES || MEMBER ||
     786|| KEY || Services to support storing, deleting and retrieving keys (e.g. SSH)  for members || NO || KEY ||
     787
     788== Member Service Methods ==
     789
     790The information managed by the MA API is divided into three categories, for purposes of applying different AuthZ policies at these different levels:
     791
     792 * Public: Public information about a member (e.g. public SSH or SSH keys, speaks-for credentials, certificates)
     793 * Private: Private information (e.g. private SSL or SSH keys) that should be given only to the member or a tool speaking for the member with a valid speaks-for credential
     794 * Identifying: Information that could identify the given member (e.g. name, email, affiliation)
     795
     796The following table contains required fields for member objects and whether they are allowed in lookup ‘match’ criteria and their protection (public, private, identifying):
     797
     798
     799|| ''' Name ''' || ''' Type ''' || ''' Description ''' || ''' Match ''' || ''' Protection ''' ||
     800|| MEMBER_URN || URN || URN of given member || Yes || Public ||
     801|| MEMBER_UID ||UID || UID (unique within authority) of member || Yes || Public ||
     802|| MEMBER_FIRSTNAME || STRING || First name of member || Yes || Identifying ||
     803|| MEMBER_LASTNAME || STRING || Last name of member || Yes || Identifying ||
     804|| MEMBER_USERNAME || STRING || Username of user || Yes || Public ||
     805|| MEMBER_EMAIL || STRING || Email of user || Yes || Identifying ||
     806
     807{{{
     808#!python
     809# Return information about version and options (filter, query, credential types) accepted by this member authority
     810#
     811# Arguments: None
     812#
     813# Return:
     814#     get_version structure information as described above
     815def get_version()
     816}}}
     817
     818{{{
     819#!python
     820# Lookup public information about members matching given criteria
     821#
     822# Arguments:
     823#   options: set of ‘filter’ and ‘match’ criteria specifying which members and which fields for each member to return
     824#
     825# Return:
     826#   Dictionary indexed by member URN of dictionaries of name/value pairs of fields specified in ‘filter’ options for members matching ‘match’ criteria
     827def lookup_public_member_info (credentials, options)
     828}}}
     829
     830{{{
     831#!python
     832# Lookup private (SSL/SSH key) information about members matching given criteria
     833#
     834# Arguments:
     835#    options: set of ‘filter’ and ‘match’ criteria specifying which members and which fields for each member to return
     836#
     837# Return:
     838#    Dictionary indexed by member URN of name/value pairs of fields specified in ‘filter’ options for members matching ‘match’ criteria
     839def lookup_private_member_info (credentials, options)
     840}}}
     841
     842{{{
     843#!python
     844# Lookup identifying (e.g. name, email) info about matching members
     845#
     846# Arguments:
     847#    options: set of ‘filter’ and ‘match’ criteria specifying which members and which fields for each member to return
     848#
     849# Return:
     850#    Dictionary indexed by member URN of name/value pairs of fields specified in ‘filter’ options for members matching ‘match’ criteria
     851def  lookup_identifying_member_info(credentials, options)
     852}}}
     853
     854{{{
     855#!python
     856# Update information about given member public, private or identifying information
     857#
     858# Arguments:
     859#    member_urn: URN of member for whom to set information
     860#    options: Containing ‘update’ key with dictionary of name/value pairs to update info for given member
     861#
     862# Return: None
     863def update_member_info(member_urn, credentials, options)
     864}}}
     865
     866{{{
     867#!python
     868# Provide list of credentials (signed statements) for given member
     869# This is member-specific information suitable for passing as credentials in an AM API call for aggregate authorization.
     870# Arguments:
     871#    member_urn: URN of member for which to retrieve credentials
     872#    options: Potentially contains ‘speaking-for’ key indicating a speaks-for invocation (with certificate of the accountable member in the credentials argument)
     873#
     874# Return:
     875#     List of credential in “CREDENTIALS” format, i.e. a list of credentials with type information suitable for passing to aggregates speaking AM API V3.
     876def get_credentials(member_urn, credentials, options)
     877}}}
     878
     879== Key Service Methods ==
     880
     881The Key Service provides methods to allow for storing, deleting and retrieving SSH or similar keys for members. It is not intended for retrieving SSL public/private keys or certs.
     882
     883The following table contains the required fields for key objects and whether they are allowed in lookup 'match' criteria, required at creation or allowed at update:
     884
     885|| '''Name''' || '''Type''' || '''Description''' || '''Match''' || '''Creation''' || '''Update''' ||
     886|| KEY_MEMBER || URN || URN of member associated with key pair || Yes || Required || No ||
     887|| KEY_ID || STRING || Unique identifier of key: typically a fingerprint or hash of public key || Yes || No || No ||
     888|| KEY_PUBLIC || KEY || Public key value || Yes || Required || No ||
     889|| KEY_PRIVATE || KEY || Private key value || Yes || Allowed || No ||
     890|| KEY_DESCRIPTION || STRING || Human readable description of key pair || Yes || Allowed || Yes ||
     891
     892Note that access to key information is subject to authorization policy. The public keys are likely to be readily available but access to the private keys will be tightly restricted (often only to the user or authorized proxy). Requests to lookup information for which the requestor is not authorized should fail on, at least, a per row basis. That is, if one asks for KEY_PUBLIC and KEY_PRIVATE for a list of member_urn's, the key pair should be returned only for those members to whom access to BOTH halves of the key are allowed. Note also that storing the private key is optional: an empty private key returned from a lookup method is an indication that no such key is stored, not that the access to the private key is not authorized.
     893
     894{{{
     895#!python
     896# Create a record for a key pair for given member
     897#
     898# Arguments:
     899#    options: 'fields' containing the fields for the key pair being stored
     900#
     901# Return:
     902#    Dictionary of name/value pairs for created key record including the KEY_ID
     903#
     904# Should return DUPLICATE_ERROR if a key with the same KEY_ID is already stored for given user
     905def create_key(credentials, options)
     906}}}
     907
     908{{{
     909#!python
     910# Delete a key pair for given member
     911#
     912# Arguments:
     913#    member_urn: urn of member for which to delete key pair
     914#    key_id: KEY_ID (fingerprint) of key pair to be deleted
     915#
     916# Return:
     917#    True if succeeded
     918#
     919# Should return ARGUMENT_ERROR if no such key is found for user
     920def delete_key(member_urn, key_id, credentials, options)
     921}}}
     922
     923{{{
     924#!python
     925# Update the details of a key pair for given member
     926#
     927# Arguments:
     928#    member_urn: urn of member for which to delete key pair
     929#    key_id: KEY_ID (fingerprint) of key pair to be deleted
     930#    options: 'fields' containing fields for key pairs that are permitted for update
     931#
     932# Return:
     933#    None
     934#
     935# Should return ARGUMENT_ERROR if no such key is found for user
     936def update_key(member_urn, key_id, credentials, options)
     937}}}
     938
     939{{{
     940#!python
     941# Lookup keys for given match criteria return fields in given filter criteria
     942#
     943# Arguments:
     944#    options: 'match' for query match criteria, 'filter' for fields to be returned
     945#
     946# Return:
     947#    Dictionary (indexed by member_urn) of dictionaries containing name/value pairs for all keys registered for that given user.
     948def lookup_keys(credentials, options)
     949}}}
     950
     951== Appendix: Federation Object Models ==
     952
     953As described, each Federation service method takes a set of options that provide further details on the request. Many of these options reflect the fields of the underlying object models. For example, the Slice Authority manages slice objects and allows for options for querying for and by slice object fields.
     954
     955Different Federation Authorities will implement different subsets of the possible set of Federation services. Those that do implement a given service should implement the API’s described above. The fields of the objects maintained through these API’s are flexible: some fields are required but different Authorities may have their own additional data, to be returned by the get_version method.
     956
     957The following diagram reflects the different objects maintained within the full range of Authority services, their interactions and mandatory fields.
     958
     959[[Image(FedObjectModel.pdf, 50%,nolink)]]
     960
     961== Appendix B: API Data Types ==
     962
     963The following table describes the data types referenced in the document above, in terms of format and meaning.
     964
     965|| ''' Type ''' || ''' Description ''' || ''' Format ''' ||
     966|| URN || Standard GENI identifier, guaranteed to be unique across all GENI services and authorities at a given time, but may be reused by obsolete/expired objects (e.g. slices) || '''Example:''' urn:publicid:IDN+mych+user+abrown ''' Details: ''' urn:publicid:IDN+AUTHORITY+TYPE+NAME where AUTHORITY is the unique fully qualified identifier of the authority creating the URN (e.g. ch.geni.net), TYPE is the type of entity (e.g. slice, user, tool, project) and name is the unique name of the entity (e.g. slice_name, user_name, tool_name, project_name) ||
     967|| UID || Unique identifier within the scope of a single authority, not guaranteed to be unique across authorities || '''Example:''' 8e405a75-3ff7-4288-bfa5-111552fa53ce '''Details:''' Varies by implementation but the python UUID4 standard is a good example. ||
     968|| STRING || Generic UTF-8 string ||  ||
     969|| INTEGER || Generic integer argument || ||
     970|| DATETIME || Date time in UTC format || '''Examples:''' 2013-06-15 02:39:08 2013-06-15 02:39:08-05:00 '''Details:''' Assumed in GMT time zone unless specified: '''GMT:''' YYYY-MM-DD HH:mm:ss '''Time zone offset specified:''' YYYY-MM-DD HH:mm:ss-HH:mm ||
     971|| EMAIL || Well-formed email address || '''Example:''' jbrown@geni.net ||
     972|| KEY || SSH or SSL public or private key (contents, not filename) || Key-specific format ||
     973|| BOOLEAN || True or False (case insensitive) || '''Example:''' True ||
     974|| CREDENTIALS || List of dictionaries, one per credential, tagged with credential type and version (as indicated in the GENI AM API specification) || '''Details:''' Credentials = [ { geni_type: <string, case insensitive>, geni_version: <string containing an integer>, geni_value : <credential as string>, <others> } ] ||
     975|| CERTIFICATE || X509 certificate (contents, not filename) || Standard X509 certificate format ||
     976
     977As noted above, this list is subject to change as the API develops over time.