wiki:UniformClearinghouseAPI

Version 71 (modified by mbrinn@bbn.com, 10 years ago) (diff)

Convert API formatting to python formatting for increased readability

GENI Federation API’s

Marshall Brinn, GPO

DRAFT: August 30, 2013

Introduction

This 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.

The GENI Software Architecture rests on the interaction between different entities:

Aggregates : Collections of resources managed and presented in accordance with the AM API

Members : Experimenters or other human consumers of aggregate resources

Authorities : Services that manage assertions about members and their permissions with respect to aggregate resources.

There are two fundamental authority types in GENI:

  • Member Authority [MA]: Manages and asserts attributes about particular members
  • Slice Authority [SA]: Manages slice objects and generates credentials for members with respect to slices.

A 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.

The 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.

Authorities 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.

This 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.

API General Properties

The APIs described here share some common properties, which should be assumed for the rest of this document:

  • The wire-protocol is XML/RPC. It is thus language independent on both client and server side of the API calls.
  • 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.
  • Each call takes an ‘options’ argument, a dictionary allowing for passing specific non-standard/optional arguments
  • 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.
  • 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.
  • A Registry or Authority is free to implement additional methods beyond those specified in this document.
  • 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.

These API’s are provided in pseudo-code (i.e. language independent) format, with inputs and outputs (optional and required) described by comments, e.g.

# Perform method fed_func
#
# Arguments:
#  argl : ...
#  credentials : list of {type : credential} tuples representing credentials provided by caller to support AuthZ on method call.
#      [NB: This argument will be omitted in descriptions below. ]
#  options : … [ Recognized options: ….]
#
# Return: 
#  E.g. a list of dictionaries with these fields mandatory (…) and these fields optional (…)
def fed_func (arg1, arg2, credentials, options)

API 'get_version' methods

Different 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.

Each 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):

  • VERSION: 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.
  • SERVICES: The set of services the given URL supports [Authorities only]
  • CREDENTIAL_TYPES: A list of recognized credential types (e.g. [ABAC, SFA]) and list of supported credential versions on protected API methods. [Authorities only]
  • ROLES : A list of recognized roles for slice/project membership (optional for those Slice Authorities supporting membership). [Authorities only]
  • OBJECTS : List of additional supported objects (e.g. PROJECT in SA, KEY in MA). Not needed if only default objects handled (e.g. SLICE in SA, MEMBER in MA, SERVICE in Registry). [Authorities only]
  • FIELDS: A dictionary of supplementary object field names (i.e. in additional to the required fields) and associated attributes including:
    • “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)
    • “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.]
    • “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.
    • "MATCH" attributes may be specified as TRUE or FALSE (default = TRUE). These indicate whether a given field may be specified in an match option of a lookup call.
    • “UPDATE” attributes may be specified as TRUE or FALSE (default = FALSE). These indicate whether the given field may be specified in an update call.
    • “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.

Supplementary 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.).

The 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.

The following page provides some example returns from different get_version calls.

Example get_version returns:

The 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:

{

“VERSION”: “10.0.7”,

“SERVICES”: [“SLICE”, “PROJECT”, “SLICE_MEMBER”, “PROJECT_MEMBER”],

"OBJECTS": [ "PROJECT" ],

“CREDENTIAL_TYPES”: {“SFA”: [ "1" ]}, “ABAC” : ["1", "2"]},

“ROLES” : [“LEAD”, “ADMIN”, “MEMBER”, “AUDITOR”, “OPERATOR” ],

“FIELDS”: {

"_GENI_PROJECT_UID": {"TYPE" : "UID", "UPDATE" : FALSE},

“_GENI_SLICE_EMAIL”: {“TYPE”: “EMAIL”, “CREATE”: “REQUIRED”, “UPDATE”: TRUE}

“_GENI_PROJECT_EMAIL”: {“TYPE”: “EMAIL”, “CREATE”: “REQUIRED”, “UPDATE”: TRUE, “OBJECT”: “PROJECT”}

}

}

The following is an example of a return from a get_version for an MA, provided in JSON-like syntax:

