Permissions

Apps have fine grained permissions similar to those found in the Jobs and Files services. Using these, you can share your app other Tapis users. App permissions are private by default, so when you first POST your app to the Apps service, you are the only one who can see it. You may share your app with other users by granting them varying degrees of permissions. The full list of app permission values are listed in the following table.

Permission Description
READ Gives the ability to view the app description.
WRITE Gives the ability to update the app.
EXECUTE Gives the ability to submit jobs using the app
ALL Gives full READ and WRITE and EXECUTE permissions to the user.
READ_WRITE Gives full READ and WRITE permissions to the user
READ_EXECUTE Gives full READ and EXECUTE permissions to the user
WRITE_EXECUTE Gives full WRITE and EXECUTE permissions to the user

App permissions are distinct from all other roles and permissions and do not have implications outside the Apps service. This means that if you want to allow someone to run a job using your app, it is not sufficient to grant them READ_EXECUTE permissions on your app. They must also have an appropriate user role on the execution system on which the app will run. Similarly, if you do not have the right to publish on the executionSystem or access the deploymentPath on the deploymentSystem in your app description, you will not be able to publish your app.

Listing permissions

App permissions are managed through a set of URLs consistent with the permission operations elsewhere in the API. To query for a user’s permission for an app, perform a GET on the user’s unique app permissions url.

You can use the following CLI command:

apps-pems-list -v -u $USERNAME $APP_ID
Show curl
curl -sk -H "Authorization: Bearer $ACCESS_TOKEN" \
https://agave.iplantc.org/apps/v2/$APP_ID/pems/$USERNAME?pretty=true

The response from the service will be a JSON object representing the user permission. If the user does not have a permission for that app, the permission value will be NONE. By default, only you have permission to your private apps. Public apps will return a single permission for the public meta user rather than return a permissions for every user.

Show json response
{
"username": "$USERNAME",
"permission": {
  "read": true,
  "write": true,
  "execute": true
},
"_links": {
  "self": {
    "href": "https://agave.iplantc.org/apps/v2/$APP_ID/pems/$USERNAME"
  },
  "app": {
    "href": "https://agave.iplantc.org/apps/v2/$APP_ID"
  },
  "profile": {
    "href": "https://agave.iplantc.org/profiles/v2/$USERNAME"
  }
}
}

You can also query for all permissions granted on a specific app by making a GET request on the app’s permission collection.

apps-pems-list -v $APP_ID
Show curl
curl -sk -H "Authorization: Bearer $ACCESS_TOKEN" \
https://agave.iplantc.org/apps/v2/$APP_ID/pems?pretty=true

This time the service will respond with a JSON array of permission objects.

Show json response
{
  "username": "$USERNAME",
  "permission": {
    "read": true,
    "write": true,
    "execute": true
  },
  "_links": {
    "self": {
      "href": "https://agave.iplantc.org/apps/v2/$APP_ID/pems/$USERNAME"
    },
    "app": {
      "href": "https://agave.iplantc.org/apps/v2/$APP_ID"
    },
    "profile": {
      "href": "https://agave.iplantc.org/profiles/v2/$USERNAME"
    }
  }
}

Adding and updating permissions

Setting permissions is done by posting a JSON object containing a permission and username. Alternatively, you can POST just the permission and append the username to the URL.

apps-pems-update -v -u bgibson -p READ $APP_ID
Show curl
# Standard syntax to grant permissions to a specific user
curl -sk -H "Authorization: Bearer $ACCESS_TOKEN" -X POST -d "username=bgibson&permission=READ" https://agave.iplantc.org/apps/v2/$APP_ID/pems?pretty=true

# Abbreviated POST data to grant permission to a single user
curl -sk -H "Authorization: Bearer $ACCESS_TOKEN" -X POST -d "permission=READ" https://agave.iplantc.org/apps/v2/$APP_ID/pems/bgibson?pretty=true

The response will contain a JSON object representing the permission that was just created.
Show json response
{
"username": "bgibson",
"permission": {
  "read": true,
  "write": false,
  "execute": false
},
"_links": {
  "self": {
    "href": "https://agave.iplantc.org/apps/v2/$APP_ID/pems/bgibson"
  },
  "app": {
    "href": "https://agave.iplantc.org/apps/v2/$APP_ID"
  },
  "profile": {
    "href": "https://agave.iplantc.org/profiles/v2/bgibson"
  }
}
}

Deleting permissions

Permissions can be deleted on a user-by-user basis, or all at once. To delete an individual user permission, make a DELETE request on the user’s app permission URL.

