diff --git a/satellite/console/consoleweb/server.go b/satellite/console/consoleweb/server.go index f620342ee..5c407b51f 100644 --- a/satellite/console/consoleweb/server.go +++ b/satellite/console/consoleweb/server.go @@ -80,6 +80,7 @@ type Config struct { GoogleTagManagerID string `help:"id for google tag manager" default:""` GeneralRequestURL string `help:"url link to general request page" default:"https://support.tardigrade.io/hc/en-us/requests/new?ticket_form_id=360000379291"` ProjectLimitsIncreaseRequestURL string `help:"url link to project limit increase request page" default:"https://support.tardigrade.io/hc/en-us/requests/new?ticket_form_id=360000683212"` + GatewayCredentialsRequestURL string `help:"url link for gateway credentials requests" default:""` RateLimit web.IPRateLimiterConfig @@ -288,6 +289,7 @@ func (server *Server) appHandler(w http.ResponseWriter, r *http.Request) { DefaultProjectLimit int GeneralRequestURL string ProjectLimitsIncreaseRequestURL string + GatewayCredentialsRequestURL string } data.SatelliteName = server.config.SatelliteName @@ -299,6 +301,7 @@ func (server *Server) appHandler(w http.ResponseWriter, r *http.Request) { data.DefaultProjectLimit = server.config.DefaultProjectLimit data.GeneralRequestURL = server.config.GeneralRequestURL data.ProjectLimitsIncreaseRequestURL = server.config.ProjectLimitsIncreaseRequestURL + data.GatewayCredentialsRequestURL = server.config.GatewayCredentialsRequestURL if server.templates.index == nil { server.log.Error("index template is not set") diff --git a/scripts/testdata/satellite-config.yaml.lock b/scripts/testdata/satellite-config.yaml.lock index f706fc320..2641130eb 100755 --- a/scripts/testdata/satellite-config.yaml.lock +++ b/scripts/testdata/satellite-config.yaml.lock @@ -88,6 +88,9 @@ compensation.withheld-percents: 75,75,75,50,50,50,25,25,25,0,0,0,0,0,0 # allow domains to embed the satellite in a frame, space separated # console.frame-ancestors: tardigrade.io +# url link for gateway credentials requests +# console.gateway-credentials-request-url: "" + # url link to general request page # console.general-request-url: https://support.tardigrade.io/hc/en-us/requests/new?ticket_form_id=360000379291 diff --git a/web/satellite/index.html b/web/satellite/index.html index 51783caa0..be987334b 100644 --- a/web/satellite/index.html +++ b/web/satellite/index.html @@ -12,6 +12,7 @@ + {{ .SatelliteName }} diff --git a/web/satellite/src/api/accessGrants.ts b/web/satellite/src/api/accessGrants.ts index b957ef4f2..3de470e32 100644 --- a/web/satellite/src/api/accessGrants.ts +++ b/web/satellite/src/api/accessGrants.ts @@ -2,13 +2,23 @@ // See LICENSE for copying information. import { BaseGql } from '@/api/baseGql'; -import { AccessGrant, AccessGrantCursor, AccessGrantsApi, AccessGrantsPage } from '@/types/accessGrants'; +import { + AccessGrant, + AccessGrantCursor, + AccessGrantsApi, + AccessGrantsPage, + GatewayCredentials, +} from '@/types/accessGrants'; +import { HttpClient } from '@/utils/httpClient'; +import { MetaUtils } from '@/utils/meta'; /** * AccessGrantsApiGql is a graphql implementation of Access Grants API. * Exposes all access grants-related functionality */ export class AccessGrantsApiGql extends BaseGql implements AccessGrantsApi { + private readonly client: HttpClient = new HttpClient(); + /** * Fetch access grants. * @@ -118,6 +128,37 @@ export class AccessGrantsApiGql extends BaseGql implements AccessGrantsApi { return response.data.deleteAPIKeys; } + /** + * Used to get gateway credentials using access grant. + * + * @param accessGrant - generated access grant + * @throws Error + */ + public async getGatewayCredentials(accessGrant: string): Promise { + const requestURL: string = MetaUtils.getMetaContent('gateway-credentials-request-url'); + if (!requestURL) throw new Error('Cannot get gateway credentials: request URL is not provided'); + + const path = `${requestURL}/v1/access`; + const body = { + access_grant: accessGrant, + public: false, + }; + const response = await this.client.post(path, JSON.stringify(body)); + if (!response.ok) { + throw new Error('Cannot get gateway credentials'); + } + + const result = await response.json(); + + return new GatewayCredentials( + result.id, + new Date(result.created_at), + result.access_key_id, + result.secret_key, + result.endpoint, + ); + } + /** * Method for mapping access grants page from json to AccessGrantsPage type. * diff --git a/web/satellite/src/store/modules/accessGrants.ts b/web/satellite/src/store/modules/accessGrants.ts index 9b994127d..89353431e 100644 --- a/web/satellite/src/store/modules/accessGrants.ts +++ b/web/satellite/src/store/modules/accessGrants.ts @@ -9,6 +9,7 @@ import { AccessGrantsOrderBy, AccessGrantsPage, DurationPermission, + GatewayCredentials, } from '@/types/accessGrants'; import { SortDirection } from '@/types/common'; @@ -17,6 +18,7 @@ export const ACCESS_GRANTS_ACTIONS = { CREATE: 'createAccessGrant', DELETE: 'deleteAccessGrants', CLEAR: 'clearAccessGrants', + GET_GATEWAY_CREDENTIALS: 'getGatewayCredentials', SET_SEARCH_QUERY: 'setAccessGrantsSearchQuery', SET_SORT_BY: 'setAccessGrantsSortingBy', SET_SORT_DIRECTION: 'setAccessGrantsSortingDirection', @@ -28,6 +30,7 @@ export const ACCESS_GRANTS_ACTIONS = { export const ACCESS_GRANTS_MUTATIONS = { SET_PAGE: 'setAccessGrants', + SET_GATEWAY_CREDENTIALS: 'setGatewayCredentials', TOGGLE_SELECTION: 'toggleAccessGrantsSelection', TOGGLE_BUCKET_SELECTION: 'toggleBucketSelection', CLEAR_SELECTION: 'clearAccessGrantsSelection', @@ -50,6 +53,7 @@ const { SET_SEARCH_QUERY, SET_PAGE_NUMBER, SET_DURATION_PERMISSION, + SET_GATEWAY_CREDENTIALS, } = ACCESS_GRANTS_MUTATIONS; export class AccessGrantsState { @@ -59,6 +63,7 @@ export class AccessGrantsState { public selectedBucketNames: string[] = []; public permissionNotBefore: Date = new Date(); public permissionNotAfter: Date = new Date('2200-01-01'); + public gatewayCredentials: GatewayCredentials = new GatewayCredentials(); } /** @@ -80,6 +85,9 @@ export function makeAccessGrantsModule(api: AccessGrantsApi): StoreModule { + const credentials: GatewayCredentials = await api.getGatewayCredentials(accessGrant); + + commit(SET_GATEWAY_CREDENTIALS, credentials); + }, setAccessGrantsSearchQuery: function ({commit}, search: string) { commit(SET_SEARCH_QUERY, search); }, diff --git a/web/satellite/src/types/accessGrants.ts b/web/satellite/src/types/accessGrants.ts index 48ee75cbe..7cda2e907 100644 --- a/web/satellite/src/types/accessGrants.ts +++ b/web/satellite/src/types/accessGrants.ts @@ -32,6 +32,14 @@ export interface AccessGrantsApi { * @throws Error */ delete(ids: string[]): Promise; + + /** + * Get gateway credentials using access grant + * + * @returns GatewayCredentials + * @throws Error + */ + getGatewayCredentials(accessGrant: string): Promise; } /** @@ -103,3 +111,16 @@ export class DurationPermission { public notAfter: Date = new Date(), ) {} } + +/** + * GatewayCredentials class holds info for gateway credentials generated from access grant. + */ +export class GatewayCredentials { + constructor( + public id: string = '', + public createdAt: Date = new Date(), + public accessKeyId: string = '', + public secretKey: string = '', + public endpoint: string = '', + ) {} +} diff --git a/web/satellite/tests/unit/mock/api/accessGrants.ts b/web/satellite/tests/unit/mock/api/accessGrants.ts index 82f4edec6..f01107a01 100644 --- a/web/satellite/tests/unit/mock/api/accessGrants.ts +++ b/web/satellite/tests/unit/mock/api/accessGrants.ts @@ -1,7 +1,13 @@ // Copyright (C) 2020 Storj Labs, Inc. // See LICENSE for copying information. -import { AccessGrant, AccessGrantCursor, AccessGrantsApi, AccessGrantsPage } from '@/types/accessGrants'; +import { + AccessGrant, + AccessGrantCursor, + AccessGrantsApi, + AccessGrantsPage, + GatewayCredentials, +} from '@/types/accessGrants'; /** * Mock for AccessGrantsApi @@ -25,4 +31,8 @@ export class AccessGrantsMock implements AccessGrantsApi { delete(ids: string[]): Promise { return Promise.resolve(); } + + getGatewayCredentials(accessGrant: string): Promise { + return Promise.resolve(new GatewayCredentials('testCredId', new Date(), 'testAccessKeyId', 'testSecret', 'testEndpoint')); + } }