{

“VERSION”: “10.0.7”,

“CREDENTIAL_TYPES”: [“SFA”, “ABAC”],

"SERVICES": ["MEMBER", "KEY"],

"OBJECTS": [ "KEY" ],

“FIELDS”: {

“MEMBER_DISPLAYNAME”: {“TYPE”: “STRING”, “CREATE”: “ALLOWED”, “UPDATE”,

TRUE, “PROTECT”: “IDENTIFYING”},

“MEMBER_AFFILIATION”: {“TYPE”: “STRING”, “CREATE”: “ALLOWED”, “UPDATE”:

TRUE, “PROTECT”: “IDENTIFTYING”},

“MEMBER_SSL_PUBLIC_KEY”: {“TYPE”: “SSL_KEY”},

“MEMBER_SSL_PRIVATE_KEY”: {“TYPE”: “SSL_KEY”, “PROTECT”: “PRIVATE”},

“MEMBER_SSH_PUBLIC_KEY”: {“TYPE”: “SSH_KEY”},

“MEMBER_SSH_PRIVATE_KEY”: {“TYPE”: “SSH_KEY”, “PROTECT”: “PRIVATE”},

“MEMBER_ENABLED”: {“TYPE”: “BOOLEAN”, “UPDATE”: TRUE}

}

}

The following is an example of a return from a get_version from a Registry, provided in JSON-like syntax:

{

“VERSION”: “10.0.7”,

“FIELDS”: {

“SERVICE_PROVIDER”: {“TYPE”: “STRING”}}

}

}

API Error Handing

All 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).

Each 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:

CODE_NAME CODE_VALUE DESCRIPTION
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’.
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
AUTHORIZATION_ERROR 2 The invoking tool or member does not have the authority to invoke the given call with the given arguments
ARGUMENT_ERROR 3 The arguments provided to the call were mal-formed or mutually inconsistent.
DATABASE_ERROR 4 An error from the underlying database was returned. (More info should be provided in the ‘output’ return value]
DUPLICATE_ERROR 5 An error indicating attempt to create an object that already exists
NOT_IMPLEMENTED_ERROR 100 The given method is not implemented on the server.
SERVER_ERROR 101 An error in the client/server connection

API Method Conventions

Each Registry and Authority manages the state of or access to objects. Some conventions apply to similar methods across Registry or Authority services.

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.

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).

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).

Specifically, 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).

The 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.

The 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.

The 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).

If 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.

API Method Examples:

A Member Authority (MA) manages information about member objects. The MA method lookup_member could take an options argument such as

{

"match”: {“MEMBER_LASTNAME”: “BROWN”},

"filter”: [“MEMBER_EMAIL”, “MEMBER_FIRSTNAME”]

Such 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.

{

“urn:publicid:IDN+mych+user+abrown” :

{“MEMBER_EMAIL”: abrown@williams.edu,

“MEMBER_FIRSTNAME”: “Arlene”},

“urn:publicid:IDN+mych+user+mbrown” :

{“MEMBER_EMAIL”: mbrown@umass.edu,

“MEMBER_FIRSTNAME”: “Michael”},

“urn:publicid:IDN+mych+user+sbrown” :

{“MEMBER_EMAIL”: sbrown@stanford.edu,

“MEMBER_FIRSTNAME”: “Sam”}

}

A 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:

{

“fields” : { “SLICE_DESCRIPTION”: “Updated Description”,

“SLICE_EXPIRATION”: “2013-07-29T13:15:30Z” }

}

An example of lookup_slice that wanted to retrieve the slice names for a list of slice URNs could specify options:

{“match”: {

“SLICE_URN”: [

“urn:publicid+IDN+this_sa:myproject+slice+slice1”,

“urn:publicid+IDN+this_sa:myproject+slice+slice2”,

“urn:publicid+IDN+this_sa:myproject+slice+slice3”

]},

“filter”: [“SLICE_NAME”]

}

API Method Examples (cont.):

An example of create_slice call would specify required options e.g.:

{

‘fields’ : {

“SLICE_NAME”: “TEST_SLICE”,

“SLICE_DESCRIPTION”: “My Test Slice”,

“SLICE_EMAIL”: myemail@geni.net,

“PROJECT_URN”: “urn:publicid+IDN+this_sa+project+myproject”

}

}

and receive a return dictionary looking like:

{

“SLICE_URN”: “urn:publicid+IDN+this.sa+slice+TESTSLICE”,

“SLICE_UID”: “…”,

“SLICE_NAME”: “TESTSLICE”,

“SLICE_CREDENTIAL”: “.....”,

“SLICE_DESCRIPTION”: “My Test Slice”,

“PROJECT_URN”: “urn:publicid+IDN+this_sa+project+myproject”,

“SLICE_EXPIRATION”: “2013-08-29T13:15:30Z”,

“SLICE_EXPIRED”: “FALSE”,

“SLICE_CREATION”: “2013-07-29T13:15:30Z”,

“SLICE_EMAIL”: myemail@geni.net

}

API Authentication

This 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.

Support for Speaks-for API Invocations

Best 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.

Accordingly, 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:

  • A 'speaking-for' option containing the URN of the user being spoken for
  • 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).