apps-pems-delete -u bgibson $APP_ID
Show curl
curl -sk -H "Authorization: Bearer $ACCESS_TOKEN" -X DELETE https://agave.iplantc.org/apps/v2/$APP_ID/pems/bgibson?pretty=true

Show response

The CLI response will be:

Successfully removed permission for bgibson on app $APP_ID

And the cURL response will be an empty result object. |

You can accomplish the same thing by updating the user permission to an empty value.

apps-pems-update -v -u bgibson $APP_ID
Show curl
# Delete permission for a single user by updating with an empty permission value
curl -sk -H "Authorization: Bearer $ACCESS_TOKEN"  \
    -X POST -d "username=bgibson" -d "permission=NONE" \
    https://agave.iplantc.org/apps/v2/$APP_ID/pems?pretty=true

# Delete permission for a single user by updating with an empty permission value
curl -sk -H "Authorization: Bearer $ACCESS_TOKEN" \
    -X POST -d "permission=" \
    https://agave.iplantc.org/apps/v2/$APP_ID/pems/bgibson?pretty=true

Since this is an update operation, the resulting JSON permission object will be returned showing the user has no permissions to the app anymore.

Show json response
{
"username": "bgibson",
"permission": {
  "read": false,
  "write": false,
  "execute": false
},
"_links": {
  "self": {
    "href": "https://agave.iplantc.org/apps/v2/$APP_ID/pems/bgibson"
  },
  "app": {
    "href": "https://agave.iplantc.org/apps/v2/$APP_ID"
  },
  "profile": {
    "href": "https://agave.iplantc.org/profiles/v2/bgibson"
  }
}
}

To delete all permissions for an app, make a DELETE request on the app’s permissions collection.

apps-pems-delete $APP_ID
Show curl
curl -sk -H "Authorization: Bearer $ACCESS_TOKEN" \
    -X DELETE \
    https://agave.iplantc.org/apps/v2/$APP_ID/pems?pretty=true

The response will be an empty result object.

App Publishing

In addition to traditional permissions, apps also have a concept of scope. Unless otherwise configured, apps are private to the owner and the users they grant permission. Applications can, however move from the private space into the public space for use any anyone. Moving an app into the public space is called publishing. Publishing an app gives it much greater exposure and results in increased usage by the user community. It also comes with increased responsibilities for the original owner as well as the API administrators. Several of these are listed below:

  • Public apps must run on public systems. This makes the app available to everyone.
  • Public apps must be vetted for performance, reliability, and security by the API administrators.
  • The original app author must remain available via email for ongoing support.
  • Public apps must be copied into a public repository and checksummed.
  • Updates to public apps must result in a snapshot of the original app being created and stored with its resulting checksum in a separate location.
  • API administrators must maintain and support the app throughout its lifetime.
information_source:
 If you have an app you would like to see published, please contact your API administrators for more information.

Publishing an app

To publish an app, make a PUT request on the app resource. In this example, we publish the wc-osg-1.00 app.

apps-publish -e condor.opensciencegrid.org wc-osg-1.00
Show curl
curl -sk -H "Authorization: Bearer $ACCESS_TOKEN"
    -H "Content-Type: application/json"
    -X PUT
    --data-binary '{"action":"publish","executionSystem":"condor.opensciencegrid.org"}'
    https://agave.iplantc.org/apps/v2/wc-osg-1.00?pretty=true

