The preparation for creating an account in Aruna is minimal. It is only required that you are already registered in a supported AAI. Currently that is:
GWDG SSO Service, i.e. DFN AAI, Life Science Login (ELIXIR AAI) or GfBio Accounts
These are also the current options that are offered if you want to register or login via the Aruna demo website. If you want to register via the Aruna API instead, you just have to put the OIDC token you received from one of the previously mentioned services into the user registration request header for authorization.
From here on you have two possibilities to authenticate/authorize all of your actions inside Aruna system:
You can use your OIDC token which consumes the granted permissions you have on resources.
You create API tokens which can either
Consume the permissions you have on resources
Have scoped permissions which are directly associated with the token
Client creation
If you plan to send your requests via gRPC the first step is to establish a connection to the gRPC gateway of the server you want to send the requests to.
The presence of a client connection to the specific resource service is required for all further requests in this tutorial if the requests are send via gRPC.
Development instance endpoint URLs
The development instance can be used for testing purposes. It can be accessed via the following URLs after successful registration.
Please remember that the development instance in no way guarantees data consistency and availability!
JSON-over-HTTP: https://api.dev.aruna-storage.org or localized e.g. https://api.gi.dev.aruna-storage.org
gRPC Clients: https://grpc.dev.aruna-storage.org or localized e.g. https://grpc.gi.dev.aruna-storage.org
DataProxies: e.g. https://proxy.gi.dev.aruna-storage.org
It is also emphasized that Aruna is a data orchestration engine that orchestrates data and metadata on behalf of multiple storage instances.
While we provide some physical storage for our partners, not all storage instances are operated by us.
Danger
These are minimal reproducible examples only for demonstration purposes which should not be used 'as-is' in a production environment!
To use the Rust API library you have to set it as dependency aruna-rust-api = "<Aruna-Rust-API-Version>" in the cargo.toml of your project.
You can find the latest version of the Aruna Rust API package on crates.io.
Note
This example additionally implements an interceptor which adds the authorization token automatically to each request send by the service clients.
It is a little more complicated and extra work up front but offers the advantage of having to worry less about the correct API token request metadata later.
All Rust examples in this documentation assume that the client services have been initialized with an interceptor.
usearuna_rust_api::api::storage::services::v2::{authorization_service_client::AuthorizationServiceClient,collection_service_client::CollectionServiceClient,dataset_service_client::DatasetServiceClient,object_service_client::ObjectServiceClient,project_service_client::ProjectServiceClient,storage_status_service_client::StorageStatusServiceClient,user_service_client::UserServiceClient,}usestd::sync::Arc;usetonic::codegen::InterceptedService;usetonic::metadata::{AsciiMetadataKey,AsciiMetadataValue};usetonic::transport::{Channel,ClientTlsConfig};// Create a client interceptor which always adds the specified api token to the request header#[derive(Clone)]pubstructClientInterceptor{api_token:String,}// Implement a request interceptor which always adds // the authorization header with a specific API token to all requestsimpltonic::service::InterceptorforClientInterceptor{fncall(&mutself,request:tonic::Request<()>)->Result<tonic::Request<()>,tonic::Status>{letmutmut_req:tonic::Request<()>=request;letmetadata=mut_req.metadata_mut();metadata.append(AsciiMetadataKey::from_bytes("Authorization".as_bytes()).unwrap(),AsciiMetadataValue::try_from(format!("Bearer {}",self.api_token.as_str())).unwrap(),);returnOk(mut_req);}}fnmain(){// Create connection to the Aruna instance via gRPCletapi_token="MySecretArunaApiToken".to_string();lettls_config=ClientTlsConfig::new();letendpoint=Channel::from_shared("https://<URL-To-Aruna-Instance-gRPC-endpoint>").unwrap().tls_config(tls_config).unwrap();letchannel=endpoint.connect().await.unwrap();letinterceptor=ClientInterceptor{api_token:api_token.clone()};// Create the individual client servicesletmutinfo_client=StorageStatusServiceClient::new(channel.clone());letmutauth_client=AuthorizationServiceClient::with_interceptor(channel.clone(),interceptor.clone());letmutuser_client=UserServiceClient::with_interceptor(channel.clone(),interceptor.clone());letmutproject_client=ProjectServiceClient::with_interceptor(channel.clone(),interceptor.clone());letmutcollection_client=CollectionServiceClient::with_interceptor(channel.clone(),interceptor.clone());letmutdataset_client=DatasetServiceClient::with_interceptor(channel.clone(),interceptor.clone());letmutobject_client=ObjectServiceClient::with_interceptor(channel.clone(),interceptor.clone());// let mut other_client = ...// Do something with the client services ...}
To use the Python API library in your Python project you have to install the PyPI package: pip install Aruna-Python-API.
Note
This example additionally implements an interceptor which adds the authorization token automatically to each request send by the service clients.
It is a little more complicated and extra work up front but offers the advantage of having to worry less about the correct API token request metadata later.
All Python examples in this documentation assume that the client services have been initialized with an interceptor.
importcollectionsimportgrpcfromaruna.api.storage.services.v2.info_service_pb2_grpcimportStorageStatusServiceStubfromaruna.api.storage.services.v2.authorization_service_pb2_grpcimportAuthorizationServiceStubfromaruna.api.storage.services.v2.user_service_pb2_grpcimportUserServiceStubfromaruna.api.storage.services.v2.project_service_pb2_grpcimportProjectServiceStubfromaruna.api.storage.services.v2.collection_service_pb2_grpcimportCollectionServiceStubfromaruna.api.storage.services.v2.dataset_service_pb2_grpcimportDatasetServiceStubfromaruna.api.storage.services.v2.object_service_pb2_grpcimportObjectServiceStub# Valid Aruna API token# In a production environment this should be stored in a more secure location ...API_TOKEN='MySecretArunaApiToken'# Aruna instance gRPC endpointARUNA_HOST='<URL-To-Aruna-Instance-gRPC-endpoint>'# Protocol (e.g. https://) has to be omittedARUNA_PORT='443'class_MyAuthInterceptor(grpc.UnaryUnaryClientInterceptor):""" Implement abstract class grpc.UnaryUnaryClientInterceptor to extend request metadata. """defintercept_unary_unary(self,continuation,client_call_details,request):# Append authorization token to request metadatametadata=[]ifclient_call_details.metadataisnotNone:metadata=list(client_call_details.metadata)metadata.append(('authorization',f'Bearer {API_TOKEN}'))# Continue with new client call detailsrequest_iterator=iter((request,))updated_details=_ClientCallDetails(client_call_details.method,client_call_details.timeout,metadata,client_call_details.credentials)returncontinuation(updated_details,next(request_iterator))class_ClientCallDetails(collections.namedtuple('_ClientCallDetails',('method','timeout','metadata','credentials')),grpc.ClientCallDetails):""" Implement grpc.ClientCallDetails to pass modified request details in interceptor. """passclassArunaClient(object):""" Class to contain the Aruna gRPC client service stubs for easier usage. """def__init__(self,):ssl_credentials=grpc.ssl_channel_credentials()self.secure_channel=grpc.secure_channel("{}:{}".format(ARUNA_HOST,ARUNA_PORT),ssl_credentials)self.intercept_channel=grpc.intercept_channel(self.secure_channel,_MyAuthInterceptor())self.info_client=StorageStatusServiceStub(self.intercept_channel)self.auth_client=AuthorizationServiceStub(self.intercept_channel)self.user_client=UserServiceStub(self.intercept_channel)self.project_client=ProjectServiceStub(self.intercept_channel)self.collection_client=CollectionServiceStub(self.intercept_channel)self.dataset_client=DatasetServiceStub(self.intercept_channel)self.object_client=ObjectServiceStub(self.intercept_channel)# self.other_client = ...# Entry point of the scriptif__name__=='__main__':# Instantiate ArunaClientclient=ArunaClient()# Do something with the client services ...
To use the Python API library in your Python project you have to install the PyPI package: pip install Aruna-Python-API.
Note
This example does not consider adding the authorization token metadata to every request.
In this case you have to manually add the authorization token header by using the with_call(...) extension of the client service methods.
All Python examples in this documentation assume that the client services have been initialized with an interceptor.
importgrpcfromaruna.api.storage.services.v2.info_service_pb2_grpcimportStorageStatusServiceStubfromaruna.api.storage.services.v2.authorization_service_pb2_grpcimportAuthorizationServiceStubfromaruna.api.storage.services.v2.user_service_pb2_grpcimportUserServiceStubfromaruna.api.storage.services.v2.project_service_pb2_grpcimportProjectServiceStubfromaruna.api.storage.services.v2.collection_service_pb2_grpcimportCollectionServiceStubfromaruna.api.storage.services.v2.dataset_service_pb2_grpcimportDatasetServiceStubfromaruna.api.storage.services.v2.object_service_pb2_grpcimportObjectServiceStub# Valid Aruna API token# In a production environment this should be stored in a more secure location ...API_TOKEN='MySecretArunaApiToken'# Aruna instance gRPC endpointARUNA_HOST='<URL-To-Aruna-Instance-gRPC-Endpoint>'# Protocol (e.g. https://) has to be omittedARUNA_PORT='443'classArunaClient(object):""" Class to contain the Aruna gRPC client service stubs for easier usage. """def__init__(self):# Read TLS credentials from local trusted certificates and instantiate a channelssl_credentials=grpc.ssl_channel_credentials()self.channel=grpc.secure_channel("{}:{}".format(ARUNA_HOST,ARUNA_PORT),ssl_credentials)self.info_client=StorageStatusServiceStub(self.channel)self.auth_client=AuthorizationServiceStub(self.channel)self.user_client=UserServiceStub(self.channel)self.project_client=ProjectServiceStub(self.channel)self.collection_client=CollectionServiceStub(self.channel)self.dataset_client=DatasetServiceStub(self.channel)self.object_client=ObjectServiceStub(self.channel)# self.xyz_client = ...# Entry point of the Python scriptif__name__=='__main__':# Instantiate ArunaClientclient=ArunaClient()# Do something with the client services ... for example:response,call=client.user_client.GetUser.with_call(request=GetUserRequest(),metadata=(('Authorization',f"Bearer {API_TOKEN}"),))
User registration
Users can register themselves with an email address and an individual display name in an Aruna instance.
You only need the valid OIDC token received from one of the supported AAI logins.
The display_name and email parameters are mandatory while project is optional.
The provided email will only be used for system-relevant notifications e.g. advance notifications of maintenance.
The project parameter is a hint for the administrators to associate the newly registered user with a project for identification purposes.
1 2 3 4 5 6 7 8 910
# Native JSON request to register OIDC user
curl-d' { "display_name": "Forename Surname", "email": "forename.surname@example.com", "project": "My little science project" }'\ -H'Authorization: Bearer <AUTH_TOKEN>'\ -H'Content-Type: application/json'\ -XPOSThttps://<URL-to-Aruna-instance-API-endpoint>/v2/user/register
1 2 3 4 5 6 7 8 9101112131415
// Create tonic/ArunaAPI request to register OIDC userletrequest=RegisterUserRequest{display_name:"Forename Surname".to_string(),email:"forename.surname@example.com".to_string(),project:"My little science project".to_string(),};// Send the request to the Aruna instance gRPC endpointletresponse=user_client.register_user(request).await.unwrap().into_inner();// Do something with the responseprintln!("Registered user: {:#?}",response.user_id)
1 2 3 4 5 6 7 8 91011121314
# Create tonic/ArunaAPI request to register OIDC userrequest=RegisterUserRequest(display_name="Forename Surname",email="forename.surname@example.com",project="My little science project")# Send the request to the Aruna instance gRPC endpointresponse=client.user_client.RegisterUser(request=request)# Do something with the responseprint(f'{response}')
User activation
After registration users additionally have to be activated once in a second step to prevent misuse of the system.
Required permissions
Users can only be activated by Aruna global administrators.
1234
# For convenience, administrators can request info on all unactivated users at once
curl-H'Authorization: Bearer <AUTH_TOKEN>'\ -H'Content-Type: application/json'\ -XGEThttps://<URL-to-Aruna-instance-API-endpoint>/v2/user/not_activated
1234
# Native JSON request to activate registered user
curl-H'Authorization: Bearer <AUTH_TOKEN>'\-H'Content-Type: application/json'\-XPATCHhttps://<URL-to-Aruna-instance-API-endpoint>/v2/user/{user-id}/activate
1 2 3 4 5 6 7 8 91011
// Create tonic/ArunaAPI request to fetch all not activated usersletrequest=GetNotActivatedUsersRequest{};// Send the request to the Aruna instance gRPC gatewayletunactivated=user_client.get_not_activated_users(request).await.unwrap().into_inner();// Do something with the responseprintln!("{:#?}",unactivated);
1 2 3 4 5 6 7 8 910111213
// Create tonic/ArunaAPI request for user activation letrequest=ActivateUserRequest{user_id:"<user-id>".to_string()// Has to be a valid ULID of a registered user};// Send the request to the Aruna instance gRPC endpointletresponse=user_client.activate_user(request).await.unwrap().into_inner();// Do something with the responseprintln!("Activated user: {:#?}",response.user_id)
12345678
# Create tonic/ArunaAPI request to fetch all not activated usersrequest=GetNotActivatedUsersRequest()# Send the request to the Aruna instance gRPC endpointresponse=client.user_client.GetNotActivatedUsers(request=request)# Do something with the responseprint(f'{response}')
1 2 3 4 5 6 7 8 910
# Create tonic/ArunaAPI request for user activationrequest=ActivateUserRequest(user_id="<user-id>"# Has to be a valid ULID of a registered user)# Send the request to the Aruna instance gRPC endpointresponse=client.user_client.ActivateUser(request=request)# Do something with the responseprint(f'{response}')
Who am I / What am I
To check which user a token is associated with or get information about the current users permissions, you can use the UserService API.
Required permissions
Registered users do not need special permissions to fetch information about their user account.
Only Aruna global administrators can request user information of other users i.e. set the user_id parameter of the request to the id of another user.
1234
# Native JSON request to fetch user information associated with authorization token
curl-H'Authorization: Bearer <AUTH_TOKEN>'\-H'Content-Type: application/json'\-XGEThttps://<URL-to-Aruna-instance-API-endpoint>/v2/user
1234
# Native JSON request to fetch user information associated with the provided user id
curl-H'Authorization: Bearer <AUTH_TOKEN>'\-H'Content-Type: application/json'\-XGET'https://<URL-to-Aruna-instance-API-endpoint>/v2/user?userId=<user-id>'
1 2 3 4 5 6 7 8 910111213
// Create tonic/ArunaAPI request to fetch user info of current userletrequest=GetUserRequest{user_id:"".to_string()};// Send the request to the Aruna instance gRPC endpointletresponse=user_client.get_user(request).await.unwrap().into_inner();// Do something with the responseprintln!("{:#?}",response);
12345678
# Create tonic/ArunaAPI request to fetch user info of current userrequest=GetUserRequest()# Send the request to the Aruna instance gRPC endpointresponse=client.user_client.GetUser(request=request)# Do something with the responseprint(f'{response}')