The 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.

Aggregates 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.

Registry API

The 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).

All Registry calls are unprotected; they have no requirement for passing a client-side cert or validating any client-cert cert that is passed.

The following table describes the default fields for services (aggregates and authorities) provided by Registry API calls:

Name Type DESCRIPTION
SERVICE_URN URN URN of given service
SERVICE_URL URL URL by which to contact the service
SERVICE_CERT Certificate Public certificate of service
SERVICE_NAME String Short name of service
SERVICE_DESCRIPTION String Descriptive name of service
# Provide a structure detailing the version information as well as details of accepted options for Registry API calls.
#
# Arguments:
#   None
#
# Return:
#   get_version structure information as described above
def get_version()
# Return information about all aggregates associated with the Federation
#
# Arguments:
#  options: 'match' and 'filter' options   as described in standard lookup methods
#
# Return:
 #  List of dictionaries of name/value pairs for each returned AM
def lookup_aggregates(options)
#
# Return information about all MA’s associated with the Federation#
#
# Arguments:
#  options: 'match' and 'filter' options   as described in standard lookup methods
#
#Return:
#  List of dictionaries of name/value pairs for each returned MA
def lookup_member_authorities(options)
# Return information about all SA’s associated with the Federation
#
# Arguments:
#   options: 'match' and 'filter' options   as described in standard lookup methods
#
# Return:
#   List of dictionaries of name/value pairs for each returned SA
def lookup_slice_authorities(options)

The 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:

Type Object URN Authority URN
Slice urn:publicid:IDN+sa_name+slice+slice_name urn:publicid:IDN+sa_name+authority+sa
Member urn:publicid:IDN+ma_name+user+user_name urn:publicid:IDN+ma_name+authority+ma
# Lookup the authorities for a given URNs
#
# There should be at most one (potentially none) per URN. 
# 
# This requires extracting the authority from the URN and then looking up the authority in the Registry's set of services.
#
# Arguments:
#   urns: URNs of entities for which the authority is requested
#
# Return:
#   List of dictionaries {urn : url} mapping URLs of Authorities to given URN's
def lookup_authorities_for_urns(urns)
# Return list of trust roots (certificates) associated with this Federation.
#
# Often this is a concatenatation of the trust roots of the included authorities.
#
# Arguments:
#   None
#
# Return:
#   List of certificates representing trust roots of this Federation.
def get_trust_roots()

Slice Authority API

The 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.

All SA calls are protected; passing and validating a client-side cert is required.

The following is a list of potential SA services.

Service Description Required
SLICE Managing generation, renewal of slice credentials and slice lookup services YES
SLICE_MEMBER Defining and managing roles of members with respect to slices NO
SLIVER_INFO Providing information about what Aggregates have reported having slivers for a given slice. Non-authoritative/advisory NO
PROJECT Defining projects (groupings of slices) and project lookup services NO
PROJECT_MEMBER Defining and managing roles of members with respect to projects NO

Slice Service Methods

The 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.

The 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:

  • PI: The user has a PI lead and is typically considered appropriate for creating projects or slices (if there are no projects)
  • ADMIN: The user has special 'admin' privileges and can perform operations not otherwise authorized.

Note 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.

The following table contains required fields for slice objects and whether they are allowed in lookup ‘match’ criteria, required at creation or allowed at update:

Name Type Description Match Creation Update
SLICE_URN URN URN of given slice Yes No No
SLICE_UID UID UID (unique within authority) of slice Yes No No
SLICE_CREATION DATETIME Creation time of slice No No No
SLICE_EXPIRATION DATETIME Expiration time of slice No Allowed Yes
SLICE_EXPIRED BOOLEAN Whether slice has expired Yes No No
SLICE_NAME STRING Short name of Slice No Required No
SLICE_DESCRIPTION STRING Description of Slice No Allowed Yes
SLICE_PROJECT_URN URN URN of project to which slice is associated (if SA supports project) Yes Required (if SA supports project) No

NB: 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.