The response from the service will resemble the following:
Show json response
{
"id": "wc-osg-1.00u1",
"name": "wc-osg",
"icon": null,
"uuid": "8734854070765284890-242ac116-0001-005",
"parallelism": "SERIAL",
"defaultProcessorsPerNode": 1,
"defaultMemoryPerNode": 1,
"defaultNodeCount": 1,
"defaultMaxRunTime": null,
"defaultQueue": null,
"version": "1.00",
"revision": 1,
"isPublic": false,
"helpURI": "http://www.gnu.org/s/coreutils/manual/html_node/wc-invocation.html",
"label": "wc condor",
"shortDescription": "Count words in a file",
"longDescription": "",
"tags": [
  "gnu",
  "textutils"
],
"ontology": [
  "http://sswapmeet.sswap.info/algorithms/wc"
],
"executionType": "CONDOR",
"executionSystem": "condor.opensciencegrid.org",
"deploymentPath": "/agave/apps/wc-1.00",
"deploymentSystem": "public.storage.agave",
"templatePath": "/wrapper.sh",
"testPath": "/wrapper.sh",
"checkpointable": true,
"lastModified": "2016-09-15T04:48:17.000-05:00",
"modules": [
  "load TACC",
  "purge"
],
"available": true,
"inputs": [
  {
    "id": "query1",
    "value": {
      "validator": "",
      "visible": true,
      "required": false,
      "order": 0,
      "enquote": false,
      "default": [
        "read1.fq"
      ]
    },
    "details": {
      "label": "File to count words in: ",
      "description": "",
      "argument": null,
      "showArgument": false,
      "repeatArgument": false
    },
    "semantics": {
      "minCardinality": 1,
      "maxCardinality": -1,
      "ontology": [
        "http://sswapmeet.sswap.info/util/TextDocument"
      ],
      "fileTypes": [
        "text-0"
      ]
    }
  }
],
"parameters": [],
"outputs": [
  {
    "id": "outputWC",
    "value": {
      "validator": "",
      "order": 0,
      "default": "wc_out.txt"
    },
    "details": {
      "label": "Text file",
      "description": "Results of WC"
    },
    "semantics": {
      "minCardinality": 1,
      "maxCardinality": 1,
      "ontology": [
        "http://sswapmeet.sswap.info/util/TextDocument"
      ],
      "fileTypes": []
    }
  }
],
"_links": {
  "self": {
    "href": "https://api.tacc.utexas.edu/apps/v2/wc-osg-1.00u1"
  },
  "executionSystem": {
    "href": "https://api.tacc.utexas.edu/systems/v2/condor.opensciencegrid.org"
  },
  "storageSystem": {
    "href": "https://api.tacc.utexas.edu/systems/v2/public.storage.agave"
  },
  "history": {
    "href": "https://api.tacc.utexas.edu/apps/v2/wc-osg-1.00u1/history"
  },
  "metadata": {
    "href": "https://api.tacc.utexas.edu/meta/v2/data/?q=%7B%22associationIds%22%3A%228734854070765284890-242ac116-0001-005%22%7D"
  },
  "owner": {
    "href": "https://papi.tacc.utexas.edu/profiles/v2/nryan"
  },
  "permissions": {
    "href": "https://api.tacc.utexas.edu/apps/v2/wc-osg-1.00u1/pems"
  }
}
}

Notice a few things about the response.

  1. Both the executionSystem and deploymentSystem have changed. Public apps must run and store their assets on public systems.
  2. We did not specify the deploymentSystem where the public app assets should be stored, so Tapis placed them on the default public storage system, public.storage.agave.
  3. We did not specify the deploymentPath where the public app assets should be stored, so Tapis placed them in the publicAppsDir of the deploymentPath.
  4. The deploymentPath is now a zip archive rather than a folder. Tapis does this because once, published, the app can no longer be updated, so the assets are frozen and stored in a separate location, removed from user access.
  5. The id of the app has changed. It now has a u1 appended to the original app id. This indicates that it is a public app and that it has been updated a single time. If we were to publish the app again, the resulting id would be wc-osg-1.00u2. This differs from unpublished apps whose revision number increments without impacting the app id. Every time you publish an app, the id of the resulting public app will change.

Disabling an App

Unpublishing a public system is equivalent to disabling it.

Unlike systems, it is not possible to unpublish an app. Once published, a deep copy of the app is store in an external location with its own provenance trail. If you would like to remove a published app from further use, simply disable it.

apps-disable -v $APP_ID
Show curl
curl -sk -H "Authorization: Bearer $ACCESS_TOKEN"
    -X PUT -d "action=disable"
    https://agave.iplantc.org/apps/v2/$APP_ID?pretty=true

The response will look identical to before, but with available set to false

Cloning an app

Often times you will want to copy an existing app for use on another system, or simply to obtain a private copy of the app for your own use. This can be done using the clone functionality in the Apps service. The following tabs show how to do this using the unix curl command as well as with the Tapis CLI.

apps-clone -N my-pyplot-demo -V 2.2 demo-pyplot-demo-advanced-0.1.0
Show curl
curl -sk -H "Authorization: Bearer $ACCESS_TOKEN" \
    -X PUT 'https://agave.iplantc.org/apps/v2/$APP_ID?pretty=true' \
    --data-urlencode action=clone \
    --data-urlencode name=$NEW_APP_NAME \
    --data-urlencode version=0.1.2 \
    --data-urlencode deploymentSystem= $STORAGE_SYSTEM \
    --data-urlencode executionSystem= $EXECUTION_SYSTEM

information_source:
 When cloning public apps, the entire app bundle will be recreated on the deploymentSystem you specify or your default storage system. The same is not true for private apps. Cloning a private app will copy the job description, but not the app bundle. This is to honor the original ownership of the assets and prevent them from leaking out to the public space without the owner’s permission. If you need direct access to the app’s assets, request that the owner give you read access to the folder listed as the deploymentPath in the app description.