Providers, the backbone of UCloud, expose compute and storage resources to end-users.
Rationale
UCloud/Core is an orchestrator of Resources. This means, that the core doesn't actually know how to serve files or run computational workloads. Instead, the core must ask one or more Providers to fulfil requests from the user.
Figure: UCloud/Core receives a request from the user and forwards it to a provider.
The core isn't a simple proxy. Before passing the request, UCloud performs the following tasks:
Authentication: UCloud ensures that users have authenticated.
Authorization: The Project system of UCloud brings role-based authorization to all Resources. The core verifies all actions before forwarding the request.
Resolving references: UCloud maintains a catalog of all Resources in the system. All user requests only contain a reference to these Resources. UCloud verifies and resolves all references before proxying the request.
The communication between UCloud/Core and the provider happens through the provider APIs. Throughout the developer guide, you will find various sections describing these APIs. These APIs contain both an ingoing (from the provider's perspective) and outgoing APIs. This allows for bidirectional communication between both parties. In almost all cases, the communication from the user goes through UCloud/Core. The only exception to this rule is when the data involved is either sensitive or large. In these cases, UCloud will only be responsible for facilitating direct communication. A common example of this is file uploads.
/* This example shows an example provider. The provider's specification contains basic contactinformation. This information is used by UCloud when it needs to communicate with a provider. */Providers.retrieveSpecification.call(FindByStringId( id ="51231", ), admin).orThrow()/*ProviderSpecification( domain = "provider.example.com", https = true, id = "example", port = 443, product = ProductReference( category = "", id = "", provider = "ucloud_core", ), )*/
Communication Flow: Curl
# ------------------------------------------------------------------------------------------------------# $host is the UCloud instance to contact. Example: 'http://localhost:8080' or 'https://cloud.sdu.dk'# $accessToken is a valid access-token issued by UCloud# ------------------------------------------------------------------------------------------------------# This example shows an example provider. The provider's specification contains basic contact# information. This information is used by UCloud when it needs to communicate with a provider.# Authenticated as admincurl-XGET-H"Authorization: Bearer $accessToken""$host/api/providers/retrieveSpecification?id=51231"# {# "id": "example",# "domain": "provider.example.com",# "https": true,# "port": 443,# "product": {# "id": "",# "category": "",# "provider": "ucloud_core"# }# }
Communication Flow: Visual
Example: Registering a Provider
Frequency of use
Common
Actors
The integration module (unauthenticated) (integrationModule)
The admin of the provider (authenticated as a normal UCloud user) (systemAdministrator)
A UCloud administrator (admin)
The UCloud/Core service user (ucloud)
Communication Flow: Kotlin
/* WARNING: The following flow still works, but is no longer used by the default configuration ofthe integration module. Instead, it has been replaced by the much simpler approach of havinga UCloud administrator register the provider manually and then exchange tokens out-of-band. *//* This example shows how a Provider registers with UCloud/Core. In this example, the Provider will be using the Integration Module. The system administrator, of the Provider, has just installed the Integration Module. Before starting the module, the system administrator has configured the module to contact UCloud at a known address. *//* When the system administrator launches the Integration Module, it will automatically contact UCloud. This request contains the contact information back to the Provider. */Providers.requestApproval.call( ProvidersRequestApprovalRequest.Information( specification =ProviderSpecification( domain ="provider.example.com", https =true, id ="example", port =null, product =ProductReference( category ="", id ="", provider ="ucloud_core", ), ), ), integrationModule).orThrow()/*ProvidersRequestApprovalResponse.RequiresSignature( token = "9eb96d0a27b1330cdc727ef4316bd48265f71414", )*//* UCloud/Core responds with a token and the IM displays a link to the sysadmin. The sysadmin follows this link, and authenticates with their own UCloud user. This triggers the following request: */Providers.requestApproval.call( ProvidersRequestApprovalRequest.Sign( token ="9eb96d0a27b1330cdc727ef4316bd48265f71414", ), integrationModule).orThrow()/*ProvidersRequestApprovalResponse.RequiresSignature( token = "9eb96d0a27b1330cdc727ef4316bd48265f71414", )*//* The sysadmin now sends his token to a UCloud administrator. This communication always happen out-of-band. For a production system, we expect to have been in a dialogue with you about this process already.The UCloud administrator approves the request. */Providers.approve.call(ProvidersApproveRequest( token ="9eb96d0a27b1330cdc727ef4316bd48265f71414", ), admin).orThrow()/*FindByStringId( id = "51231", )*//* UCloud/Core sends a welcome message to the Integration Module. The core uses the original token to authenticate the request. The request also contains the refreshToken and publicKey required by the IM. Under normal circumstances, the IM will auto-configure itself to use these tokens. */IntegrationProvider.welcome.call(IntegrationProviderWelcomeRequest( createdProvider =ProviderWelcomeTokens( publicKey ="~~ public key ~~", refreshToken ="8accc446c2e3ac924ff07c77d93e1679378a5dad", ), token ="9eb96d0a27b1330cdc727ef4316bd48265f71414", ), ucloud).orThrow()/*Unit*//* Alternatively, the sysadmin can read the tokens and perform manual configuration. */Providers.retrieve.call(ResourceRetrieveRequest( flags =ProviderIncludeFlags( filterCreatedAfter =null, filterCreatedBefore =null, filterCreatedBy =null, filterIds =null, filterName =null, filterProductCategory =null, filterProductId =null, filterProvider =null, filterProviderIds =null, hideProductCategory =null, hideProductId =null, hideProvider =null, includeOthers =false, includeProduct =false, includeSupport =false, includeUpdates =false, ), id ="51231", ), systemAdministrator).orThrow()/*Provider( createdAt = 1633329776235, id = "51231", owner = ResourceOwner( createdBy = "sysadmin", project = null, ), permissions = null, publicKey = "~~ public key ~~", refreshToken = "8accc446c2e3ac924ff07c77d93e1679378a5dad", specification = ProviderSpecification( domain = "provider.example.com", https = true, id = "example", port = null, product = ProductReference( category = "", id = "", provider = "ucloud_core", ), ), status = ProviderStatus( resolvedProduct = null, resolvedSupport = null, ), updates = emptyList(), providerGeneratedId = "51231", )*/
Communication Flow: Curl
# ------------------------------------------------------------------------------------------------------# $host is the UCloud instance to contact. Example: 'http://localhost:8080' or 'https://cloud.sdu.dk'# $accessToken is a valid access-token issued by UCloud# ------------------------------------------------------------------------------------------------------# WARNING: The following flow still works, but is no longer used by the default configuration of# the integration module. Instead, it has been replaced by the much simpler approach of having# a UCloud administrator register the provider manually and then exchange tokens out-of-band.# This example shows how a Provider registers with UCloud/Core. In this example, the Provider will # be using the Integration Module. The system administrator, of the Provider, has just installed the # Integration Module. Before starting the module, the system administrator has configured the module # to contact UCloud at a known address.# When the system administrator launches the Integration Module, it will automatically contact # UCloud. This request contains the contact information back to the Provider.# Authenticated as integrationModulecurl -XPOST -H "Authorization: Bearer $accessToken" -H "Content-Type: content-type: application/json; charset=utf-8" "$host/api/providers/requestApproval" -d '{
"type":"information","specification":{"id":"example","domain":"provider.example.com","https":true,"port":null,"product":{"id":"","category":"","provider":"ucloud_core" } }}'# {# "type": "requires_signature",# "token": "9eb96d0a27b1330cdc727ef4316bd48265f71414"# }# UCloud/Core responds with a token and the IM displays a link to the sysadmin. The sysadmin follows # this link, and authenticates with their own UCloud user. This triggers the following request:curl -XPOST -H "Authorization: Bearer $accessToken" -H "Content-Type: content-type: application/json; charset=utf-8" "$host/api/providers/requestApproval" -d '{
"type":"sign","token":"9eb96d0a27b1330cdc727ef4316bd48265f71414"}'# {# "type": "requires_signature",# "token": "9eb96d0a27b1330cdc727ef4316bd48265f71414"# }# The sysadmin now sends his token to a UCloud administrator. This communication always happen # out-of-band. For a production system, we expect to have been in a dialogue with you about this # process already.# # The UCloud administrator approves the request.# Authenticated as admincurl -XPOST -H "Authorization: Bearer $accessToken" -H "Content-Type: content-type: application/json; charset=utf-8" "$host/api/providers/approve" -d '{
"token":"9eb96d0a27b1330cdc727ef4316bd48265f71414"}'# {# "id": "51231"# }# UCloud/Core sends a welcome message to the Integration Module. The core uses the original token to # authenticate the request. The request also contains the refreshToken and publicKey required by the # IM. Under normal circumstances, the IM will auto-configure itself to use these tokens.# Authenticated as ucloudcurl -XPOST -H "Authorization: Bearer $accessToken" -H "Content-Type: content-type: application/json; charset=utf-8" "$host/ucloud/example/integration/welcome" -d '{
"token":"9eb96d0a27b1330cdc727ef4316bd48265f71414","createdProvider":{"refreshToken":"8accc446c2e3ac924ff07c77d93e1679378a5dad","publicKey":"~~ public key ~~" }}'# {# }# Alternatively, the sysadmin can read the tokens and perform manual configuration.# Authenticated as systemAdministratorcurl -XGET -H "Authorization: Bearer $accessToken" "$host/api/providers/retrieve?includeOthers=false&includeUpdates=false&includeSupport=false&includeProduct=false&id=51231"
# {# "id": "51231",# "specification": {# "id": "example",# "domain": "provider.example.com",# "https": true,# "port": null,# "product": {# "id": "",# "category": "",# "provider": "ucloud_core"# }# },# "refreshToken": "8accc446c2e3ac924ff07c77d93e1679378a5dad",# "publicKey": "~~ public key ~~",# "createdAt": 1633329776235,# "status": {# "resolvedSupport": null,# "resolvedProduct": null# },# "updates": [# ],# "owner": {# "createdBy": "sysadmin",# "project": null# },# "permissions": null# }
Communication Flow: Visual
Example: A Provider authenticating with UCloud/Core
Frequency of use
Common
Pre-conditions
The provider has already been registered with UCloud/Core
Actors
The UCloud/Core service user (ucloud)
The provider (provider)
Communication Flow: Kotlin
/* 📝 Note: The tokens shown here are not representative of tokens you will see in practice */AuthProviders.refresh.call(bulkRequestOf(RefreshToken( refreshToken ="fb69e4367ee0fe4c76a4a926394aee547a41d998", )), provider).orThrow()/*BulkResponse( responses = listOf(AccessToken( accessToken = "eyJhbGciOiJIUzM4NCIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIjUF9leGFtcGxlIiwicm9sZSI6IlBST1ZJREVSIiwiaWF0IjoxNjMzNTIxMDA5LCJleHAiOjE2MzM1MjE5MTl9.P4zL-LBeahsga4eH0GqKpBmPf-Sa7pU70QhiXB1BchBe0DE9zuJ_6fws9cs9NOIo",
)), )*/
Communication Flow: Curl
# ------------------------------------------------------------------------------------------------------# $host is the UCloud instance to contact. Example: 'http://localhost:8080' or 'https://cloud.sdu.dk'# $accessToken is a valid access-token issued by UCloud# ------------------------------------------------------------------------------------------------------# 📝 Note: The tokens shown here are not representative of tokens you will see in practice# Authenticated as providercurl -XPOST -H "Authorization: Bearer $accessToken" -H "Content-Type: content-type: application/json; charset=utf-8" "$host/auth/providers/refresh" -d '{
"items": [ {"refreshToken":"fb69e4367ee0fe4c76a4a926394aee547a41d998" } ]}'# {# "responses": [# {# "accessToken": "eyJhbGciOiJIUzM4NCIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIjUF9leGFtcGxlIiwicm9sZSI6IlBST1ZJREVSIiwiaWF0IjoxNjMzNTIxMDA5LCJleHAiOjE2MzM1MjE5MTl9.P4zL-LBeahsga4eH0GqKpBmPf-Sa7pU70QhiXB1BchBe0DE9zuJ_6fws9cs9NOIo"
# }# ]# }
This request is sent by the client, if the client believes that initialization of resources might be needed. NOTE: This request might be sent even if initialization has already taken place. UCloud/Core does not check if initialization has already taken place, it simply validates the request.
renewToken
Replaces the current refresh-token and certificate of a Provider
⚠️ WARNING: This endpoint will immediately invalidate all traffic going to your Provider This endpoint should only be used if the current tokens are compromised.