# Provide details on the version, services and options supported by this SA
#
# Arguments:
#    Options:
#
# Return:
#   get_version structure information as described above
def get_version()
# Create a new slice, optionally within a project. See generic create_* method description above.
#
# Arguments:
#
#   Options: 
#       'fields', a dictionary field/value pairs for object to be created
#
# Return:
#   Dictionary of field/value pairs for created slice (e.g. slice URN, slice UUID, expiration and slice credential)
#
# Should return DUPLICATE_ERROR if creating a slice for which a non-expired slice of same name exists.
def create_slice (credentials, options)
# Lookup slice detail for slices matching ‘match’ options.
#
# ‘filter’ options indicate what detail to provide. See generic lookup_* method description above.
#
# Arguments:
#    options: What details to provide (filter options) for which slices (match options)
#
# Return: List of dictionaries with field/value pairs for each returned slice
#
def lookup_slices (credentials, options)
# Update fields in given slice object. See generic update_* method description above.
#
# Arguments:
#   slice_urn: URN of slice to update
#
#    Options: Contains ‘fields’ key referring dictionary of name/value pairs to update
# Return: None
#
def update_slice(slice_urn, credentials, options)
# 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.
#
# 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.
#
# 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".
#
# Arguments:
#   slice_urn: URN of slice for which to get member’s credentials
#   options: Potentially contains ‘speaking-for’ key indicating a speaks-for invocation (with certificate of the accountable member in the credentials argument)
# Return:
#   List of credential in “CREDENTIALS” format, i.e. a list of credentials with type information suitable for passing to aggregates speaking AM API V3.
def get_credentials(slice_urn, credentials, options)

Slice Member Service Methods

Slices 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.

The 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.

# Modify slice membership, adding, removing and changing roles of members with respect to given slice
#
# Arguments:
#   Slice_urn: URN of slice for which to modify membership
#   Options:
#       members_to_add: List of member_urn/role tuples for members to add to slice of form {‘SLICE_MEMBER’ : member_urn, ‘SLICE_ROLE’ : role}
#       members_to_remove: List of member_urn of members to remove from slice
#       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}
#
# Return:
#   None
def modify_slice_membership(slice_urn, credentials, options)
# Lookup members of given slice and their roles within that slice
#
# Arguments:
#   slice_urn: URN of slice for which to provide current members and roles
#
# Return:
#    List of dictionaries of member_urn/role pairs [{‘SLICE_MEMBER’: member_urn, ‘SLICE_ROLE’: role }...] where ‘role’ is a string of the role name
def 'lookup_slice_members(slice_urn, credentials, options)
# Lookup slices for which the given member belongs
#
# Arguments:
#   Member_urn: The member for whom to find slices to which it belongs
#
# Return:
#    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
def lookup_slices_for_member(member_urn, credentials, options)

Sliver Info Service Methods

Sliver 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.

It 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.

The 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:

Name Type Description Match Creation Update
SLIVER_INFO_SLICE_URN URN URN of slice for registered sliver Yes Required No
SLIVER_INFO_URN URN URN of registered sliver Yes Required No
SLIVER_INFO_AGGREGATE_URN URN URN of aggregate of registered sliver Yes Required No
SLIVER_INFO_CREATOR_URN URN URN of member/tool that created the registered sliver Yes Required No
SLIVER_INFO_EXPIRATION DATETIME Time of sliver expiration No Allowed Yes
SLIVER_INFO_CREATION DATETIME Time of sliver creation No Allowed No
# Create a record of a sliver creation
#
# Arguments:
#   options: 'fields' containing the fields for the sliver info  being registered at SA
#
# Return:
# Dictionary of name/value pairs for created sliver_info record
def create_sliver_info(credentials, options)
# Delete a sliver_info record
#
# Arguments:
#    sliver_urn: urn of sliver whose record is to be deleted
#
# Return:
#   True if succeeded
#
#Should return ARGUMENT_ERROR if no such sliver urn is registered
def delete_sliver_info(sliver_urn, credentials, options)
# Update the details of a sliver_info record
#
#Arguments:
#   sliver_urn: urn of sliver for which to update
#   options: 'fields' containing fields for sliver_infos that are permitted for update
#
# Return:
#   True if succeeded
#
# Should return ARGUMENT_ERROR if no such sliver_urn is found
def update_sliver_info(sliver_urn, credentials, options)
# Lookup sliver_info for given match criteria return fields in given filter criteria
#
# Arguments:
#   options: 'match' for query match criteria, 'filter' for fields to be returned
#
# Return:
#    Dictionary (indexed by sliver_urn) of dictionaries containing name/value pairs for all sliver_infos registered at this SA matching given criteria.
def lookup_sliver_info(credentials, options)

Project Service Methods

Projects 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).

The following table contains required fields for project objects and whether they are allowed in lookup ‘match’ criteria, required at creation or allowed at update:

Name Type Description Match Creation Update
PROJECT_URN URN URN of given project Yes No No
PROJECT_UID UID UID (unique within authority) of project Yes No No
PROJECT_CREATION DATETIME Creation time of project No No No
PROJECT_EXPIRATION DATETIME Expiration time of project No Allowed Yes
PROJECT_EXPIRED BOOLEAN Whether project has expired Yes No No
PROJECT_NAME STRING Short name of Project No Required No
PROJECT_DESCRIPTION STRING Description of Project No Allowed Yes
# Create project with given details. See generic create_* description above.
#
# Arguments:
#   Options: 'fields', a dictionary of name/value pairs for newly created project.
#
# Return:
#   Dictionary of name/value pairs of newly created project including urn
#
#Should return DUPLICATE_ERROR if creating a project for which a project of same name exists.
def create_project(credentials, options)
# Lookup project detail for projects matching ‘match options.
# ‘filter options indicate what detail to provide.
#
# Arguments:
#    options: What details to provide (filter options) for which members (match options)
#
# Return:
#    Dictionary of name/value pairs from ‘filter’ options for each project matching ‘match’ option criteria.
def lookup_projects(credentials, options)
# Update fields in given project object, as allowed in Get_version advertisement. See generic update_* description above.
#
# Arguments:
#    project_urn: URN of project to update
#    Options: Contains ‘fields’ key referencing dictionary of key/value pairs to update project
#
# Return: None
def update_project(project_urn, credentials, options)

Project Member Service Methods

Projects may have members associated with them in particular roles. See the Slice Member Service Methods above for more description.

# Modify project membership, adding, removing and changing roles of members with respect to given project
#
# Arguments:
#   project_urn: Name of project for which to modify membership
#   Options:
#      members_to_add: List of member_urn/role tuples for members to add to project of form {‘PROJECT_MEMBER’: member_urn, ‘PROJECT_ROLE’ : role}
#      members_to_remove: List of member_urn of members to remove from project
#      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}
#
# Return:  None
def modify_project_membership(project_urn, credentials, options)
# Lookup members of given project and their roles within that project
#
# Arguments:
#    project_urn: project_urn for which to provide current members and roles
#
#Return:
#   List of dictionaries of member_urn/role pairs of form [{‘PROJECT_MEMBER’: member_urn, ‘PROJECT_ROLE’: role}...]
def lookup_project_members (project_urn, credentials, options)
# Lookup projects for which the given member belongs
#
# Arguments:
#    Member_urn: The member for whom to find project to which it belongs
#
# Return:
#    Dictionary of slice_urn/role pairs (‘PROJECT_URN’ : project_urn, ‘PROJECT_ROLE’ : role} where role is a string of the role name
def lookup_projects_for_member(member_urn, credentials, options)

Member Authority API

The Member Authority API provides services to manage information about federation members including public and potentially private or identifying information.

As 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.

All MA calls are protected; passing and validating a client-side cert is required.

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:

  • The user/tool cert is signed by someone in the Federation's trust chain
  • 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.
  • 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.
  • Access to private info (SSL or SSH keys) should be restricted only to the user’s own keys for ordinary users.

Like 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:

Service Description Required
MEMBER Services to lookup and update information about members YES
KEY Services to support storing, deleting and retrieving keys (e.g. SSH) for members NO

Member Service Methods

The information managed by the MA API is divided into three categories, for purposes of applying different AuthZ policies at these different levels:

  • Public: Public information about a member (e.g. public SSH or SSH keys, speaks-for credentials, certificates)
  • 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
  • Identifying: Information that could identify the given member (e.g. name, email, affiliation)

The following table contains required fields for member objects and whether they are allowed in lookup ‘match’ criteria and their protection (public, private, identifying):

Name Type Description Match Protection
MEMBER_URN URN URN of given member Yes Public
MEMBER_UID UID UID (unique within authority) of member Yes Public
MEMBER_FIRSTNAME STRING First name of member Yes Identifying
MEMBER_LASTNAME STRING Last name of member Yes Identifying
MEMBER_USERNAME STRING Username of user Yes Public
MEMBER_EMAIL STRING Email of user No Identifying
# Return information about version and options (filter, query, credential types) accepted by this member authority
#
# Arguments: None
# 
# Return:
#     get_version structure information as described above
def get_version()
# Lookup public information about members matching given criteria
#
# Arguments:
#   options: set of ‘filter’ and ‘match’ criteria specifying which members and which fields for each member to return
#
# Return:
#   Dictionary indexed by member URN of dictionaries of name/value pairs of fields specified in ‘filter’ options for members matching ‘match’ criteria
def lookup_public_member_info (options)
# Lookup private (SSL/SSH key) information about members matching given criteria
#
# Arguments:
#    options: set of ‘filter’ and ‘match’ criteria specifying which members and which fields for each member to return
#
# Return:
#    Dictionary indexed by member URN of name/value pairs of fields specified in ‘filter’ options for members matching ‘match’ criteria
def lookup_private_member_info (credentials, options)
# Lookup identifying (e.g. name, email) info about matching members
#
# Arguments:
#    options: set of ‘filter’ and ‘match’ criteria specifying which members and which fields for each member to return
#
# Return:
#    Dictionary indexed by member URN of name/value pairs of fields specified in ‘filter’ options for members matching ‘match’ criteria
def  lookup_identifying_member_info(credentials, options)
# Update information about given member public, private or identifying information
#
# Arguments:
#    member_urn: URN of member for whom to set information
#    options: Containing ‘update’ key with dictionary of name/value pairs to update info for given member
#
# Return: None
def update_member_info(member_urn, credentials, options)
# Provide list of credentials (signed statements) for given member
# This is member-specific information suitable for passing as credentials in an AM API call for aggregate authorization.
# Arguments:
#    member_urn: URN of member for which to retrieve credentials
#    options: Potentially contains ‘speaking-for’ key indicating a speaks-for invocation (with certificate of the accountable member in the credentials argument)
#
# Return:
#     List of credential in “CREDENTIALS” format, i.e. a list of credentials with type information suitable for passing to aggregates speaking AM API V3.
def get_credentials(member_urn, credentials, options)

Key Service Methods

The 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.

The 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:

Name Type Description Match Creation Update
KEY_MEMBER URN URN of member associated with key pair Yes Required No
KEY_ID STRING Unique identifier of key: typically a fingerprint or hash of public key Yes No No
KEY_PUBLIC KEY Public key value Yes Required No
KEY_PRIVATE KEY Private key value Yes Allowed No
KEY_DESCRIPTION STRING Human readable description of key pair Yes Allowed Yes

Note 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.

# Create a record for a key pair for given member
#
# Arguments:
#    member_urn: URN of member for which to retrieve credentials
#    options: 'fields' containing the fields for the key pair being stored
#
# Return:
#    Dictionary of name/value pairs for created key record including the KEY_ID
#
# Should return DUPLICATE_ERROR if a key with the same KEY_ID is already stored for given user
def create_key(member_urn, credentials, options)
# Delete a key pair for given member
#
# Arguments:
#    member_urn: urn of member for which to delete key pair
#    key_id: KEY_ID (fingerprint) of key pair to be deleted
#
# Return:
#    True if succeeded 
#
# Should return ARGUMENT_ERROR if no such key is found for user
def delete_key(member_urn, key_id, credentials, options)
# Update the details of a key pair for given member
#
# Arguments:
#    member_urn: urn of member for which to delete key pair
#    key_id: KEY_ID (fingerprint) of key pair to be deleted
#    options: 'fields' containing fields for key pairs that are permitted for update
#
# Return:
#    True if succeeded 
#
# Should return ARGUMENT_ERROR if no such key is found for user
def update_key(member_urn, key_id, credentials, options)
# Lookup keys for given match criteria return fields in given filter criteria
#
# Arguments:
#    options: 'match' for query match criteria, 'filter' for fields to be returned
#
# Return:
#    Dictionary (indexed by member_urn) of dictionaries containing name/value pairs for all keys registered for that given user.
def lookup_keys(credentials, options)

Appendix: Federation Object Models

As 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.

Different 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.

The following diagram reflects the different objects maintained within the full range of Authority services, their interactions and mandatory fields.

No image "FedObjectModel.pdf" attached to UniformClearinghouseAPI

Appendix B: API Data Types

The following table describes the data types referenced in the document above, in terms of format and meaning.

Type Description Format
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)
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.
STRING Generic UTF-8 string
INTEGER Generic integer argument
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
EMAIL Well-formed email address Example: jbrown@geni.net
KEY SSH or SSL public or private key (contents, not filename) Key-specific format
BOOLEAN True or False (case insensitive) Example: True
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> } ]
CERTIFICATE X509 certificate (contents, not filename) Standard X509 certificate format

As noted above, this list is subject to change as the API develops over time.