chore(API): Update the API definitions for RDP (#6758)

This commit is contained in:
Ryan Derr authored and GitHub committed 2026-07-08 16:42:34 +05:30
1 parent b495fe653b
commit 6f03523372
30 files changed
+4189 -268

No files matched your search

+1
View File
@@ -47,6 +47,7 @@ const (
EnvBoundarySRVLookup = "BOUNDARY_SRV_LOOKUP" EnvBoundarySRVLookup = "BOUNDARY_SRV_LOOKUP"
AsciiCastMimeType = "application/x-asciicast" AsciiCastMimeType = "application/x-asciicast"
VideoMimeType = "video/webm"
StreamChunkSize = 1024 * 64 // stream chuck buffer size StreamChunkSize = 1024 * 64 // stream chuck buffer size
) )
+11 -9
View File
@@ -11,13 +11,15 @@ import (
) )
type ChannelRecording struct { type ChannelRecording struct {
Id string `json:"id,omitempty"` Id string `json:"id,omitempty"`
BytesUp uint64 `json:"bytes_up,string,omitempty"` BytesUp uint64 `json:"bytes_up,string,omitempty"`
BytesDown uint64 `json:"bytes_down,string,omitempty"` BytesDown uint64 `json:"bytes_down,string,omitempty"`
CreatedTime time.Time `json:"created_time,omitempty"` CreatedTime time.Time `json:"created_time,omitempty"`
UpdatedTime time.Time `json:"updated_time,omitempty"` UpdatedTime time.Time `json:"updated_time,omitempty"`
StartTime time.Time `json:"start_time,omitempty"` StartTime time.Time `json:"start_time,omitempty"`
EndTime time.Time `json:"end_time,omitempty"` EndTime time.Time `json:"end_time,omitempty"`
Duration api.Duration `json:"duration,omitempty"` Duration api.Duration `json:"duration,omitempty"`
MimeTypes []string `json:"mime_types,omitempty"` MimeTypes []string `json:"mime_types,omitempty"`
RecordingState *RecordingState `json:"recording_state,omitempty"`
Attributes map[string]interface{} `json:"attributes,omitempty"`
} }
@@ -21,4 +21,7 @@ type ConnectionRecording struct {
Duration api.Duration `json:"duration,omitempty"` Duration api.Duration `json:"duration,omitempty"`
MimeTypes []string `json:"mime_types,omitempty"` MimeTypes []string `json:"mime_types,omitempty"`
ChannelRecordings []*ChannelRecording `json:"channel_recordings,omitempty"` ChannelRecordings []*ChannelRecording `json:"channel_recordings,omitempty"`
RecordingState *RecordingState `json:"recording_state,omitempty"`
Exports []*Export `json:"exports,omitempty"`
Videos []*Video `json:"videos,omitempty"`
} }
+371 -4
View File
@@ -6,16 +6,19 @@ package sessionrecordings
import ( import (
"bytes" "bytes"
"context" "context"
"encoding/json"
"errors" "errors"
"fmt" "fmt"
"io" "io"
"net/url" "net/url"
"slices"
"strconv"
"github.com/hashicorp/boundary/api" "github.com/hashicorp/boundary/api"
) )
// Download will of course download the request session recording resource. // Download makes a Boundary request to download the requested session recording
// Currently it always requests a mime-type of asciicast. // or media resource.
func (c *Client) Download(ctx context.Context, contentId string, opt ...Option) (io.ReadCloser, error) { func (c *Client) Download(ctx context.Context, contentId string, opt ...Option) (io.ReadCloser, error) {
switch { switch {
case contentId == "": case contentId == "":
@@ -30,8 +33,13 @@ func (c *Client) Download(ctx context.Context, contentId string, opt ...Option)
if err != nil { if err != nil {
return nil, fmt.Errorf("error creating download request: %w", err) return nil, fmt.Errorf("error creating download request: %w", err)
} }
opts.queryMap["mime_type"] = api.AsciiCastMimeType mimeType, ok := opts.queryMap["mime_type"]
req.Header.Set("Accept", api.AsciiCastMimeType) if !ok {
// Maintain backwards compatibility if mime-type isn't passed in.
opts.queryMap["mime_type"] = api.AsciiCastMimeType
mimeType = api.AsciiCastMimeType
}
req.Header.Set("Accept", mimeType)
if len(opts.queryMap) > 0 { if len(opts.queryMap) > 0 {
q := url.Values{} q := url.Values{}
@@ -99,3 +107,362 @@ func (c *Client) ReApplyStoragePolicy(ctx context.Context, contentId string, opt
target.Response = resp target.Response = resp
return target, nil return target, nil
} }
// Export starts an export against a session recording connection.
func (c *Client) Export(ctx context.Context, connectionRecordingId, mimeType string, opt ...Option) (*ExportCreateResult, error) {
switch {
case connectionRecordingId == "":
return nil, fmt.Errorf("empty connectionRecordingId")
case mimeType == "":
return nil, fmt.Errorf("empty mimeType")
case c.client == nil:
return nil, fmt.Errorf("nil client")
}
opts, apiOpts := getOpts(opt...)
opts.postMap["mime_type"] = mimeType
req, err := c.client.NewRequest(ctx, "POST", "session-recordings/"+url.PathEscape(connectionRecordingId)+":export", opts.postMap, apiOpts...)
if err != nil {
return nil, fmt.Errorf("error creating request: %w", err)
}
if len(opts.queryMap) > 0 {
q := url.Values{}
for k, v := range opts.queryMap {
q.Add(k, v)
}
req.URL.RawQuery = q.Encode()
}
resp, err := c.client.Do(req)
if err != nil {
return nil, fmt.Errorf("error performing client request: %w", err)
}
target := new(ExportCreateResult)
target.Item = new(Export)
apiErr, err := resp.Decode(target.Item)
if err != nil {
return nil, fmt.Errorf("error decoding response: %w", err)
}
if apiErr != nil {
return nil, apiErr
}
target.Response = resp
return target, nil
}
// ReadExport reads an export.
func (c *Client) ReadExport(ctx context.Context, exportId string, opt ...Option) (*ExportReadResult, error) {
switch {
case exportId == "":
return nil, fmt.Errorf("empty exportId")
case c.client == nil:
return nil, fmt.Errorf("nil client")
}
opts, apiOpts := getOpts(opt...)
req, err := c.client.NewRequest(ctx, "GET", "session-recordings/"+url.PathEscape(exportId)+":export", nil, apiOpts...)
if err != nil {
return nil, fmt.Errorf("error creating request: %w", err)
}
if len(opts.queryMap) > 0 {
q := url.Values{}
for k, v := range opts.queryMap {
q.Add(k, v)
}
req.URL.RawQuery = q.Encode()
}
resp, err := c.client.Do(req)
if err != nil {
return nil, fmt.Errorf("error performing client request: %w", err)
}
target := new(ExportReadResult)
target.Item = new(Export)
apiErr, err := resp.Decode(target.Item)
if err != nil {
return nil, fmt.Errorf("error decoding response: %w", err)
}
if apiErr != nil {
return nil, apiErr
}
target.Response = resp
return target, nil
}
// ListExports lists existing session recording exports.
func (c *Client) ListExports(ctx context.Context, scopeId string, opt ...Option) (*ExportListResult, error) {
switch {
case scopeId == "":
return nil, fmt.Errorf("empty scopeId")
case c.client == nil:
return nil, fmt.Errorf("nil client")
}
opts, apiOpts := getOpts(opt...)
opts.queryMap["scope_id"] = scopeId
requestPath := "session-recordings:list-exports"
if opts.withResourcePathOverride != "" {
requestPath = opts.withResourcePathOverride
}
req, err := c.client.NewRequest(ctx, "GET", requestPath, nil, apiOpts...)
if err != nil {
return nil, fmt.Errorf("error creating request: %w", err)
}
if len(opts.queryMap) > 0 {
q := url.Values{}
for k, v := range opts.queryMap {
q.Add(k, v)
}
req.URL.RawQuery = q.Encode()
}
resp, err := c.client.Do(req)
if err != nil {
return nil, fmt.Errorf("error performing client request: %w", err)
}
target := new(ExportListResult)
apiErr, err := resp.Decode(target)
if err != nil {
return nil, fmt.Errorf("error decoding response: %w", err)
}
if apiErr != nil {
return nil, apiErr
}
target.Response = resp
if target.ResponseType == "complete" || target.ResponseType == "" {
return target, nil
}
// In case we shortcut out due to client directed pagination, ensure these
// are set.
target.recursive = opts.withRecursive
target.pageSize = opts.withPageSize
target.scopeId = scopeId
target.allRemovedIds = target.RemovedIds
if opts.withClientDirectedPagination {
return target, nil
}
allItems := make([]*Export, 0, target.EstItemCount)
allItems = append(allItems, target.Items...)
// If there are more results, automatically fetch the rest of the results.
// idToIndex keeps a map from the ID of an item to its index in target.Items.
// This is used to update updated items in-place and remove deleted items
// from the result after pagination is done.
idToIndex := map[string]int{}
for i, item := range allItems {
idToIndex[item.Id] = i
}
// If we're here there are more pages and the client does not want to
// paginate on their own; fetch them as this call returns all values.
currentPage := target
for {
nextPage, err := c.ListExportsNextPage(ctx, currentPage, opt...)
if err != nil {
return nil, fmt.Errorf("error getting next page: %w", err)
}
for _, item := range nextPage.Items {
if i, ok := idToIndex[item.Id]; ok {
// Item has already been seen at index i, update in-place
allItems[i] = item
} else {
allItems = append(allItems, item)
idToIndex[item.Id] = len(allItems) - 1
}
}
currentPage = nextPage
if currentPage.ResponseType == "complete" {
break
}
}
// The current page here is the final page of the results, that is, the
// response type is "complete"
// Remove items that were deleted since the end of the last iteration.
// If a SessionRecording has been updated and subsequently removed, we don't want
// it to appear both in the Items and RemovedIds, so we remove it from the Items.
for _, removedId := range currentPage.RemovedIds {
if i, ok := idToIndex[removedId]; ok {
// Remove the item at index i without preserving order
// https://github.com/golang/go/wiki/SliceTricks#delete-without-preserving-order
allItems[i] = allItems[len(allItems)-1]
allItems = allItems[:len(allItems)-1]
// Update the index of the previously last element
idToIndex[allItems[i].Id] = i
}
}
// Sort the results again since in-place updates and deletes
// may have shuffled items. We sort by created time descending
// (most recently created first), same as the API.
slices.SortFunc(allItems, func(i, j *Export) int {
return j.CreatedTime.Compare(i.CreatedTime)
})
// Since we paginated to the end, we can avoid confusion
// for the user by setting the estimated item count to the
// length of the items slice. If we don't set this here, it
// will equal the value returned in the last response, which is
// often much smaller than the total number returned.
currentPage.EstItemCount = uint(len(allItems))
// Set items to the full list we have collected here
currentPage.Items = allItems
// Set the returned value to the last page with calculated values
target = currentPage
// Finally, since we made at least 2 requests to the server to fulfill this
// function call, resp.Body and resp.Map will only contain the most recent response.
// Overwrite them with the true response.
target.Response.Body.Reset()
if err := json.NewEncoder(target.Response.Body).Encode(target); err != nil {
return nil, fmt.Errorf("error encoding final JSON list response: %w", err)
}
if err := json.Unmarshal(target.Response.Body.Bytes(), &target.Response.Map); err != nil {
return nil, fmt.Errorf("error encoding final map list response: %w", err)
}
// Note: the HTTP response body is consumed by resp.Decode in the loop,
// so it doesn't need to be updated (it will always be, and has always been, empty).
return target, nil
}
// ListExportsNextPage obtains the next page of an export listing process, given
// the current page.
func (c *Client) ListExportsNextPage(ctx context.Context, currentPage *ExportListResult, opt ...Option) (*ExportListResult, error) {
if currentPage == nil {
return nil, fmt.Errorf("empty currentPage")
}
if currentPage.scopeId == "" {
return nil, fmt.Errorf("empty scopeId")
}
if c.client == nil {
return nil, fmt.Errorf("nil client")
}
if currentPage.ResponseType == "complete" || currentPage.ResponseType == "" {
return nil, fmt.Errorf("no more pages available")
}
opts, apiOpts := getOpts(opt...)
opts.queryMap["scope_id"] = currentPage.scopeId
// Don't require them to re-specify recursive
if currentPage.recursive {
opts.queryMap["recursive"] = "true"
}
if currentPage.pageSize != 0 {
opts.queryMap["page_size"] = strconv.FormatUint(uint64(currentPage.pageSize), 10)
}
requestPath := "session-recordings:list-exports"
if opts.withResourcePathOverride != "" {
requestPath = opts.withResourcePathOverride
}
req, err := c.client.NewRequest(ctx, "GET", requestPath, nil, apiOpts...)
if err != nil {
return nil, fmt.Errorf("error creating request: %w", err)
}
opts.queryMap["list_token"] = currentPage.ListToken
if len(opts.queryMap) > 0 {
q := url.Values{}
for k, v := range opts.queryMap {
q.Add(k, v)
}
req.URL.RawQuery = q.Encode()
}
resp, err := c.client.Do(req)
if err != nil {
return nil, fmt.Errorf("error performing client request: %w", err)
}
nextPage := new(ExportListResult)
apiErr, err := resp.Decode(nextPage)
if err != nil {
return nil, fmt.Errorf("error decoding response: %w", err)
}
if apiErr != nil {
return nil, apiErr
}
// Ensure values are carried forward to the next call
nextPage.scopeId = currentPage.scopeId
nextPage.recursive = currentPage.recursive
nextPage.pageSize = currentPage.pageSize
// Cache the removed IDs from this page
nextPage.allRemovedIds = append(currentPage.allRemovedIds, nextPage.RemovedIds...)
// Set the response body to the current response
nextPage.Response = resp
// If we're done iterating, pull the full set of removed IDs into the last
// response
if nextPage.ResponseType == "complete" {
// Collect up the last values
nextPage.RemovedIds = nextPage.allRemovedIds
// For now, removedIds will only be populated if this pagination cycle
// was the result of a "refresh" operation (i.e., the caller provided a
// list token option to this call).
//
// Sort to make response deterministic
slices.Sort(nextPage.RemovedIds)
// Remove any duplicates
nextPage.RemovedIds = slices.Compact(nextPage.RemovedIds)
}
return nextPage, nil
}
// CancelExport cancels an existing export.
func (c *Client) CancelExport(ctx context.Context, exportId string, opt ...Option) (*ExportDeleteResult, error) {
switch {
case exportId == "":
return nil, fmt.Errorf("empty exportId")
case c.client == nil:
return nil, fmt.Errorf("nil client")
}
opts, apiOpts := getOpts(opt...)
req, err := c.client.NewRequest(ctx, "POST", "session-recordings/"+url.PathEscape(exportId)+":export:cancel", nil, apiOpts...)
if err != nil {
return nil, fmt.Errorf("error creating request: %w", err)
}
if len(opts.queryMap) > 0 {
q := url.Values{}
for k, v := range opts.queryMap {
q.Add(k, v)
}
req.URL.RawQuery = q.Encode()
}
resp, err := c.client.Do(req)
if err != nil {
return nil, fmt.Errorf("error performing client request: %w", err)
}
apiErr, err := resp.Decode(nil)
if err != nil {
return nil, fmt.Errorf("error decoding response: %w", err)
}
if apiErr != nil {
return nil, apiErr
}
return &ExportDeleteResult{Response: resp}, nil
}
+95
View File
@@ -0,0 +1,95 @@
// Code generated by "make api"; DO NOT EDIT.
// Copyright IBM Corp. 2020, 2026
// SPDX-License-Identifier: MPL-2.0
package sessionrecordings
import (
"time"
"github.com/hashicorp/boundary/api"
"github.com/hashicorp/boundary/api/scopes"
)
type Export struct {
Id string `json:"id,omitempty"`
Scope *scopes.ScopeInfo `json:"scope,omitempty"`
MimeType string `json:"mime_type,omitempty"`
State string `json:"state,omitempty"`
ProgressPercent uint32 `json:"progress_percent,omitempty"`
WorkerId string `json:"worker_id,omitempty"`
CreatedTime time.Time `json:"created_time,omitempty"`
UpdatedTime time.Time `json:"updated_time,omitempty"`
Version uint32 `json:"version,omitempty"`
ConnectionRecordingId string `json:"connection_recording_id,omitempty"`
Error string `json:"error,omitempty"`
AuthorizedActions []string `json:"authorized_actions,omitempty"`
}
type ExportReadResult struct {
Item *Export
Response *api.Response
}
func (n ExportReadResult) GetItem() *Export {
return n.Item
}
func (n ExportReadResult) GetResponse() *api.Response {
return n.Response
}
type ExportCreateResult = ExportReadResult
type ExportDeleteResult struct {
Response *api.Response
}
// GetItem will always be nil for ExportDeleteResult
func (n ExportDeleteResult) GetItem() any {
return nil
}
func (n ExportDeleteResult) GetResponse() *api.Response {
return n.Response
}
type ExportListResult struct {
Items []*Export `json:"items,omitempty"`
EstItemCount uint `json:"est_item_count,omitempty"`
RemovedIds []string `json:"removed_ids,omitempty"`
ListToken string `json:"list_token,omitempty"`
ResponseType string `json:"response_type,omitempty"`
Response *api.Response
// The following fields are used for cached information when client-directed
// pagination is used.
recursive bool
pageSize uint32
scopeId string
allRemovedIds []string
}
func (n ExportListResult) GetItems() []*Export {
return n.Items
}
func (n ExportListResult) GetEstItemCount() uint {
return n.EstItemCount
}
func (n ExportListResult) GetRemovedIds() []string {
return n.RemovedIds
}
func (n ExportListResult) GetListToken() string {
return n.ListToken
}
func (n ExportListResult) GetResponseType() string {
return n.ResponseType
}
func (n ExportListResult) GetResponse() *api.Response {
return n.Response
}
+11
View File
@@ -30,6 +30,7 @@ type options struct {
withPageSize uint32 withPageSize uint32
withResourcePathOverride string withResourcePathOverride string
withRecursive bool withRecursive bool
withMimeType string
} }
func getDefaultOptions() options { func getDefaultOptions() options {
@@ -62,6 +63,9 @@ func getOpts(opt ...Option) (options, []api.Option) {
if opts.withPageSize != 0 { if opts.withPageSize != 0 {
opts.queryMap["page_size"] = strconv.FormatUint(uint64(opts.withPageSize), 10) opts.queryMap["page_size"] = strconv.FormatUint(uint64(opts.withPageSize), 10)
} }
if opts.withMimeType != "" {
opts.queryMap["mime_type"] = opts.withMimeType
}
return opts, apiOpts return opts, apiOpts
} }
@@ -110,3 +114,10 @@ func WithRecursive(recurse bool) Option {
o.withRecursive = recurse o.withRecursive = recurse
} }
} }
// WithMimeType tells the API to set a specific mime-type on this request.
func WithMimeType(mimeType string) Option {
return func(o *options) {
o.withMimeType = mimeType
}
}
@@ -0,0 +1,41 @@
// Code generated by "make api"; DO NOT EDIT.
// Copyright IBM Corp. 2020, 2026
// SPDX-License-Identifier: MPL-2.0
package sessionrecordings
import (
"fmt"
"github.com/mitchellh/mapstructure"
)
type RdpTargetAttributes struct {
DefaultPort uint32 `json:"default_port,omitempty"`
DefaultClientPort uint32 `json:"default_client_port,omitempty"`
}
func AttributesMapToRdpTargetAttributes(in map[string]any) (*RdpTargetAttributes, error) {
if in == nil {
return nil, fmt.Errorf("nil input map")
}
var out RdpTargetAttributes
dec, err := mapstructure.NewDecoder(&mapstructure.DecoderConfig{
Result: &out,
TagName: "json",
})
if err != nil {
return nil, fmt.Errorf("error creating mapstructure decoder: %w", err)
}
if err := dec.Decode(in); err != nil {
return nil, fmt.Errorf("error decoding: %w", err)
}
return &out, nil
}
func (pt *Target) GetRdpTargetAttributes() (*RdpTargetAttributes, error) {
if pt.Type != "rdp" {
return nil, fmt.Errorf("asked to fetch %s-type attributes but target is of type %s", "rdp", pt.Type)
}
return AttributesMapToRdpTargetAttributes(pt.Attributes)
}
@@ -0,0 +1,11 @@
// Code generated by "make api"; DO NOT EDIT.
// Copyright IBM Corp. 2020, 2026
// SPDX-License-Identifier: MPL-2.0
package sessionrecordings
type RecordingState struct {
StorageState string `json:"storage_state,omitempty"`
SyncingErrorDetails string `json:"syncing_error_details,omitempty"`
VerificationErrorDetails string `json:"verification_error_details,omitempty"`
}
@@ -39,6 +39,8 @@ type SessionRecording struct {
AuthorizedActions []string `json:"authorized_actions,omitempty"` AuthorizedActions []string `json:"authorized_actions,omitempty"`
RetainUntil time.Time `json:"retain_until,omitempty"` RetainUntil time.Time `json:"retain_until,omitempty"`
DeleteAfter time.Time `json:"delete_after,omitempty"` DeleteAfter time.Time `json:"delete_after,omitempty"`
Availability string `json:"availability,omitempty"`
RecordingState *RecordingState `json:"recording_state,omitempty"`
} }
type SessionRecordingReadResult struct { type SessionRecordingReadResult struct {
@@ -0,0 +1,42 @@
// Code generated by "make api"; DO NOT EDIT.
// Copyright IBM Corp. 2020, 2026
// SPDX-License-Identifier: MPL-2.0
package sessionrecordings
import (
"fmt"
"github.com/mitchellh/mapstructure"
)
type UsernamePasswordDomainCredentialAttributes struct {
Username string `json:"username,omitempty"`
PasswordHmac string `json:"password_hmac,omitempty"`
Domain string `json:"domain,omitempty"`
}
func AttributesMapToUsernamePasswordDomainCredentialAttributes(in map[string]any) (*UsernamePasswordDomainCredentialAttributes, error) {
if in == nil {
return nil, fmt.Errorf("nil input map")
}
var out UsernamePasswordDomainCredentialAttributes
dec, err := mapstructure.NewDecoder(&mapstructure.DecoderConfig{
Result: &out,
TagName: "json",
})
if err != nil {
return nil, fmt.Errorf("error creating mapstructure decoder: %w", err)
}
if err := dec.Decode(in); err != nil {
return nil, fmt.Errorf("error decoding: %w", err)
}
return &out, nil
}
func (pt *Credential) GetUsernamePasswordDomainCredentialAttributes() (*UsernamePasswordDomainCredentialAttributes, error) {
if pt.Type != "username_password_domain" {
return nil, fmt.Errorf("asked to fetch %s-type attributes but credential is of type %s", "username_password_domain", pt.Type)
}
return AttributesMapToUsernamePasswordDomainCredentialAttributes(pt.Attributes)
}
@@ -0,0 +1,40 @@
// Code generated by "make api"; DO NOT EDIT.
// Copyright IBM Corp. 2020, 2026
// SPDX-License-Identifier: MPL-2.0
package sessionrecordings
import (
"fmt"
"github.com/mitchellh/mapstructure"
)
type VaultLdapCredentialLibraryAttributes struct {
Path string `json:"path,omitempty"`
}
func AttributesMapToVaultLdapCredentialLibraryAttributes(in map[string]any) (*VaultLdapCredentialLibraryAttributes, error) {
if in == nil {
return nil, fmt.Errorf("nil input map")
}
var out VaultLdapCredentialLibraryAttributes
dec, err := mapstructure.NewDecoder(&mapstructure.DecoderConfig{
Result: &out,
TagName: "json",
})
if err != nil {
return nil, fmt.Errorf("error creating mapstructure decoder: %w", err)
}
if err := dec.Decode(in); err != nil {
return nil, fmt.Errorf("error decoding: %w", err)
}
return &out, nil
}
func (pt *CredentialLibrary) GetVaultLdapCredentialLibraryAttributes() (*VaultLdapCredentialLibraryAttributes, error) {
if pt.Type != "vault-ldap" {
return nil, fmt.Errorf("asked to fetch %s-type attributes but credential-library is of type %s", "vault-ldap", pt.Type)
}
return AttributesMapToVaultLdapCredentialLibraryAttributes(pt.Attributes)
}
+16
View File
@@ -0,0 +1,16 @@
// Code generated by "make api"; DO NOT EDIT.
// Copyright IBM Corp. 2020, 2026
// SPDX-License-Identifier: MPL-2.0
package sessionrecordings
import (
"time"
)
type Video struct {
Id string `json:"id,omitempty"`
CreatedTime time.Time `json:"created_time,omitempty"`
LengthSeconds uint64 `json:"length_seconds,string,omitempty"`
SizeBytes uint64 `json:"size_bytes,string,omitempty"`
}
+60
View File
@@ -341,6 +341,30 @@ func DefaultEgressWorkerFilter() Option {
} }
} }
func WithRdpTargetEnableSessionRecording(inEnableSessionRecording bool) Option {
return func(o *options) {
raw, ok := o.postMap["attributes"]
if !ok {
raw = any(map[string]any{})
}
val := raw.(map[string]any)
val["enable_session_recording"] = inEnableSessionRecording
o.postMap["attributes"] = val
}
}
func DefaultRdpTargetEnableSessionRecording() Option {
return func(o *options) {
raw, ok := o.postMap["attributes"]
if !ok {
raw = any(map[string]any{})
}
val := raw.(map[string]any)
val["enable_session_recording"] = nil
o.postMap["attributes"] = val
}
}
func WithSshTargetEnableSessionRecording(inEnableSessionRecording bool) Option { func WithSshTargetEnableSessionRecording(inEnableSessionRecording bool) Option {
return func(o *options) { return func(o *options) {
raw, ok := o.postMap["attributes"] raw, ok := o.postMap["attributes"]
@@ -353,6 +377,18 @@ func WithSshTargetEnableSessionRecording(inEnableSessionRecording bool) Option {
} }
} }
func DefaultSshTargetEnableSessionRecording() Option {
return func(o *options) {
raw, ok := o.postMap["attributes"]
if !ok {
raw = any(map[string]any{})
}
val := raw.(map[string]any)
val["enable_session_recording"] = nil
o.postMap["attributes"] = val
}
}
func WithHostId(inHostId string) Option { func WithHostId(inHostId string) Option {
return func(o *options) { return func(o *options) {
o.postMap["host_id"] = inHostId o.postMap["host_id"] = inHostId
@@ -431,6 +467,30 @@ func DefaultSessionMaxSeconds() Option {
} }
} }
func WithRdpTargetStorageBucketId(inStorageBucketId string) Option {
return func(o *options) {
raw, ok := o.postMap["attributes"]
if !ok {
raw = any(map[string]any{})
}
val := raw.(map[string]any)
val["storage_bucket_id"] = inStorageBucketId
o.postMap["attributes"] = val
}
}
func DefaultRdpTargetStorageBucketId() Option {
return func(o *options) {
raw, ok := o.postMap["attributes"]
if !ok {
raw = any(map[string]any{})
}
val := raw.(map[string]any)
val["storage_bucket_id"] = nil
o.postMap["attributes"] = val
}
}
func WithSshTargetStorageBucketId(inStorageBucketId string) Option { func WithSshTargetStorageBucketId(inStorageBucketId string) Option {
return func(o *options) { return func(o *options) {
raw, ok := o.postMap["attributes"] raw, ok := o.postMap["attributes"]
+4 -2
View File
@@ -11,8 +11,10 @@ import (
) )
type RdpTargetAttributes struct { type RdpTargetAttributes struct {
DefaultPort uint32 `json:"default_port,omitempty"` DefaultPort uint32 `json:"default_port,omitempty"`
DefaultClientPort uint32 `json:"default_client_port,omitempty"` DefaultClientPort uint32 `json:"default_client_port,omitempty"`
StorageBucketId string `json:"storage_bucket_id,omitempty"`
EnableSessionRecording bool `json:"enable_session_recording,omitempty"`
} }
func AttributesMapToRdpTargetAttributes(in map[string]any) (*RdpTargetAttributes, error) { func AttributesMapToRdpTargetAttributes(in map[string]any) (*RdpTargetAttributes, error) {
+53
View File
@@ -107,6 +107,10 @@ type structInfo struct {
// fields. // fields.
versionEnabled bool versionEnabled bool
// mimeTypeEnabled indicates that we should build a WithMimeType API option
// for this resource.
mimeTypeEnabled bool
// This is used for building the api path. // This is used for building the api path.
pluralResourceName string pluralResourceName string
@@ -1273,6 +1277,15 @@ var inputStructs = []*structInfo{
mapstructureConversionTemplate, mapstructureConversionTemplate,
}, },
}, },
{
inProto: &session_recordings.RdpTargetAttributes{},
outFile: "sessionrecordings/rdp_target_attributes.gen.go",
subtypeName: "Rdp",
parentTypeName: "Target",
templates: []*template.Template{
mapstructureConversionTemplate,
},
},
{ {
inProto: &session_recordings.Host{}, inProto: &session_recordings.Host{},
outFile: "sessionrecordings/host.gen.go", outFile: "sessionrecordings/host.gen.go",
@@ -1312,6 +1325,15 @@ var inputStructs = []*structInfo{
mapstructureConversionTemplate, mapstructureConversionTemplate,
}, },
}, },
{
inProto: &session_recordings.UsernamePasswordDomainCredentialAttributes{},
outFile: "sessionrecordings/username_password_domain_credential_attributes.gen.go",
subtype: "username_password_domain",
parentTypeName: "Credential",
templates: []*template.Template{
mapstructureConversionTemplate,
},
},
{ {
inProto: &session_recordings.JsonCredentialAttributes{}, inProto: &session_recordings.JsonCredentialAttributes{},
outFile: "sessionrecordings/json_credential_attributes.gen.go", outFile: "sessionrecordings/json_credential_attributes.gen.go",
@@ -1362,6 +1384,15 @@ var inputStructs = []*structInfo{
mapstructureConversionTemplate, mapstructureConversionTemplate,
}, },
}, },
{
inProto: &session_recordings.VaultLdapCredentialLibraryAttributes{},
outFile: "sessionrecordings/vault_ldap_credential_library_attributes.gen.go",
subtype: "vault-ldap",
parentTypeName: "CredentialLibrary",
templates: []*template.Template{
mapstructureConversionTemplate,
},
},
{ {
inProto: &session_recordings.CredentialStore{}, inProto: &session_recordings.CredentialStore{},
outFile: "sessionrecordings/credential_store.gen.go", outFile: "sessionrecordings/credential_store.gen.go",
@@ -1379,6 +1410,10 @@ var inputStructs = []*structInfo{
inProto: &session_recordings.ValuesAtTime{}, inProto: &session_recordings.ValuesAtTime{},
outFile: "sessionrecordings/values_at_time.gen.go", outFile: "sessionrecordings/values_at_time.gen.go",
}, },
{
inProto: &session_recordings.RecordingState{},
outFile: "sessionrecordings/recording_state.gen.go",
},
{ {
inProto: &session_recordings.ConnectionRecording{}, inProto: &session_recordings.ConnectionRecording{},
outFile: "sessionrecordings/connection_recording.gen.go", outFile: "sessionrecordings/connection_recording.gen.go",
@@ -1401,6 +1436,23 @@ var inputStructs = []*structInfo{
{Name: "BytesDown", JsonTags: []string{"string"}}, {Name: "BytesDown", JsonTags: []string{"string"}},
}, },
}, },
{
inProto: &session_recordings.Export{},
outFile: "sessionrecordings/export.gen.go",
pluralResourceName: "exports",
createResponseTypes: []string{CreateResponseType, ReadResponseType, ListResponseType, DeleteResponseType}, // DeleteResponseType is used for cancel.
},
{
inProto: &session_recordings.Video{},
outFile: "sessionrecordings/video.gen.go",
fieldOverrides: []fieldInfo{
// int64 fields get marshalled by protobuf as strings, so we have
// to tell the json parser that their json representation is a
// string but they go into Go int64 types.
{Name: "LengthSeconds", JsonTags: []string{"string"}},
{Name: "SizeBytes", JsonTags: []string{"string"}},
},
},
{ {
// this must be the last block of session recording blocks, otherwise // this must be the last block of session recording blocks, otherwise
// the bits beyond inProto and outFile will get overwritten by // the bits beyond inProto and outFile will get overwritten by
@@ -1418,6 +1470,7 @@ var inputStructs = []*structInfo{
recursiveListing: true, recursiveListing: true,
skipListFiltering: true, skipListFiltering: true,
versionEnabled: false, versionEnabled: false,
mimeTypeEnabled: true,
fieldOverrides: []fieldInfo{ fieldOverrides: []fieldInfo{
// int64 fields get marshalled by protobuf as strings, so we have // int64 fields get marshalled by protobuf as strings, so we have
// to tell the json parser that their json representation is a // to tell the json parser that their json representation is a
+16 -1
View File
@@ -49,6 +49,7 @@ type templateInput struct {
SliceSubtypes map[string]sliceSubtypeInfo SliceSubtypes map[string]sliceSubtypeInfo
ExtraFields []fieldInfo ExtraFields []fieldInfo
VersionEnabled bool VersionEnabled bool
MimeTypeEnabled bool
NonPaginatedListing bool NonPaginatedListing bool
CreateResponseTypes []string CreateResponseTypes []string
SkipListFiltering bool SkipListFiltering bool
@@ -70,6 +71,7 @@ func fillTemplates() {
ParentTypeName: in.parentTypeName, ParentTypeName: in.parentTypeName,
ExtraFields: in.extraFields, ExtraFields: in.extraFields,
VersionEnabled: in.versionEnabled, VersionEnabled: in.versionEnabled,
MimeTypeEnabled: in.mimeTypeEnabled,
NonPaginatedListing: in.nonPaginatedListing, NonPaginatedListing: in.nonPaginatedListing,
CreateResponseTypes: in.createResponseTypes, CreateResponseTypes: in.createResponseTypes,
SkipListFiltering: in.skipListFiltering, SkipListFiltering: in.skipListFiltering,
@@ -204,6 +206,7 @@ func fillTemplates() {
SkipListFiltering: inputMap[pkg].skipListFiltering, SkipListFiltering: inputMap[pkg].skipListFiltering,
RecursiveListing: inputMap[pkg].recursiveListing, RecursiveListing: inputMap[pkg].recursiveListing,
VersionEnabled: inputMap[pkg].versionEnabled, VersionEnabled: inputMap[pkg].versionEnabled,
MimeTypeEnabled: inputMap[pkg].mimeTypeEnabled,
} }
if err := optionTemplate.Execute(outBuf, input); err != nil { if err := optionTemplate.Execute(outBuf, input); err != nil {
@@ -955,6 +958,7 @@ type options struct {
withPageSize uint32 withPageSize uint32
withResourcePathOverride string withResourcePathOverride string
{{ if .RecursiveListing }} withRecursive bool {{ end }} {{ if .RecursiveListing }} withRecursive bool {{ end }}
{{ if .MimeTypeEnabled }} withMimeType string {{ end }}
} }
func getDefaultOptions() options { func getDefaultOptions() options {
@@ -986,7 +990,10 @@ func getOpts(opt ...Option) (options, []api.Option) {
} {{ end }} } {{ end }}
if opts.withPageSize != 0 { if opts.withPageSize != 0 {
opts.queryMap["page_size"] = strconv.FormatUint(uint64(opts.withPageSize), 10) opts.queryMap["page_size"] = strconv.FormatUint(uint64(opts.withPageSize), 10)
} }{{ if .MimeTypeEnabled }}
if opts.withMimeType != "" {
opts.queryMap["mime_type"] = opts.withMimeType
} {{ end }}
return opts, apiOpts return opts, apiOpts
} }
@@ -1058,6 +1065,14 @@ func WithRecursive(recurse bool) Option {
} }
} }
{{ end }} {{ end }}
{{ if .MimeTypeEnabled }}
// WithMimeType tells the API to set a specific mime-type on this request.
func WithMimeType(mimeType string) Option {
return func(o *options) {
o.withMimeType = mimeType
}
}
{{ end }}
{{ range $fieldIndex, $field := .Fields }} {{ range $fieldIndex, $field := .Fields }}
{{ $subtypes := (removeDups $field.SubtypeNames ) }} {{ $subtypes := (removeDups $field.SubtypeNames ) }}
{{ if ( eq ( len ( $subtypes ) ) 0 )}} {{ if ( eq ( len ( $subtypes ) ) 0 )}}
+24
View File
@@ -1296,6 +1296,30 @@ func initCommands(ui, serverCmdUi cli.Ui, runOpts *RunOptions) {
Func: "delete", Func: "delete",
} }
}), }),
"session-recordings list-exports": wrapper.Wrap(func() wrapper.WrappableCommand {
return &sessionrecordingscmd.ExportCommand{
Command: base.NewCommand(ui, opts...),
Action: sessionrecordingscmd.ExportCommandActionList,
}
}),
"session-recordings export": wrapper.Wrap(func() wrapper.WrappableCommand {
return &sessionrecordingscmd.ExportCommand{
Command: base.NewCommand(ui, opts...),
Action: sessionrecordingscmd.ExportCommandActionCreate,
}
}),
"session-recordings export read": wrapper.Wrap(func() wrapper.WrappableCommand {
return &sessionrecordingscmd.ExportCommand{
Command: base.NewCommand(ui, opts...),
Action: sessionrecordingscmd.ExportCommandActionRead,
}
}),
"session-recordings export cancel": wrapper.Wrap(func() wrapper.WrappableCommand {
return &sessionrecordingscmd.ExportCommand{
Command: base.NewCommand(ui, opts...),
Action: sessionrecordingscmd.ExportCommandActionCancel,
}
}),
"session-recordings reapply-storage-policy": wrapper.Wrap(func() wrapper.WrappableCommand { "session-recordings reapply-storage-policy": wrapper.Wrap(func() wrapper.WrappableCommand {
return &sessionrecordingscmd.ReApplyStoragePolicyCommand{ return &sessionrecordingscmd.ReApplyStoragePolicyCommand{
Command: base.NewCommand(ui, opts...), Command: base.NewCommand(ui, opts...),
@@ -24,11 +24,13 @@ var (
) )
const ( const (
castExt = ".cast" // default download file extension (is overridden when an output file is specified) castExt = ".cast" // default download file extension for Asciicast files (overridden when an output file is specified)
webmExt = ".webm" // default download file extension for Webm files (overridden when an output file is specified)
) )
type DownloadCommand struct { type DownloadCommand struct {
*base.Command *base.Command
flagMimeType string
} }
func (c *DownloadCommand) Synopsis() string { func (c *DownloadCommand) Synopsis() string {
@@ -59,7 +61,7 @@ func (c *DownloadCommand) Flags() *base.FlagSets {
f.StringVar(&base.StringVar{ f.StringVar(&base.StringVar{
Name: "output", Name: "output",
Target: &c.FlagOutputFile, Target: &c.FlagOutputFile,
Usage: "An optional output file for the download. If not provided the recording id will be used with a \".cast\" extension. Use \"-\" for stdout.", Usage: "An optional output file for the download. If not provided the recording id will be used with a \".cast\" or \".webm\" extension. Use \"-\" for stdout.",
Aliases: []string{"o"}, Aliases: []string{"o"},
}) })
f.BoolVar(&base.BoolVar{ f.BoolVar(&base.BoolVar{
@@ -68,6 +70,13 @@ func (c *DownloadCommand) Flags() *base.FlagSets {
Usage: "An option to stop downloads that would overwrite existing files.", Usage: "An option to stop downloads that would overwrite existing files.",
Aliases: []string{"nc"}, Aliases: []string{"nc"},
}) })
f.StringVar(&base.StringVar{
Name: "mime-type",
Target: &c.flagMimeType,
Usage: "The mime-type for the requested content.",
Default: api.AsciiCastMimeType,
Aliases: []string{"mt"},
})
return set return set
} }
@@ -91,6 +100,16 @@ func (c *DownloadCommand) Run(args []string) int {
case c.FlagId == "": case c.FlagId == "":
c.PrintCliError(errors.New("ID must be provided via -id")) c.PrintCliError(errors.New("ID must be provided via -id"))
return base.CommandUserError return base.CommandUserError
case c.flagMimeType == "":
c.flagMimeType = api.AsciiCastMimeType // Allow for backwards compatibility.
}
switch c.flagMimeType {
case api.AsciiCastMimeType:
case api.VideoMimeType:
default:
c.PrintCliError(fmt.Errorf("Unknown mime-type %q", c.flagMimeType))
return base.CommandUserError
} }
client, err := c.Client() client, err := c.Client()
@@ -107,7 +126,7 @@ func (c *DownloadCommand) Run(args []string) int {
} }
sClient := sessionrecordings.NewClient(client) sClient := sessionrecordings.NewClient(client)
result, err := sClient.Download(c.Context, c.FlagId) result, err := sClient.Download(c.Context, c.FlagId, sessionrecordings.WithMimeType(c.flagMimeType))
if err != nil { if err != nil {
if apiErr := api.AsServerError(err); apiErr != nil { if apiErr := api.AsServerError(err); apiErr != nil {
c.PrintApiError(apiErr, "Error from controller when downloading session recording") c.PrintApiError(apiErr, "Error from controller when downloading session recording")
@@ -146,7 +165,7 @@ func (c *DownloadCommand) Run(args []string) int {
} }
defer outFile.Close() defer outFile.Close()
default: default:
fileName := getNextFileName(c.FlagId) fileName := getNextFileName(c.FlagId, c.flagMimeType)
outFile, err = os.Create(fileName) outFile, err = os.Create(fileName)
if err != nil { if err != nil {
c.PrintCliError(fmt.Errorf("Unable to create download file %q: %w", fileName, err)) c.PrintCliError(fmt.Errorf("Unable to create download file %q: %w", fileName, err))
@@ -162,13 +181,23 @@ func (c *DownloadCommand) Run(args []string) int {
return base.CommandSuccess return base.CommandSuccess
} }
func getNextFileName(baseName string) string { func getNextFileName(baseName, mimeType string) string {
if _, err := os.Stat(baseName + castExt); os.IsNotExist(err) { var ext string
return baseName + castExt switch mimeType {
case api.AsciiCastMimeType:
ext = castExt
case api.VideoMimeType:
ext = webmExt
default:
ext = castExt // Allow for backwards compatibility
}
if _, err := os.Stat(baseName + ext); os.IsNotExist(err) {
return baseName + ext
} }
startIndex := 1 startIndex := 1
for { for {
fileName := baseName + castExt + "." + strconv.Itoa(startIndex) fileName := baseName + ext + "." + strconv.Itoa(startIndex)
if _, err := os.Stat(fileName); os.IsNotExist(err) { if _, err := os.Stat(fileName); os.IsNotExist(err) {
return fileName return fileName
} }
@@ -0,0 +1,453 @@
// Copyright IBM Corp. 2024, 2026
// SPDX-License-Identifier: BUSL-1.1
package sessionrecordingscmd
import (
"errors"
"fmt"
"time"
"github.com/hashicorp/boundary/api"
"github.com/hashicorp/boundary/api/sessionrecordings"
"github.com/hashicorp/boundary/internal/cmd/base"
"github.com/mitchellh/go-wordwrap"
"github.com/posener/complete"
)
// ExportCommandAction defines actions supported by a session recording export
// resource.
type ExportCommandAction string
const (
// ExportCommandActionCreate defines the export creation action.
ExportCommandActionCreate ExportCommandAction = "create"
// ExportCommandActionRead defines the export read action.
ExportCommandActionRead ExportCommandAction = "read"
// ExportCommandActionList defines the export listing action.
ExportCommandActionList ExportCommandAction = "list"
// ExportCommandActionCancel defines the export cancel action.
ExportCommandActionCancel ExportCommandAction = "cancel"
)
// ExportCommand defines a session recording export command. This command
// exposes all actions that are available for session recording exports.
// Note: Custom code has to be used as this sub-resource does not fit well with
// the existing cli autogen logic.
type ExportCommand struct {
*base.Command
Action ExportCommandAction
flagMimeType string
}
func (c *ExportCommand) Synopsis() string {
switch c.Action {
case ExportCommandActionCreate:
// Create refers to starting, reading or cancelling because the "export"
// sub-command is both used to start an export and also as an
// entry-point for the "export read" and "export cancel" sub-commands.
return wordwrap.WrapString("Start, read or cancel a session recording export", base.TermWidth)
case ExportCommandActionRead:
return wordwrap.WrapString("Read a session recording export", base.TermWidth)
case ExportCommandActionCancel:
return wordwrap.WrapString("Cancel a session recording export", base.TermWidth)
case ExportCommandActionList:
return wordwrap.WrapString("List session recording exports", base.TermWidth)
default:
return wordwrap.WrapString("Perform actions on session recording export resources", base.TermWidth)
}
}
func (c *ExportCommand) Help() string {
var out []string
switch c.Action {
case ExportCommandActionCreate:
out = append(out,
"Usage: boundary session-recordings export [action] [args]",
"",
" Create a new export. Example:",
"",
` $ boundary session-recordings export -id cr_1234567890 -mime-type video/webm`,
"",
" Also used as an entrypoint to read or cancel an existing export.",
"",
" Please see subcommand help for detailed usage information.",
)
case ExportCommandActionRead:
out = append(out,
"Usage: boundary session-recordings export read [args]",
"",
" Read an existing export. Example:",
"",
` $ boundary session-recordings export read -id exp_1234567890`,
)
case ExportCommandActionCancel:
out = append(out,
"Usage: boundary session-recordings export cancel [args]",
"",
" Cancel an existing export. Example:",
"",
` $ boundary session-recordings export cancel -id exp_1234567890`,
)
case ExportCommandActionList:
out = append(out,
"Usage: boundary session-recordings list-exports [args]",
"",
" List exports within an enclosing scope or resource. Example:",
"",
` $ boundary session-recordings list-exports -scope-id global -recursive true`,
)
}
out = append(out, "", "")
return base.WrapForHelpText(out) + c.Flags().Help()
}
func (c *ExportCommand) Flags() *base.FlagSets {
set := c.FlagSet(base.FlagSetHTTP | base.FlagSetClient | base.FlagSetOutputFormat)
fs := set.NewFlagSet("Command Options")
switch c.Action {
case ExportCommandActionCreate:
fs.StringVar(&base.StringVar{
Name: "connection-recording-id",
Target: &c.FlagId,
Usage: "The id of the connection recording to export",
Aliases: []string{"cr-id"},
})
fs.StringVar(&base.StringVar{
Name: "mime-type",
Target: &c.flagMimeType,
Usage: "The export's requested mime-type. Must be a valid Boundary API mime-type",
Aliases: []string{"mt"},
})
case ExportCommandActionRead, ExportCommandActionCancel:
fs.StringVar(&base.StringVar{
Name: "id",
Target: &c.FlagId,
Usage: "The export's id",
})
case ExportCommandActionList:
fs.StringVar(&base.StringVar{
Name: "scope-id",
Target: &c.FlagScopeId,
Usage: "The scope in which to make the request.",
EnvVar: "BOUNDARY_SCOPE_ID",
Default: "global",
})
fs.BoolVar(&base.BoolVar{
Name: "recursive",
Target: &c.FlagRecursive,
Usage: "If set, the list operation will be applied recursively into child scopes, if supported by the type.",
Default: false,
})
}
return set
}
func (c *ExportCommand) AutocompleteArgs() complete.Predictor {
return complete.PredictAnything
}
func (c *ExportCommand) AutocompleteFlags() complete.Flags {
return c.Flags().Completions()
}
func (c *ExportCommand) Run(args []string) int {
fs := c.Flags()
err := fs.Parse(args)
if err != nil {
c.PrintCliError(err)
return base.CommandUserError
}
client, err := c.Client()
if c.WrapperCleanupFunc != nil {
defer func() {
if err := c.WrapperCleanupFunc(); err != nil {
c.PrintCliError(fmt.Errorf("Error cleaning kms wrapper: %w", err))
}
}()
}
if err != nil {
c.PrintCliError(fmt.Errorf("Error creating API client: %w", err))
return base.CommandCliError
}
srCl := sessionrecordings.NewClient(client)
switch c.Action {
case ExportCommandActionCreate:
return c.create(srCl)
case ExportCommandActionRead:
return c.read(srCl)
case ExportCommandActionList:
return c.list(srCl)
case ExportCommandActionCancel:
return c.cancel(srCl)
}
return base.CommandSuccess
}
func (c *ExportCommand) create(cl *sessionrecordings.Client) int {
switch {
case c.FlagId == "":
c.PrintCliError(errors.New("Missing connection recording id. Must be provided via -connection-recording-id"))
return base.CommandUserError
case c.flagMimeType == "":
c.PrintCliError(fmt.Errorf("Missing mime-type. Must be provided via -mime-type"))
return base.CommandUserError
}
result, err := cl.Export(c.Context, c.FlagId, c.flagMimeType)
if err != nil {
if apiErr := api.AsServerError(err); apiErr != nil {
c.PrintApiError(apiErr, "Error from controller when starting a session connection recording export")
return base.CommandApiError
}
c.PrintCliError(fmt.Errorf("Session connection recording export error: %w", err))
return base.CommandCliError
}
switch base.Format(c.UI) {
case "table":
c.UI.Output(c.printItemTable(result.GetItem(), result.GetResponse()))
case "json":
if ok := c.PrintJsonItem(result.GetResponse()); !ok {
return base.CommandCliError
}
}
return base.CommandSuccess
}
func (c *ExportCommand) read(cl *sessionrecordings.Client) int {
switch { //nolint:staticcheck // QF1002. For consistency with how we check function inputs.
case c.FlagId == "":
c.PrintCliError(fmt.Errorf("Missing export id. Must be provided via -id"))
return base.CommandUserError
}
result, err := cl.ReadExport(c.Context, c.FlagId)
if err != nil {
if apiErr := api.AsServerError(err); apiErr != nil {
c.PrintApiError(apiErr, "Error from controller when reading a session connection recording export")
return base.CommandApiError
}
c.PrintCliError(fmt.Errorf("Session connection recording export read error: %w", err))
return base.CommandCliError
}
switch base.Format(c.UI) {
case "table":
c.UI.Output(c.printItemTable(result.GetItem(), result.GetResponse()))
case "json":
if ok := c.PrintJsonItem(result.GetResponse()); !ok {
return base.CommandCliError
}
}
return base.CommandSuccess
}
func (c *ExportCommand) cancel(cl *sessionrecordings.Client) int {
switch { //nolint:staticcheck // QF1002. For consistency with how we check function inputs.
case c.FlagId == "":
c.PrintCliError(fmt.Errorf("Missing export id. Must be provided via -id"))
return base.CommandUserError
}
result, err := cl.CancelExport(c.Context, c.FlagId)
if err != nil {
if apiErr := api.AsServerError(err); apiErr != nil {
c.PrintApiError(apiErr, "Error from controller when cancelling a session connection recording export")
return base.CommandApiError
}
c.PrintCliError(fmt.Errorf("Session connection recording export cancel error: %w", err))
return base.CommandCliError
}
switch base.Format(c.UI) {
case "table":
c.UI.Output("The cancel operation completed successfully.")
case "json":
if ok := c.PrintJsonItem(result.GetResponse()); !ok {
return base.CommandCliError
}
}
return base.CommandSuccess
}
func (c *ExportCommand) list(cl *sessionrecordings.Client) int {
switch { //nolint:staticcheck // QF1002. For consistency with how we check function inputs.
case c.FlagScopeId == "":
c.PrintCliError(fmt.Errorf("Missing scope id. Must be provided via -scope-id"))
return base.CommandUserError
}
opts := make([]sessionrecordings.Option, 0, 1)
if c.FlagRecursive {
opts = append(opts, sessionrecordings.WithRecursive(true))
}
result, err := cl.ListExports(c.Context, c.FlagScopeId, opts...)
if err != nil {
if apiErr := api.AsServerError(err); apiErr != nil {
c.PrintApiError(apiErr, "Error from controller when listing session connection recording exports")
return base.CommandApiError
}
c.PrintCliError(fmt.Errorf("Session connection recording export listing error: %w", err))
return base.CommandCliError
}
switch base.Format(c.UI) {
case "table":
c.UI.Output(c.printListTable(result.GetItems()))
case "json":
if ok := c.PrintJsonItems(result.GetResponse()); !ok {
return base.CommandCliError
}
}
return base.CommandSuccess
}
func (c *ExportCommand) printItemTable(item *sessionrecordings.Export, resp *api.Response) string {
nonAttributeMap := map[string]any{}
if item.Id != "" {
nonAttributeMap["ID"] = item.Id
}
if item.Scope.Id != "" {
nonAttributeMap["Scope ID"] = item.Scope.Id
}
if item.ConnectionRecordingId != "" {
nonAttributeMap["Connection Recording ID"] = item.ConnectionRecordingId
}
if item.MimeType != "" {
nonAttributeMap["Mime Type"] = item.MimeType
}
if item.State != "" {
nonAttributeMap["State"] = item.State
}
if item.ProgressPercent > 0 {
nonAttributeMap["Progress (%)"] = item.ProgressPercent
}
if item.WorkerId != "" {
nonAttributeMap["Worker ID"] = item.WorkerId
}
if item.Error != "" {
nonAttributeMap["Error"] = item.Error
}
if !item.CreatedTime.IsZero() {
nonAttributeMap["Created Time"] = item.CreatedTime.Local().Format(time.RFC1123)
}
if !item.UpdatedTime.IsZero() {
nonAttributeMap["Updated Time"] = item.UpdatedTime.Local().Format(time.RFC1123)
}
maxLength := base.MaxAttributesLength(nonAttributeMap, nil, nil)
ret := []string{
"",
"Export information:",
base.WrapMap(2, maxLength+2, nonAttributeMap),
}
if item.Scope != nil {
ret = append(ret,
"",
" Scope:",
base.ScopeInfoForOutput(item.Scope, maxLength),
)
}
if len(item.AuthorizedActions) > 0 {
ret = append(ret,
"",
" Authorized Actions:",
base.WrapSlice(4, item.AuthorizedActions),
)
}
return base.WrapForHelpText(ret)
}
func (c *ExportCommand) printListTable(items []*sessionrecordings.Export) string {
if len(items) == 0 {
return "No exports found"
}
output := []string{
"",
"Export information:",
}
for i, item := range items {
if i > 0 {
output = append(output, "")
}
if item.Id != "" {
output = append(output,
fmt.Sprintf(" ID: %s", item.Id),
)
} else {
output = append(output,
fmt.Sprintf(" ID: %s", "(not available)"),
)
}
if item.ConnectionRecordingId != "" {
output = append(output,
fmt.Sprintf(" Connection Recording ID: %s", item.ConnectionRecordingId),
)
}
if c.FlagRecursive && item.Scope.Id != "" {
output = append(output,
fmt.Sprintf(" Scope ID: %s", item.Scope.Id),
)
}
if !item.CreatedTime.IsZero() {
output = append(output,
fmt.Sprintf(" Created Time: %s", item.CreatedTime.Local().Format(time.RFC1123)),
)
}
if !item.UpdatedTime.IsZero() {
output = append(output,
fmt.Sprintf(" Updated Time: %s", item.UpdatedTime.Local().Format(time.RFC1123)),
)
}
if item.MimeType != "" {
output = append(output,
fmt.Sprintf(" Mime Type: %s", item.MimeType),
)
}
if item.State != "" {
output = append(output,
fmt.Sprintf(" State: %s", item.State),
)
}
if item.ProgressPercent > 0 {
output = append(output,
fmt.Sprintf(" Progress (%%): %d", item.ProgressPercent),
)
}
if item.WorkerId != "" {
output = append(output,
fmt.Sprintf(" Worker ID: %s", item.WorkerId),
)
}
if item.Error != "" {
output = append(output,
fmt.Sprintf(" Error: %s", item.Error),
)
}
if len(item.AuthorizedActions) > 0 {
output = append(output,
" Authorized Actions:",
base.WrapSlice(6, item.AuthorizedActions),
)
}
}
return base.WrapForHelpText(output)
}
@@ -13,6 +13,7 @@ import (
"github.com/hashicorp/boundary/api/sessionrecordings" "github.com/hashicorp/boundary/api/sessionrecordings"
"github.com/hashicorp/boundary/internal/cmd/base" "github.com/hashicorp/boundary/internal/cmd/base"
"github.com/hashicorp/boundary/internal/recording" "github.com/hashicorp/boundary/internal/recording"
"github.com/hashicorp/boundary/internal/util"
) )
type extraCmdVars struct{} type extraCmdVars struct{}
@@ -38,8 +39,11 @@ func (c *Command) extraHelpFunc(helpMap map[string]func() string) string {
"", "",
` $ boundary session-recordings download -id chr_1234567890`, ` $ boundary session-recordings download -id chr_1234567890`,
"", "",
" Export a session recording:",
" Please see the sessions subcommand help for detailed usage information.", "",
` $ boundary session-recordings export -connection-recording-id cr_1234567890 -mime-type video/webm`,
"",
" Please see subcommand help for detailed usage information.",
}) })
default: default:
@@ -116,6 +120,28 @@ func (c *Command) printListTable(items []*sessionrecordings.SessionRecording) st
fmt.Sprintf(" State: %s", item.State), fmt.Sprintf(" State: %s", item.State),
) )
} }
if item.Availability != "" {
output = append(output,
fmt.Sprintf(" Availability: %s", item.Availability),
)
}
if !util.IsNil(item.RecordingState) {
if item.RecordingState.StorageState != "" {
output = append(output,
fmt.Sprintf(" Storage State: %s", item.RecordingState.StorageState),
)
}
if item.RecordingState.SyncingErrorDetails != "" {
output = append(output,
fmt.Sprintf(" Syncing Error Details: %s", item.RecordingState.SyncingErrorDetails),
)
}
if item.RecordingState.VerificationErrorDetails != "" {
output = append(output,
fmt.Sprintf(" Verification Error Details: %s", item.RecordingState.VerificationErrorDetails),
)
}
}
if !item.RetainUntil.IsZero() { if !item.RetainUntil.IsZero() {
var retention string var retention string
switch item.RetainUntil { switch item.RetainUntil {
@@ -210,6 +236,9 @@ func printItemTable(item *sessionrecordings.SessionRecording, resp *api.Response
if item.Endpoint != "" { if item.Endpoint != "" {
nonAttributeMap["Endpoint"] = item.Endpoint nonAttributeMap["Endpoint"] = item.Endpoint
} }
if item.Availability != "" {
nonAttributeMap["Availability"] = item.Availability
}
maxLength := base.MaxAttributesLength(nonAttributeMap, nil, nil) maxLength := base.MaxAttributesLength(nonAttributeMap, nil, nil)
@@ -219,6 +248,25 @@ func printItemTable(item *sessionrecordings.SessionRecording, resp *api.Response
base.WrapMap(2, maxLength+2, nonAttributeMap), base.WrapMap(2, maxLength+2, nonAttributeMap),
} }
if !util.IsNil(item.RecordingState) {
recordingStateMap := map[string]any{}
if item.RecordingState.StorageState != "" {
recordingStateMap["Storage State"] = item.RecordingState.StorageState
}
if item.RecordingState.SyncingErrorDetails != "" {
recordingStateMap["Syncing Error Details"] = item.RecordingState.SyncingErrorDetails
}
if item.RecordingState.VerificationErrorDetails != "" {
recordingStateMap["Verification Error Details"] = item.RecordingState.VerificationErrorDetails
}
if len(recordingStateMap) != 0 {
maxRecordingStateLength := base.MaxAttributesLength(recordingStateMap, nil, nil)
ret = append(ret,
" Recording State:", base.WrapMap(4, maxRecordingStateLength+2, recordingStateMap),
)
}
}
if item.Scope != nil { if item.Scope != nil {
ret = append(ret, ret = append(ret,
"", "",
@@ -279,10 +327,16 @@ func printItemTable(item *sessionrecordings.SessionRecording, resp *api.Response
if item.CreateTimeValues.Target.IngressWorkerFilter != "" { if item.CreateTimeValues.Target.IngressWorkerFilter != "" {
targetMap["Ingress Worker Filter"] = item.CreateTimeValues.Target.IngressWorkerFilter targetMap["Ingress Worker Filter"] = item.CreateTimeValues.Target.IngressWorkerFilter
} }
if item.CreateTimeValues.Target.Type != "" {
targetMap["Target Type"] = item.CreateTimeValues.Target.Type
}
if item.CreateTimeValues.Target.Attributes != nil { if item.CreateTimeValues.Target.Attributes != nil {
if attr, err := item.CreateTimeValues.Target.GetSshTargetAttributes(); err == nil && attr != nil && attr.DefaultPort != 0 { if attr, err := item.CreateTimeValues.Target.GetSshTargetAttributes(); err == nil && attr != nil && attr.DefaultPort != 0 {
targetMap["Default Port"] = attr.DefaultPort targetMap["Default Port"] = attr.DefaultPort
} }
if attr, err := item.CreateTimeValues.Target.GetRdpTargetAttributes(); err == nil && attr != nil && attr.DefaultPort != 0 {
targetMap["Default Port"] = attr.DefaultPort
}
} }
maxTargetLength := base.MaxAttributesLength(targetMap, nil, nil) maxTargetLength := base.MaxAttributesLength(targetMap, nil, nil)
ret = append(ret, ret = append(ret,
@@ -388,6 +442,11 @@ func printItemTable(item *sessionrecordings.SessionRecording, resp *api.Response
cm["Http Request Body"] = attrs.HttpRequestBody cm["Http Request Body"] = attrs.HttpRequestBody
} }
} }
if attrs, _ := cl.GetVaultLdapCredentialLibraryAttributes(); attrs != nil {
if attrs.Path != "" {
cm["Path"] = attrs.Path
}
}
maxLibLength := base.MaxAttributesLength(cm, nil, nil) maxLibLength := base.MaxAttributesLength(cm, nil, nil)
ret = append(ret, ret = append(ret,
base.WrapMap(4, maxLibLength, cm), base.WrapMap(4, maxLibLength, cm),
@@ -435,6 +494,14 @@ func printItemTable(item *sessionrecordings.SessionRecording, resp *api.Response
cm["Username"] = attrs.Username cm["Username"] = attrs.Username
} }
} }
if attrs, _ := c.GetUsernamePasswordDomainCredentialAttributes(); attrs != nil {
if attrs.Username != "" {
cm["Username"] = attrs.Username
}
if attrs.Domain != "" {
cm["Domain"] = attrs.Domain
}
}
if attrs, _ := c.GetSshPrivateKeyCredentialAttributes(); attrs != nil { if attrs, _ := c.GetSshPrivateKeyCredentialAttributes(); attrs != nil {
if attrs.Username != "" { if attrs.Username != "" {
cm["Username"] = attrs.Username cm["Username"] = attrs.Username
@@ -462,7 +529,7 @@ func printItemTable(item *sessionrecordings.SessionRecording, resp *api.Response
maxAttrLen := len(durationKey) maxAttrLen := len(durationKey)
ret = append(ret, ret = append(ret,
"", "",
" Connections Recordings:", " Connection Recordings:",
) )
for _, cr := range item.ConnectionRecordings { for _, cr := range item.ConnectionRecordings {
cm := map[string]any{ cm := map[string]any{
@@ -492,13 +559,109 @@ func printItemTable(item *sessionrecordings.SessionRecording, resp *api.Response
if len(cr.MimeTypes) > 0 { if len(cr.MimeTypes) > 0 {
cm["Mime Types"] = strings.Join(cr.MimeTypes, ", ") cm["Mime Types"] = strings.Join(cr.MimeTypes, ", ")
} }
ret = append(ret, ret = append(ret,
base.WrapMap(4, maxAttrLen, cm), base.WrapMap(4, maxAttrLen, cm),
)
if !util.IsNil(cr.RecordingState) {
connRecordingStateMap := map[string]any{}
if cr.RecordingState.StorageState != "" {
connRecordingStateMap["Storage State"] = cr.RecordingState.StorageState
}
if cr.RecordingState.SyncingErrorDetails != "" {
connRecordingStateMap["Syncing Error Details"] = cr.RecordingState.SyncingErrorDetails
}
if cr.RecordingState.VerificationErrorDetails != "" {
connRecordingStateMap["Verification Error Details"] = cr.RecordingState.VerificationErrorDetails
}
if len(connRecordingStateMap) != 0 {
maxConnRecordingStateLength := base.MaxAttributesLength(connRecordingStateMap, nil, nil)
ret = append(ret,
" Recording State:", base.WrapMap(6, maxConnRecordingStateLength+2, connRecordingStateMap),
)
}
}
ret = append(ret,
"", "",
) )
if len(cr.Exports) > 0 {
var exports []map[string]any
for _, exp := range cr.Exports {
expm := map[string]any{
"ID": exp.Id,
}
if exp.MimeType != "" {
expm["Mime Type"] = exp.MimeType
}
if exp.State != "" {
expm["State"] = exp.State
}
if exp.State == "processing" || exp.ProgressPercent > 0 {
expm["Progress (%)"] = exp.ProgressPercent
}
if exp.WorkerId != "" {
expm["Worker ID"] = exp.WorkerId
}
if exp.Error != "" {
expm["Error"] = exp.Error
}
if !exp.CreatedTime.IsZero() {
expm["Created Time"] = exp.CreatedTime.Local().Format(time.RFC1123)
}
if !exp.UpdatedTime.IsZero() {
expm["Updated Time"] = exp.UpdatedTime.Local().Format(time.RFC1123)
}
exports = append(exports, expm)
}
ret = append(ret,
"",
" Connection Recording Exports:",
)
for _, exp := range exports {
ret = append(ret,
base.WrapMap(6, maxAttrLen, exp),
"",
)
}
}
if len(cr.Videos) > 0 {
var videos []map[string]any
for _, vid := range cr.Videos {
vidm := map[string]any{
"ID": vid.Id,
}
if vid.LengthSeconds != 0 {
vidm["Length (Seconds)"] = vid.LengthSeconds
}
if vid.SizeBytes != 0 {
vidm["Size (Bytes)"] = vid.SizeBytes
}
if !vid.CreatedTime.IsZero() {
vidm["Created Time"] = vid.CreatedTime.Local().Format(time.RFC1123)
}
videos = append(videos, vidm)
}
ret = append(ret,
"",
" Connection Recording Videos:",
)
for _, vid := range videos {
ret = append(ret,
base.WrapMap(6, maxAttrLen, vid),
"",
)
}
}
if len(cr.ChannelRecordings) > 0 { if len(cr.ChannelRecordings) > 0 {
var channelRecordings []map[string]any ret = append(ret,
" Channel Recordings:",
)
for _, chr := range cr.ChannelRecordings { for _, chr := range cr.ChannelRecordings {
chrm := map[string]any{ chrm := map[string]any{
"ID": chr.Id, "ID": chr.Id,
@@ -527,15 +690,35 @@ func printItemTable(item *sessionrecordings.SessionRecording, resp *api.Response
if len(chr.MimeTypes) > 0 { if len(chr.MimeTypes) > 0 {
chrm["Mime Types"] = strings.Join(chr.MimeTypes, ", ") chrm["Mime Types"] = strings.Join(chr.MimeTypes, ", ")
} }
channelRecordings = append(channelRecordings, chrm) // SSH attributes (SshChannelRecording in the proto exposes
} // mime_types via the Attributes map).
ret = append(ret, if mimeTypes, ok := chr.Attributes["mime_types"].([]string); ok && len(mimeTypes) > 0 {
"", chrm["Mime Types"] = strings.Join(mimeTypes, ", ")
" Channel Recordings:", }
) ret = append(ret,
for _, cr := range channelRecordings { base.WrapMap(6, maxAttrLen, chrm),
)
if !util.IsNil(chr.RecordingState) {
chanRecordingStateMap := map[string]any{}
if chr.RecordingState.StorageState != "" {
chanRecordingStateMap["Storage State"] = chr.RecordingState.StorageState
}
if chr.RecordingState.SyncingErrorDetails != "" {
chanRecordingStateMap["Syncing Error Details"] = chr.RecordingState.SyncingErrorDetails
}
if chr.RecordingState.VerificationErrorDetails != "" {
chanRecordingStateMap["Verification Error Details"] = chr.RecordingState.VerificationErrorDetails
}
if len(chanRecordingStateMap) != 0 {
maxChanRecordingStateLength := base.MaxAttributesLength(chanRecordingStateMap, nil, nil)
ret = append(ret,
" Recording State:", base.WrapMap(8, maxChanRecordingStateLength+2, chanRecordingStateMap),
)
}
}
ret = append(ret, ret = append(ret,
base.WrapMap(6, maxAttrLen, cr),
"", "",
) )
} }
+37 -1
View File
@@ -25,10 +25,13 @@ func extraRdpActionsFlagsMapFuncImpl() map[string][]string {
"create": { "create": {
"address", "default-port", "default-client-port", "session-max-seconds", "session-connection-limit", "address", "default-port", "default-client-port", "session-max-seconds", "session-connection-limit",
"egress-worker-filter", "ingress-worker-filter", "egress-worker-filter", "ingress-worker-filter",
"enable-session-recording", "storage-bucket-id",
"with-alias-value", "with-alias-scope-id", "with-alias-authorize-session-host-id", "with-alias-value", "with-alias-scope-id", "with-alias-authorize-session-host-id",
}, },
"update": { "update": {
"address", "default-port", "default-client-port", "session-max-seconds", "session-connection-limit", "egress-worker-filter", "ingress-worker-filter", "address", "default-port", "default-client-port", "session-max-seconds",
"session-connection-limit", "egress-worker-filter", "ingress-worker-filter",
"enable-session-recording", "storage-bucket-id",
}, },
} }
} }
@@ -44,6 +47,8 @@ type extraRdpCmdVars struct {
flagWithAliasValue string flagWithAliasValue string
flagWithAliasScopeId string flagWithAliasScopeId string
flagWithAliasHostId string flagWithAliasHostId string
flagStorageBucketId string
flagEnableSessionRecording string
} }
func (c *RdpCommand) extraRdpHelpFunc(helpMap map[string]func() string) string { func (c *RdpCommand) extraRdpHelpFunc(helpMap map[string]func() string) string {
@@ -140,6 +145,18 @@ func extraRdpFlagsFuncImpl(c *RdpCommand, set *base.FlagSets, f *base.FlagSet) {
Target: &c.flagWithAliasHostId, Target: &c.flagWithAliasHostId,
Usage: "The authorize session host id flag used by an alias to be created for and at the same time as this target.", Usage: "The authorize session host id flag used by an alias to be created for and at the same time as this target.",
}) })
case "storage-bucket-id":
fs.StringVar(&base.StringVar{
Name: "storage-bucket-id",
Target: &c.flagStorageBucketId,
Usage: "The public ID of the storage bucket to associate with this target.",
})
case "enable-session-recording":
fs.StringVar(&base.StringVar{
Name: "enable-session-recording",
Target: &c.flagEnableSessionRecording,
Usage: "A boolean indicating if session recording is enabled for this target.",
})
} }
} }
} }
@@ -234,6 +251,25 @@ func extraRdpFlagsHandlingFuncImpl(c *RdpCommand, _ *base.FlagSets, opts *[]targ
*opts = append(*opts, targets.WithAddress(c.flagAddress)) *opts = append(*opts, targets.WithAddress(c.flagAddress))
} }
switch c.flagStorageBucketId {
case "":
case "null":
*opts = append(*opts, targets.DefaultRdpTargetStorageBucketId())
default:
*opts = append(*opts, targets.WithRdpTargetStorageBucketId(c.flagStorageBucketId))
}
switch c.flagEnableSessionRecording {
case "":
case "false":
*opts = append(*opts, targets.WithRdpTargetEnableSessionRecording(false))
case "true":
*opts = append(*opts, targets.WithRdpTargetEnableSessionRecording(true))
default:
c.UI.Error(fmt.Sprintf("Invalid bool value for enable-session-recording %v", c.flagEnableSessionRecording))
return false
}
var aliasValue string var aliasValue string
switch c.flagWithAliasValue { switch c.flagWithAliasValue {
case "": case "":
+376 -7
View File
@@ -4043,6 +4043,46 @@
] ]
} }
}, },
"/v1/session-recordings/{connection_recording_id}:export": {
"post": {
"summary": "CreateExport creates an export of the specified Connection Recording in the requested mime type. The export is processed asynchronously; use GetExport to poll the status of the export. If the ID is missing, malformed, or references a non-existing resource, an error is returned.",
"operationId": "SessionRecordingService_CreateExport",
"responses": {
"200": {
"description": "The created export.",
"schema": {
"$ref": "#/definitions/controller.api.resources.sessionrecordings.v1.Export"
}
},
"default": {
"description": "Returned when there is an error processing the request.",
"schema": {
"$ref": "#/definitions/controller.api.v1.Error"
}
}
},
"parameters": [
{
"name": "connection_recording_id",
"description": "The ID of the Connection Recording to export.",
"in": "path",
"required": true,
"type": "string"
},
{
"name": "body",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/controller.api.services.v1.SessionRecordingService.CreateExportBody"
}
}
],
"tags": [
"Session recording service"
]
}
},
"/v1/session-recordings/{id}": { "/v1/session-recordings/{id}": {
"get": { "get": {
"summary": "GetSessionRecording returns a stored Session recording if present. The provided request must include the Session recording ID for the Session recording being retrieved, or the ID of the Session that was recorded. If that ID is missing, malformed or reference a non existing resource, an error is returned.", "summary": "GetSessionRecording returns a stored Session recording if present. The provided request must include the Session recording ID for the Session recording being retrieved, or the ID of the Session that was recorded. If that ID is missing, malformed or reference a non existing resource, an error is returned.",
@@ -4075,7 +4115,7 @@
] ]
}, },
"delete": { "delete": {
"summary": "Deletes a Session Recording", "summary": "Deletes a Session Recording when provided a Session Recording ID, or deletes a Video recording when provided a Video ID. If the ID is malformed or not provided an error is returned.",
"operationId": "SessionRecordingService_DeleteSessionRecording", "operationId": "SessionRecordingService_DeleteSessionRecording",
"responses": { "responses": {
"200": { "200": {
@@ -4107,7 +4147,7 @@
}, },
"/v1/session-recordings/{id}:download": { "/v1/session-recordings/{id}:download": {
"get": { "get": {
"summary": "Download returns the contents of the specified resource in the specified mime type. Supports both Session ID and Session recording ID for looking up a Session recording. Supports both Connection ID and Connection recording ID to look up a Connection recording. A Channel recording ID is required to look up a Channel recording. The only supported mime type is \"application/x-asciicast\".", "summary": "Download returns the contents of the specified resource in the specified mime type. Supports both Session ID and Session recording ID for looking up a Session recording. Supports both Connection ID and Connection recording ID to look up a Connection recording. A Channel recording ID is required to look up a Channel recording. A Video ID is required to look up a Video recording. Supported mime types: \"application/x-asciicast\", \"video/webm\".",
"operationId": "SessionRecordingService_Download", "operationId": "SessionRecordingService_Download",
"responses": { "responses": {
"200": { "200": {
@@ -4129,14 +4169,14 @@
"parameters": [ "parameters": [
{ {
"name": "id", "name": "id",
"description": "The ID of the resource that should be downloaded. Supported types:\n - Session ID and Session recording ID for Session recordings\n - Connection ID and Connection recording ID for Connection recordings\n - Channel recording ID for Channel recordings", "description": "The ID of the resource that should be downloaded. Supported types:\n - Session ID and Session recording ID for Session recordings\n - Connection ID and Connection recording ID for Connection recordings\n - Channel recording ID for Channel recordings\n - Video ID for Video recordings",
"in": "path", "in": "path",
"required": true, "required": true,
"type": "string" "type": "string"
}, },
{ {
"name": "mime_type", "name": "mime_type",
"description": "The format of the response. The only supported mime type is \"application/x-asciicast\".\nDefaults to \"application/x-asciicast\" if not set.", "description": "The format of the response. Supports \"application/x-asciicast\" and \"video/webm\".\nDefaults to \"application/x-asciicast\" if not set.",
"in": "query", "in": "query",
"required": false, "required": false,
"type": "string" "type": "string"
@@ -4147,6 +4187,70 @@
] ]
} }
}, },
"/v1/session-recordings/{id}:export": {
"get": {
"summary": "GetExport returns a stored Export if present. The provided request must include the Export ID for the Export being retrieved. If that ID is missing, malformed, or references a non-existing resource, an error is returned.",
"operationId": "SessionRecordingService_GetExport",
"responses": {
"200": {
"description": "The requested export.",
"schema": {
"$ref": "#/definitions/controller.api.resources.sessionrecordings.v1.Export"
}
},
"default": {
"description": "Returned when there is an error processing the request.",
"schema": {
"$ref": "#/definitions/controller.api.v1.Error"
}
}
},
"parameters": [
{
"name": "id",
"description": "The ID of the Export to retrieve.",
"in": "path",
"required": true,
"type": "string"
}
],
"tags": [
"Session recording service"
]
}
},
"/v1/session-recordings/{id}:export:cancel": {
"post": {
"summary": "CancelExport cancels an Export that is in progress. The provided request must include the Export ID for the Export being cancelled. If that ID is missing, malformed, or references a non-existing resource, an error is returned. Returns the Export in its cancelled state.",
"operationId": "SessionRecordingService_CancelExport",
"responses": {
"200": {
"description": "A successful response.",
"schema": {
"$ref": "#/definitions/controller.api.services.v1.CancelExportResponse"
}
},
"default": {
"description": "Returned when there is an error processing the request.",
"schema": {
"$ref": "#/definitions/controller.api.v1.Error"
}
}
},
"parameters": [
{
"name": "id",
"description": "The ID of the Export to cancel.",
"in": "path",
"required": true,
"type": "string"
}
],
"tags": [
"Session recording service"
]
}
},
"/v1/session-recordings/{id}:reapply-storage-policy": { "/v1/session-recordings/{id}:reapply-storage-policy": {
"post": { "post": {
"summary": "ReApplyStoragePolicy will recalculate the resultant set of policy and apply the result to the given session recording.", "summary": "ReApplyStoragePolicy will recalculate the resultant set of policy and apply the result to the given session recording.",
@@ -4179,6 +4283,60 @@
] ]
} }
}, },
"/v1/session-recordings:list-exports": {
"get": {
"summary": "ListExports lists all exports. Exports are ordered by created_time descending (most recently created first).",
"operationId": "SessionRecordingService_ListExports",
"responses": {
"200": {
"description": "A successful response.",
"schema": {
"$ref": "#/definitions/controller.api.services.v1.ListExportsResponse"
}
},
"default": {
"description": "Returned when there is an error processing the request.",
"schema": {
"$ref": "#/definitions/controller.api.v1.Error"
}
}
},
"parameters": [
{
"name": "scope_id",
"description": "The scope in which to list exports.\nMust be set unless recursive is set.",
"in": "query",
"required": false,
"type": "string"
},
{
"name": "recursive",
"description": "Whether to recurse into child scopes when listing.\nIf set and scope_id is empty, shows exports in\nall scopes the caller has access to.",
"in": "query",
"required": false,
"type": "boolean"
},
{
"name": "list_token",
"description": "An opaque token that Boundary uses to continue an existing iteration or\nrequest updated items. If you do not specify a token, pagination\nstarts from the beginning. To learn more about list pagination\nin Boundary, refer to [list pagination](https://developer.hashicorp.com/boundary/docs/api-clients/api/pagination).",
"in": "query",
"required": false,
"type": "string"
},
{
"name": "page_size",
"description": "The maximum size of a page in this iteration.\nIf you do not set a page size, Boundary uses the configured default page size.\nIf the page_size is greater than the default page size configured,\nBoundary truncates the page size to this number.",
"in": "query",
"required": false,
"type": "integer",
"format": "int64"
}
],
"tags": [
"Session recording service"
]
}
},
"/v1/sessions": { "/v1/sessions": {
"get": { "get": {
"summary": "Lists all Sessions.", "summary": "Lists all Sessions.",
@@ -7195,7 +7353,15 @@
"items": { "items": {
"type": "string" "type": "string"
}, },
"description": "MimeTypes define the mime types that can\nbe used to consume the recording of this Channel.\nThe only supported mime type is \"application/x-asciicast\"." "description": "MimeTypes define the mime types that can\nbe used to consume the recording of this Channel.\nThe only supported mime type is \"application/x-asciicast\".\nDeprecated: This field has been moved to SSH-specific attributes and will be removed\nentirely in a future Boundary version."
},
"recording_state": {
"$ref": "#/definitions/controller.api.resources.sessionrecordings.v1.RecordingState",
"description": "The detailed state of the channel recording."
},
"attributes": {
"type": "object",
"description": "The attributes that are applicable for the specific Channel Recording type."
} }
}, },
"description": "ChannelRecording contains recorded information about a single Channel within a Connection.\nChannels are only present in multiplexed protocols, such as SSH." "description": "ChannelRecording contains recorded information about a single Channel within a Connection.\nChannels are only present in multiplexed protocols, such as SSH."
@@ -7255,6 +7421,26 @@
"$ref": "#/definitions/controller.api.resources.sessionrecordings.v1.ChannelRecording" "$ref": "#/definitions/controller.api.resources.sessionrecordings.v1.ChannelRecording"
}, },
"description": "Optionally, the channels used in this Connection,\nif it is using a multiplexed protocol, such as SSH." "description": "Optionally, the channels used in this Connection,\nif it is using a multiplexed protocol, such as SSH."
},
"recording_state": {
"$ref": "#/definitions/controller.api.resources.sessionrecordings.v1.RecordingState",
"description": "The detailed state of the connection recording."
},
"exports": {
"type": "array",
"items": {
"type": "object",
"$ref": "#/definitions/controller.api.resources.sessionrecordings.v1.Export"
},
"description": "Optionally, exports that may have been created for this Connection\nRecording."
},
"videos": {
"type": "array",
"items": {
"type": "object",
"$ref": "#/definitions/controller.api.resources.sessionrecordings.v1.Video"
},
"description": "Optionally, videos that may have been recorded for this Connection\nRecording."
} }
}, },
"description": "ConnectionRecording contains the recording of a single Connection within a Session." "description": "ConnectionRecording contains the recording of a single Connection within a Session."
@@ -7363,6 +7549,67 @@
}, },
"title": "CredentialStore contains all fields related to a Credential Store resource" "title": "CredentialStore contains all fields related to a Credential Store resource"
}, },
"controller.api.resources.sessionrecordings.v1.Export": {
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "The ID of the Export."
},
"scope": {
"$ref": "#/definitions/controller.api.resources.scopes.v1.ScopeInfo",
"description": "The scope that the Export is in. This is inferred from the storage bucket\nassociated with the session recording."
},
"mime_type": {
"type": "string",
"description": "The mime type of the Export."
},
"state": {
"type": "string",
"description": "The current state of the Export."
},
"progress_percent": {
"type": "integer",
"format": "int64",
"description": "The export's current progress."
},
"worker_id": {
"type": "string",
"description": "The ID of the worker processing the Export."
},
"created_time": {
"type": "string",
"format": "date-time",
"description": "The time the Export was created."
},
"updated_time": {
"type": "string",
"format": "date-time",
"description": "The time of the most recent update to the Export."
},
"version": {
"type": "integer",
"format": "int64",
"description": "The version of the Export."
},
"connection_recording_id": {
"type": "string",
"description": "The ID of the Connection Recording being exported."
},
"error": {
"type": "string",
"description": "Any error encountered during the Export, if the Export failed."
},
"authorized_actions": {
"type": "array",
"items": {
"type": "string"
},
"description": "The available actions on this resource for this user."
}
},
"description": "Export contains information about the export of a session recording."
},
"controller.api.resources.sessionrecordings.v1.Host": { "controller.api.resources.sessionrecordings.v1.Host": {
"type": "object", "type": "object",
"properties": { "properties": {
@@ -7440,6 +7687,24 @@
}, },
"description": "HostCatalog describes the HostCatalog that contains the host chosen for the\nrecorded session." "description": "HostCatalog describes the HostCatalog that contains the host chosen for the\nrecorded session."
}, },
"controller.api.resources.sessionrecordings.v1.RecordingState": {
"type": "object",
"properties": {
"storage_state": {
"type": "string",
"description": "Information about the storage state of the recording."
},
"syncing_error_details": {
"type": "string",
"description": "Information about the syncing error details of the recording."
},
"verification_error_details": {
"type": "string",
"description": "Information about the verification error details of the recording."
}
},
"description": "RecordingState contain information about the state of a recording."
},
"controller.api.resources.sessionrecordings.v1.SessionRecording": { "controller.api.resources.sessionrecordings.v1.SessionRecording": {
"type": "object", "type": "object",
"properties": { "properties": {
@@ -7499,11 +7764,11 @@
}, },
"state": { "state": {
"type": "string", "type": "string",
"description": "The current state of the session recording. One of\n\"started\", \"available\" and \"unknown\"." "description": "The current state of the session recording. One of\n\"started\", \"available\" and \"unknown\".\n\nNote: this field will eventually be deprecated two release after 1.0.0\nin favor of the availability field."
}, },
"error_details": { "error_details": {
"type": "string", "type": "string",
"description": "Any error seen during the closing of the session recording.\nCurrently only set if state is \"unknown\"." "description": "Any error seen during the closing of the session recording.\nCurrently only set if state is \"unknown\".\n\nNote: this field will eventually be deprecated two release after 1.0.0\nin favor of the error details contained in the recording_state field."
}, },
"mime_types": { "mime_types": {
"type": "array", "type": "array",
@@ -7544,6 +7809,14 @@
"type": "string", "type": "string",
"format": "date-time", "format": "date-time",
"description": "The time a session recording is scheduled to be automatically deleted." "description": "The time a session recording is scheduled to be automatically deleted."
},
"availability": {
"type": "string",
"description": "The availability of the session recording. One of \"available\" or \"not available\"."
},
"recording_state": {
"$ref": "#/definitions/controller.api.resources.sessionrecordings.v1.RecordingState",
"description": "The detailed state of the session recording."
} }
}, },
"description": "SessionRecording contains information about the recording of a Session." "description": "SessionRecording contains information about the recording of a Session."
@@ -7656,6 +7929,31 @@
}, },
"description": "ValuesAtTime contain information about other Boundary resources as they\nwere at a certain time through the lifetime of the Session Recording." "description": "ValuesAtTime contain information about other Boundary resources as they\nwere at a certain time through the lifetime of the Session Recording."
}, },
"controller.api.resources.sessionrecordings.v1.Video": {
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "The ID of the Video."
},
"created_time": {
"type": "string",
"format": "date-time",
"description": "The time the Video was created."
},
"length_seconds": {
"type": "string",
"format": "uint64",
"description": "The duration of the Video in seconds."
},
"size_bytes": {
"type": "string",
"format": "uint64",
"description": "The size of the Video in bytes."
}
},
"description": "Video contains information about the video recording of a Session Recording."
},
"controller.api.resources.sessions.v1.Connection": { "controller.api.resources.sessions.v1.Connection": {
"type": "object", "type": "object",
"properties": { "properties": {
@@ -8826,6 +9124,9 @@
} }
} }
}, },
"controller.api.services.v1.CancelExportResponse": {
"type": "object"
},
"controller.api.services.v1.CancelSessionResponse": { "controller.api.services.v1.CancelSessionResponse": {
"type": "object", "type": "object",
"properties": { "properties": {
@@ -8934,6 +9235,15 @@
} }
} }
}, },
"controller.api.services.v1.CreateExportResponse": {
"type": "object",
"properties": {
"item": {
"$ref": "#/definitions/controller.api.resources.sessionrecordings.v1.Export",
"description": "The created export."
}
}
},
"controller.api.services.v1.CreateGroupResponse": { "controller.api.services.v1.CreateGroupResponse": {
"type": "object", "type": "object",
"properties": { "properties": {
@@ -9223,6 +9533,15 @@
} }
} }
}, },
"controller.api.services.v1.GetExportResponse": {
"type": "object",
"properties": {
"item": {
"$ref": "#/definitions/controller.api.resources.sessionrecordings.v1.Export",
"description": "The requested export."
}
}
},
"controller.api.services.v1.GetGroupResponse": { "controller.api.services.v1.GetGroupResponse": {
"type": "object", "type": "object",
"properties": { "properties": {
@@ -9724,6 +10043,47 @@
} }
} }
}, },
"controller.api.services.v1.ListExportsResponse": {
"type": "object",
"properties": {
"items": {
"type": "array",
"items": {
"type": "object",
"$ref": "#/definitions/controller.api.resources.sessionrecordings.v1.Export"
},
"description": "The items returned in this page."
},
"response_type": {
"type": "string",
"description": "The type of response, either \"delta\" or \"complete\".\nDelta signifies that this is part of a paginated result\nor an update to a previously completed pagination.\nComplete signifies that it is the last page."
},
"list_token": {
"type": "string",
"description": "An opaque token used to continue an existing pagination or\nrequest updated items. Use this token in the next list request\nto request the next page."
},
"sort_by": {
"type": "string",
"description": "The name of the field which the items are sorted by."
},
"sort_dir": {
"type": "string",
"description": "The direction of the sort, either \"asc\" or \"desc\"."
},
"removed_ids": {
"type": "array",
"items": {
"type": "string"
},
"description": "A list of item IDs that have been removed since they were returned\nas part of a pagination. They should be dropped from any client cache.\nThis may contain items that are not known to the cache, if they were\ncreated and deleted between listings."
},
"est_item_count": {
"type": "integer",
"format": "int64",
"description": "An estimate at the total items available. This may change during pagination."
}
}
},
"controller.api.services.v1.ListGroupsResponse": { "controller.api.services.v1.ListGroupsResponse": {
"type": "object", "type": "object",
"properties": { "properties": {
@@ -10625,6 +10985,15 @@
} }
} }
}, },
"controller.api.services.v1.SessionRecordingService.CreateExportBody": {
"type": "object",
"properties": {
"mime_type": {
"type": "string",
"description": "The mime type of the export."
}
}
},
"controller.api.services.v1.SessionService.CancelSessionBody": { "controller.api.services.v1.SessionService.CancelSessionBody": {
"type": "object", "type": "object",
"properties": { "properties": {
@@ -312,8 +312,9 @@ type DownloadRequest struct {
// - Session ID and Session recording ID for Session recordings // - Session ID and Session recording ID for Session recordings
// - Connection ID and Connection recording ID for Connection recordings // - Connection ID and Connection recording ID for Connection recordings
// - Channel recording ID for Channel recordings // - Channel recording ID for Channel recordings
// - Video ID for Video recordings
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty" class:"public" eventstream:"observation"` // @gotags: class:"public" eventstream:"observation" Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty" class:"public" eventstream:"observation"` // @gotags: class:"public" eventstream:"observation"
// The format of the response. The only supported mime type is "application/x-asciicast". // The format of the response. Supports "application/x-asciicast" and "video/webm".
// Defaults to "application/x-asciicast" if not set. // Defaults to "application/x-asciicast" if not set.
MimeType string `protobuf:"bytes,2,opt,name=mime_type,proto3" json:"mime_type,omitempty" class:"public" eventstream:"observation"` // @gotags: class:"public" eventstream:"observation" MimeType string `protobuf:"bytes,2,opt,name=mime_type,proto3" json:"mime_type,omitempty" class:"public" eventstream:"observation"` // @gotags: class:"public" eventstream:"observation"
unknownFields protoimpl.UnknownFields unknownFields protoimpl.UnknownFields
@@ -534,6 +535,464 @@ func (*DeleteSessionRecordingResponse) Descriptor() ([]byte, []int) {
return file_controller_api_services_v1_session_recording_service_proto_rawDescGZIP(), []int{8} return file_controller_api_services_v1_session_recording_service_proto_rawDescGZIP(), []int{8}
} }
type CreateExportRequest struct {
state protoimpl.MessageState `protogen:"open.v1"`
// The ID of the Connection Recording to export.
ConnectionRecordingId string `protobuf:"bytes,1,opt,name=connection_recording_id,json=connectionRecordingId,proto3" json:"connection_recording_id,omitempty" class:"public" eventstream:"observation"` // @gotags: class:"public" eventstream:"observation"
// The mime type of the export.
MimeType string `protobuf:"bytes,2,opt,name=mime_type,proto3" json:"mime_type,omitempty" class:"public" eventstream:"observation"` // @gotags: class:"public" eventstream:"observation"
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *CreateExportRequest) Reset() {
*x = CreateExportRequest{}
mi := &file_controller_api_services_v1_session_recording_service_proto_msgTypes[9]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *CreateExportRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*CreateExportRequest) ProtoMessage() {}
func (x *CreateExportRequest) ProtoReflect() protoreflect.Message {
mi := &file_controller_api_services_v1_session_recording_service_proto_msgTypes[9]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use CreateExportRequest.ProtoReflect.Descriptor instead.
func (*CreateExportRequest) Descriptor() ([]byte, []int) {
return file_controller_api_services_v1_session_recording_service_proto_rawDescGZIP(), []int{9}
}
func (x *CreateExportRequest) GetConnectionRecordingId() string {
if x != nil {
return x.ConnectionRecordingId
}
return ""
}
func (x *CreateExportRequest) GetMimeType() string {
if x != nil {
return x.MimeType
}
return ""
}
type CreateExportResponse struct {
state protoimpl.MessageState `protogen:"open.v1"`
// The created export.
Item *session_recordings.Export `protobuf:"bytes,1,opt,name=item,proto3" json:"item,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *CreateExportResponse) Reset() {
*x = CreateExportResponse{}
mi := &file_controller_api_services_v1_session_recording_service_proto_msgTypes[10]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *CreateExportResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*CreateExportResponse) ProtoMessage() {}
func (x *CreateExportResponse) ProtoReflect() protoreflect.Message {
mi := &file_controller_api_services_v1_session_recording_service_proto_msgTypes[10]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use CreateExportResponse.ProtoReflect.Descriptor instead.
func (*CreateExportResponse) Descriptor() ([]byte, []int) {
return file_controller_api_services_v1_session_recording_service_proto_rawDescGZIP(), []int{10}
}
func (x *CreateExportResponse) GetItem() *session_recordings.Export {
if x != nil {
return x.Item
}
return nil
}
type GetExportRequest struct {
state protoimpl.MessageState `protogen:"open.v1"`
// The ID of the Export to retrieve.
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty" class:"public" eventstream:"observation"` // @gotags: class:"public" eventstream:"observation"
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *GetExportRequest) Reset() {
*x = GetExportRequest{}
mi := &file_controller_api_services_v1_session_recording_service_proto_msgTypes[11]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *GetExportRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*GetExportRequest) ProtoMessage() {}
func (x *GetExportRequest) ProtoReflect() protoreflect.Message {
mi := &file_controller_api_services_v1_session_recording_service_proto_msgTypes[11]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use GetExportRequest.ProtoReflect.Descriptor instead.
func (*GetExportRequest) Descriptor() ([]byte, []int) {
return file_controller_api_services_v1_session_recording_service_proto_rawDescGZIP(), []int{11}
}
func (x *GetExportRequest) GetId() string {
if x != nil {
return x.Id
}
return ""
}
type GetExportResponse struct {
state protoimpl.MessageState `protogen:"open.v1"`
// The requested export.
Item *session_recordings.Export `protobuf:"bytes,1,opt,name=item,proto3" json:"item,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *GetExportResponse) Reset() {
*x = GetExportResponse{}
mi := &file_controller_api_services_v1_session_recording_service_proto_msgTypes[12]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *GetExportResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*GetExportResponse) ProtoMessage() {}
func (x *GetExportResponse) ProtoReflect() protoreflect.Message {
mi := &file_controller_api_services_v1_session_recording_service_proto_msgTypes[12]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use GetExportResponse.ProtoReflect.Descriptor instead.
func (*GetExportResponse) Descriptor() ([]byte, []int) {
return file_controller_api_services_v1_session_recording_service_proto_rawDescGZIP(), []int{12}
}
func (x *GetExportResponse) GetItem() *session_recordings.Export {
if x != nil {
return x.Item
}
return nil
}
type ListExportsRequest struct {
state protoimpl.MessageState `protogen:"open.v1"`
// The scope in which to list exports.
// Must be set unless recursive is set.
ScopeId string `protobuf:"bytes,1,opt,name=scope_id,json=scopeId,proto3" json:"scope_id,omitempty" class:"public" eventstream:"observation"` // @gotags: class:"public" eventstream:"observation"
// Whether to recurse into child scopes when listing.
// If set and scope_id is empty, shows exports in
// all scopes the caller has access to.
Recursive bool `protobuf:"varint,2,opt,name=recursive,proto3" json:"recursive,omitempty" class:"public" eventstream:"observation"` // @gotags: class:"public" eventstream:"observation"
// An opaque token that Boundary uses to continue an existing iteration or
// request updated items. If you do not specify a token, pagination
// starts from the beginning. To learn more about list pagination
// in Boundary, refer to [list pagination](https://developer.hashicorp.com/boundary/docs/api-clients/api/pagination).
ListToken string `protobuf:"bytes,3,opt,name=list_token,proto3" json:"list_token,omitempty" class:"public"` // @gotags: `class:"public"`
// The maximum size of a page in this iteration.
// If you do not set a page size, Boundary uses the configured default page size.
// If the page_size is greater than the default page size configured,
// Boundary truncates the page size to this number.
PageSize uint32 `protobuf:"varint,4,opt,name=page_size,proto3" json:"page_size,omitempty" class:"public" eventstream:"observation"` // @gotags: class:"public" eventstream:"observation"
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *ListExportsRequest) Reset() {
*x = ListExportsRequest{}
mi := &file_controller_api_services_v1_session_recording_service_proto_msgTypes[13]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *ListExportsRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ListExportsRequest) ProtoMessage() {}
func (x *ListExportsRequest) ProtoReflect() protoreflect.Message {
mi := &file_controller_api_services_v1_session_recording_service_proto_msgTypes[13]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use ListExportsRequest.ProtoReflect.Descriptor instead.
func (*ListExportsRequest) Descriptor() ([]byte, []int) {
return file_controller_api_services_v1_session_recording_service_proto_rawDescGZIP(), []int{13}
}
func (x *ListExportsRequest) GetScopeId() string {
if x != nil {
return x.ScopeId
}
return ""
}
func (x *ListExportsRequest) GetRecursive() bool {
if x != nil {
return x.Recursive
}
return false
}
func (x *ListExportsRequest) GetListToken() string {
if x != nil {
return x.ListToken
}
return ""
}
func (x *ListExportsRequest) GetPageSize() uint32 {
if x != nil {
return x.PageSize
}
return 0
}
type ListExportsResponse struct {
state protoimpl.MessageState `protogen:"open.v1"`
// The items returned in this page.
Items []*session_recordings.Export `protobuf:"bytes,1,rep,name=items,proto3" json:"items,omitempty"`
// The type of response, either "delta" or "complete".
// Delta signifies that this is part of a paginated result
// or an update to a previously completed pagination.
// Complete signifies that it is the last page.
ResponseType string `protobuf:"bytes,2,opt,name=response_type,proto3" json:"response_type,omitempty" class:"public" eventstream:"observation"` // @gotags: class:"public" eventstream:"observation"
// An opaque token used to continue an existing pagination or
// request updated items. Use this token in the next list request
// to request the next page.
ListToken string `protobuf:"bytes,3,opt,name=list_token,proto3" json:"list_token,omitempty" class:"public"` // @gotags: `class:"public"`
// The name of the field which the items are sorted by.
SortBy string `protobuf:"bytes,4,opt,name=sort_by,proto3" json:"sort_by,omitempty" class:"public" eventstream:"observation"` // @gotags: class:"public" eventstream:"observation"
// The direction of the sort, either "asc" or "desc".
SortDir string `protobuf:"bytes,5,opt,name=sort_dir,proto3" json:"sort_dir,omitempty" class:"public" eventstream:"observation"` // @gotags: class:"public" eventstream:"observation"
// A list of item IDs that have been removed since they were returned
// as part of a pagination. They should be dropped from any client cache.
// This may contain items that are not known to the cache, if they were
// created and deleted between listings.
RemovedIds []string `protobuf:"bytes,6,rep,name=removed_ids,proto3" json:"removed_ids,omitempty" class:"public" eventstream:"observation"` // @gotags: class:"public" eventstream:"observation"
// An estimate at the total items available. This may change during pagination.
EstItemCount uint32 `protobuf:"varint,7,opt,name=est_item_count,proto3" json:"est_item_count,omitempty" class:"public" eventstream:"observation"` // @gotags: class:"public" eventstream:"observation"
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *ListExportsResponse) Reset() {
*x = ListExportsResponse{}
mi := &file_controller_api_services_v1_session_recording_service_proto_msgTypes[14]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *ListExportsResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ListExportsResponse) ProtoMessage() {}
func (x *ListExportsResponse) ProtoReflect() protoreflect.Message {
mi := &file_controller_api_services_v1_session_recording_service_proto_msgTypes[14]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use ListExportsResponse.ProtoReflect.Descriptor instead.
func (*ListExportsResponse) Descriptor() ([]byte, []int) {
return file_controller_api_services_v1_session_recording_service_proto_rawDescGZIP(), []int{14}
}
func (x *ListExportsResponse) GetItems() []*session_recordings.Export {
if x != nil {
return x.Items
}
return nil
}
func (x *ListExportsResponse) GetResponseType() string {
if x != nil {
return x.ResponseType
}
return ""
}
func (x *ListExportsResponse) GetListToken() string {
if x != nil {
return x.ListToken
}
return ""
}
func (x *ListExportsResponse) GetSortBy() string {
if x != nil {
return x.SortBy
}
return ""
}
func (x *ListExportsResponse) GetSortDir() string {
if x != nil {
return x.SortDir
}
return ""
}
func (x *ListExportsResponse) GetRemovedIds() []string {
if x != nil {
return x.RemovedIds
}
return nil
}
func (x *ListExportsResponse) GetEstItemCount() uint32 {
if x != nil {
return x.EstItemCount
}
return 0
}
type CancelExportRequest struct {
state protoimpl.MessageState `protogen:"open.v1"`
// The ID of the Export to cancel.
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty" class:"public" eventstream:"observation"` // @gotags: class:"public" eventstream:"observation"
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *CancelExportRequest) Reset() {
*x = CancelExportRequest{}
mi := &file_controller_api_services_v1_session_recording_service_proto_msgTypes[15]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *CancelExportRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*CancelExportRequest) ProtoMessage() {}
func (x *CancelExportRequest) ProtoReflect() protoreflect.Message {
mi := &file_controller_api_services_v1_session_recording_service_proto_msgTypes[15]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use CancelExportRequest.ProtoReflect.Descriptor instead.
func (*CancelExportRequest) Descriptor() ([]byte, []int) {
return file_controller_api_services_v1_session_recording_service_proto_rawDescGZIP(), []int{15}
}
func (x *CancelExportRequest) GetId() string {
if x != nil {
return x.Id
}
return ""
}
type CancelExportResponse struct {
state protoimpl.MessageState `protogen:"open.v1"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *CancelExportResponse) Reset() {
*x = CancelExportResponse{}
mi := &file_controller_api_services_v1_session_recording_service_proto_msgTypes[16]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *CancelExportResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*CancelExportResponse) ProtoMessage() {}
func (x *CancelExportResponse) ProtoReflect() protoreflect.Message {
mi := &file_controller_api_services_v1_session_recording_service_proto_msgTypes[16]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use CancelExportResponse.ProtoReflect.Descriptor instead.
func (*CancelExportResponse) Descriptor() ([]byte, []int) {
return file_controller_api_services_v1_session_recording_service_proto_rawDescGZIP(), []int{16}
}
var File_controller_api_services_v1_session_recording_service_proto protoreflect.FileDescriptor var File_controller_api_services_v1_session_recording_service_proto protoreflect.FileDescriptor
const file_controller_api_services_v1_session_recording_service_proto_rawDesc = "" + const file_controller_api_services_v1_session_recording_service_proto_rawDesc = "" +
@@ -569,13 +1028,46 @@ const file_controller_api_services_v1_session_recording_service_proto_rawDesc =
"\x04item\x18\x01 \x01(\v2?.controller.api.resources.sessionrecordings.v1.SessionRecordingR\x04item\"/\n" + "\x04item\x18\x01 \x01(\v2?.controller.api.resources.sessionrecordings.v1.SessionRecordingR\x04item\"/\n" +
"\x1dDeleteSessionRecordingRequest\x12\x0e\n" + "\x1dDeleteSessionRecordingRequest\x12\x0e\n" +
"\x02id\x18\x01 \x01(\tR\x02id\" \n" + "\x02id\x18\x01 \x01(\tR\x02id\" \n" +
"\x1eDeleteSessionRecordingResponse2\xe5\x12\n" + "\x1eDeleteSessionRecordingResponse\"k\n" +
"\x13CreateExportRequest\x126\n" +
"\x17connection_recording_id\x18\x01 \x01(\tR\x15connectionRecordingId\x12\x1c\n" +
"\tmime_type\x18\x02 \x01(\tR\tmime_type\"a\n" +
"\x14CreateExportResponse\x12I\n" +
"\x04item\x18\x01 \x01(\v25.controller.api.resources.sessionrecordings.v1.ExportR\x04item\"\"\n" +
"\x10GetExportRequest\x12\x0e\n" +
"\x02id\x18\x01 \x01(\tR\x02id\"^\n" +
"\x11GetExportResponse\x12I\n" +
"\x04item\x18\x01 \x01(\v25.controller.api.resources.sessionrecordings.v1.ExportR\x04item\"\x8b\x01\n" +
"\x12ListExportsRequest\x12\x19\n" +
"\bscope_id\x18\x01 \x01(\tR\ascopeId\x12\x1c\n" +
"\trecursive\x18\x02 \x01(\bR\trecursive\x12\x1e\n" +
"\n" +
"list_token\x18\x03 \x01(\tR\n" +
"list_token\x12\x1c\n" +
"\tpage_size\x18\x04 \x01(\rR\tpage_size\"\xa8\x02\n" +
"\x13ListExportsResponse\x12K\n" +
"\x05items\x18\x01 \x03(\v25.controller.api.resources.sessionrecordings.v1.ExportR\x05items\x12$\n" +
"\rresponse_type\x18\x02 \x01(\tR\rresponse_type\x12\x1e\n" +
"\n" +
"list_token\x18\x03 \x01(\tR\n" +
"list_token\x12\x18\n" +
"\asort_by\x18\x04 \x01(\tR\asort_by\x12\x1a\n" +
"\bsort_dir\x18\x05 \x01(\tR\bsort_dir\x12 \n" +
"\vremoved_ids\x18\x06 \x03(\tR\vremoved_ids\x12&\n" +
"\x0eest_item_count\x18\a \x01(\rR\x0eest_item_count\"%\n" +
"\x13CancelExportRequest\x12\x0e\n" +
"\x02id\x18\x01 \x01(\tR\x02id\"\x16\n" +
"\x14CancelExportResponse2\xe4 \n" +
"\x17SessionRecordingService\x12\xea\x03\n" + "\x17SessionRecordingService\x12\xea\x03\n" +
"\x13GetSessionRecording\x126.controller.api.services.v1.GetSessionRecordingRequest\x1a7.controller.api.services.v1.GetSessionRecordingResponse\"\xe1\x02\x92A\xb4\x02\x12\xb1\x02GetSessionRecording returns a stored Session recording if present. The provided request must include the Session recording ID for the Session recording being retrieved, or the ID of the Session that was recorded. If that ID is missing, malformed or reference a non existing resource, an error is returned.\x82\xd3\xe4\x93\x02#b\x04item\x12\x1b/v1/session-recordings/{id}\x12\xbe\x02\n" + "\x13GetSessionRecording\x126.controller.api.services.v1.GetSessionRecordingRequest\x1a7.controller.api.services.v1.GetSessionRecordingResponse\"\xe1\x02\x92A\xb4\x02\x12\xb1\x02GetSessionRecording returns a stored Session recording if present. The provided request must include the Session recording ID for the Session recording being retrieved, or the ID of the Session that was recorded. If that ID is missing, malformed or reference a non existing resource, an error is returned.\x82\xd3\xe4\x93\x02#b\x04item\x12\x1b/v1/session-recordings/{id}\x12\xbe\x02\n" +
"\x15ListSessionRecordings\x128.controller.api.services.v1.ListSessionRecordingsRequest\x1a9.controller.api.services.v1.ListSessionRecordingsResponse\"\xaf\x01\x92A\x8d\x01\x12\x8a\x01ListSessionRecordings lists all Session recordings. Session recordings are ordered by start_time descending (most recently started first).\x82\xd3\xe4\x93\x02\x18\x12\x16/v1/session-recordings\x12\x87\x04\n" + "\x15ListSessionRecordings\x128.controller.api.services.v1.ListSessionRecordingsRequest\x1a9.controller.api.services.v1.ListSessionRecordingsResponse\"\xaf\x01\x92A\x8d\x01\x12\x8a\x01ListSessionRecordings lists all Session recordings. Session recordings are ordered by start_time descending (most recently started first).\x82\xd3\xe4\x93\x02\x18\x12\x16/v1/session-recordings\x12\xc0\x04\n" +
"\bDownload\x12+.controller.api.services.v1.DownloadRequest\x1a\x14.google.api.HttpBody\"\xb5\x03\x92A\x85\x03\x12\x82\x03Download returns the contents of the specified resource in the specified mime type. Supports both Session ID and Session recording ID for looking up a Session recording. Supports both Connection ID and Connection recording ID to look up a Connection recording. A Channel recording ID is required to look up a Channel recording. The only supported mime type is \"application/x-asciicast\".\x82\xd3\xe4\x93\x02&\x12$/v1/session-recordings/{id}:download0\x01\x12\xc7\x02\n" + "\bDownload\x12+.controller.api.services.v1.DownloadRequest\x1a\x14.google.api.HttpBody\"\xee\x03\x92A\xbe\x03\x12\xbb\x03Download returns the contents of the specified resource in the specified mime type. Supports both Session ID and Session recording ID for looking up a Session recording. Supports both Connection ID and Connection recording ID to look up a Connection recording. A Channel recording ID is required to look up a Channel recording. A Video ID is required to look up a Video recording. Supported mime types: \"application/x-asciicast\", \"video/webm\".\x82\xd3\xe4\x93\x02&\x12$/v1/session-recordings/{id}:download0\x01\x12\xc7\x02\n" +
"\x14ReApplyStoragePolicy\x127.controller.api.services.v1.ReApplyStoragePolicyRequest\x1a8.controller.api.services.v1.ReApplyStoragePolicyResponse\"\xbb\x01\x92Ax\x12vReApplyStoragePolicy will recalculate the resultant set of policy and apply the result to the given session recording.\x82\xd3\xe4\x93\x02:b\x04item\"2/v1/session-recordings/{id}:reapply-storage-policy\x12\xd4\x01\n" + "\x14ReApplyStoragePolicy\x127.controller.api.services.v1.ReApplyStoragePolicyRequest\x1a8.controller.api.services.v1.ReApplyStoragePolicyResponse\"\xbb\x01\x92Ax\x12vReApplyStoragePolicy will recalculate the resultant set of policy and apply the result to the given session recording.\x82\xd3\xe4\x93\x02:b\x04item\"2/v1/session-recordings/{id}:reapply-storage-policy\x12\xf1\x02\n" +
"\x16DeleteSessionRecording\x129.controller.api.services.v1.DeleteSessionRecordingRequest\x1a:.controller.api.services.v1.DeleteSessionRecordingResponse\"C\x92A\x1d\x12\x1bDeletes a Session Recording\x82\xd3\xe4\x93\x02\x1d*\x1b/v1/session-recordings/{id}\x1a\xf0\x03\x92A\xec\x03\n" + "\x16DeleteSessionRecording\x129.controller.api.services.v1.DeleteSessionRecordingRequest\x1a:.controller.api.services.v1.DeleteSessionRecordingResponse\"\xdf\x01\x92A\xb8\x01\x12\xb5\x01Deletes a Session Recording when provided a Session Recording ID, or deletes a Video recording when provided a Video ID. If the ID is malformed or not provided an error is returned.\x82\xd3\xe4\x93\x02\x1d*\x1b/v1/session-recordings/{id}\x12\xd9\x03\n" +
"\fCreateExport\x12/.controller.api.services.v1.CreateExportRequest\x1a0.controller.api.services.v1.CreateExportResponse\"\xe5\x02\x92A\x99\x02\x12\x96\x02CreateExport creates an export of the specified Connection Recording in the requested mime type. The export is processed asynchronously; use GetExport to poll the status of the export. If the ID is missing, malformed, or references a non-existing resource, an error is returned.\x82\xd3\xe4\x93\x02B:\x01*b\x04item\"7/v1/session-recordings/{connection_recording_id}:export\x12\xfe\x02\n" +
"\tGetExport\x12,.controller.api.services.v1.GetExportRequest\x1a-.controller.api.services.v1.GetExportResponse\"\x93\x02\x92A\xdf\x01\x12\xdc\x01GetExport returns a stored Export if present. The provided request must include the Export ID for the Export being retrieved. If that ID is missing, malformed, or references a non-existing resource, an error is returned.\x82\xd3\xe4\x93\x02*b\x04item\x12\"/v1/session-recordings/{id}:export\x12\x8d\x02\n" +
"\vListExports\x12..controller.api.services.v1.ListExportsRequest\x1a/.controller.api.services.v1.ListExportsResponse\"\x9c\x01\x92An\x12lListExports lists all exports. Exports are ordered by created_time descending (most recently created first).\x82\xd3\xe4\x93\x02%\x12#/v1/session-recordings:list-exports\x12\xb9\x03\n" +
"\fCancelExport\x12/.controller.api.services.v1.CancelExportRequest\x1a0.controller.api.services.v1.CancelExportResponse\"\xc5\x02\x92A\x90\x02\x12\x8d\x02CancelExport cancels an Export that is in progress. The provided request must include the Export ID for the Export being cancelled. If that ID is missing, malformed, or references a non-existing resource, an error is returned. Returns the Export in its cancelled state.\x82\xd3\xe4\x93\x02+\")/v1/session-recordings/{id}:export:cancel\x1a\xf0\x03\x92A\xec\x03\n" +
"\x19Session recording service\x12\xb7\x02A session recording is a feature that enables administrators to record and play back user access sessions to target resources. It provides an audit trail of user activity and lets administrators monitor access. The session recording service provides endpoints that let you manage session recordings in Boundary.\x1a\x94\x01\n" + "\x19Session recording service\x12\xb7\x02A session recording is a feature that enables administrators to record and play back user access sessions to target resources. It provides an audit trail of user activity and lets administrators monitor access. The session recording service provides endpoints that let you manage session recordings in Boundary.\x1a\x94\x01\n" +
":Read about session recordings in the Boundary domain model\x12Vhttps://developer.hashicorp.com/boundary/docs/concepts/domain-model/session-recordingsBMZKgithub.com/hashicorp/boundary/internal/gen/controller/api/services;servicesb\x06proto3" ":Read about session recordings in the Boundary domain model\x12Vhttps://developer.hashicorp.com/boundary/docs/concepts/domain-model/session-recordingsBMZKgithub.com/hashicorp/boundary/internal/gen/controller/api/services;servicesb\x06proto3"
@@ -591,7 +1083,7 @@ func file_controller_api_services_v1_session_recording_service_proto_rawDescGZIP
return file_controller_api_services_v1_session_recording_service_proto_rawDescData return file_controller_api_services_v1_session_recording_service_proto_rawDescData
} }
var file_controller_api_services_v1_session_recording_service_proto_msgTypes = make([]protoimpl.MessageInfo, 9) var file_controller_api_services_v1_session_recording_service_proto_msgTypes = make([]protoimpl.MessageInfo, 17)
var file_controller_api_services_v1_session_recording_service_proto_goTypes = []any{ var file_controller_api_services_v1_session_recording_service_proto_goTypes = []any{
(*GetSessionRecordingRequest)(nil), // 0: controller.api.services.v1.GetSessionRecordingRequest (*GetSessionRecordingRequest)(nil), // 0: controller.api.services.v1.GetSessionRecordingRequest
(*GetSessionRecordingResponse)(nil), // 1: controller.api.services.v1.GetSessionRecordingResponse (*GetSessionRecordingResponse)(nil), // 1: controller.api.services.v1.GetSessionRecordingResponse
@@ -602,28 +1094,48 @@ var file_controller_api_services_v1_session_recording_service_proto_goTypes = []
(*ReApplyStoragePolicyResponse)(nil), // 6: controller.api.services.v1.ReApplyStoragePolicyResponse (*ReApplyStoragePolicyResponse)(nil), // 6: controller.api.services.v1.ReApplyStoragePolicyResponse
(*DeleteSessionRecordingRequest)(nil), // 7: controller.api.services.v1.DeleteSessionRecordingRequest (*DeleteSessionRecordingRequest)(nil), // 7: controller.api.services.v1.DeleteSessionRecordingRequest
(*DeleteSessionRecordingResponse)(nil), // 8: controller.api.services.v1.DeleteSessionRecordingResponse (*DeleteSessionRecordingResponse)(nil), // 8: controller.api.services.v1.DeleteSessionRecordingResponse
(*session_recordings.SessionRecording)(nil), // 9: controller.api.resources.sessionrecordings.v1.SessionRecording (*CreateExportRequest)(nil), // 9: controller.api.services.v1.CreateExportRequest
(*httpbody.HttpBody)(nil), // 10: google.api.HttpBody (*CreateExportResponse)(nil), // 10: controller.api.services.v1.CreateExportResponse
(*GetExportRequest)(nil), // 11: controller.api.services.v1.GetExportRequest
(*GetExportResponse)(nil), // 12: controller.api.services.v1.GetExportResponse
(*ListExportsRequest)(nil), // 13: controller.api.services.v1.ListExportsRequest
(*ListExportsResponse)(nil), // 14: controller.api.services.v1.ListExportsResponse
(*CancelExportRequest)(nil), // 15: controller.api.services.v1.CancelExportRequest
(*CancelExportResponse)(nil), // 16: controller.api.services.v1.CancelExportResponse
(*session_recordings.SessionRecording)(nil), // 17: controller.api.resources.sessionrecordings.v1.SessionRecording
(*session_recordings.Export)(nil), // 18: controller.api.resources.sessionrecordings.v1.Export
(*httpbody.HttpBody)(nil), // 19: google.api.HttpBody
} }
var file_controller_api_services_v1_session_recording_service_proto_depIdxs = []int32{ var file_controller_api_services_v1_session_recording_service_proto_depIdxs = []int32{
9, // 0: controller.api.services.v1.GetSessionRecordingResponse.item:type_name -> controller.api.resources.sessionrecordings.v1.SessionRecording 17, // 0: controller.api.services.v1.GetSessionRecordingResponse.item:type_name -> controller.api.resources.sessionrecordings.v1.SessionRecording
9, // 1: controller.api.services.v1.ListSessionRecordingsResponse.items:type_name -> controller.api.resources.sessionrecordings.v1.SessionRecording 17, // 1: controller.api.services.v1.ListSessionRecordingsResponse.items:type_name -> controller.api.resources.sessionrecordings.v1.SessionRecording
9, // 2: controller.api.services.v1.ReApplyStoragePolicyResponse.item:type_name -> controller.api.resources.sessionrecordings.v1.SessionRecording 17, // 2: controller.api.services.v1.ReApplyStoragePolicyResponse.item:type_name -> controller.api.resources.sessionrecordings.v1.SessionRecording
0, // 3: controller.api.services.v1.SessionRecordingService.GetSessionRecording:input_type -> controller.api.services.v1.GetSessionRecordingRequest 18, // 3: controller.api.services.v1.CreateExportResponse.item:type_name -> controller.api.resources.sessionrecordings.v1.Export
2, // 4: controller.api.services.v1.SessionRecordingService.ListSessionRecordings:input_type -> controller.api.services.v1.ListSessionRecordingsRequest 18, // 4: controller.api.services.v1.GetExportResponse.item:type_name -> controller.api.resources.sessionrecordings.v1.Export
4, // 5: controller.api.services.v1.SessionRecordingService.Download:input_type -> controller.api.services.v1.DownloadRequest 18, // 5: controller.api.services.v1.ListExportsResponse.items:type_name -> controller.api.resources.sessionrecordings.v1.Export
5, // 6: controller.api.services.v1.SessionRecordingService.ReApplyStoragePolicy:input_type -> controller.api.services.v1.ReApplyStoragePolicyRequest 0, // 6: controller.api.services.v1.SessionRecordingService.GetSessionRecording:input_type -> controller.api.services.v1.GetSessionRecordingRequest
7, // 7: controller.api.services.v1.SessionRecordingService.DeleteSessionRecording:input_type -> controller.api.services.v1.DeleteSessionRecordingRequest 2, // 7: controller.api.services.v1.SessionRecordingService.ListSessionRecordings:input_type -> controller.api.services.v1.ListSessionRecordingsRequest
1, // 8: controller.api.services.v1.SessionRecordingService.GetSessionRecording:output_type -> controller.api.services.v1.GetSessionRecordingResponse 4, // 8: controller.api.services.v1.SessionRecordingService.Download:input_type -> controller.api.services.v1.DownloadRequest
3, // 9: controller.api.services.v1.SessionRecordingService.ListSessionRecordings:output_type -> controller.api.services.v1.ListSessionRecordingsResponse 5, // 9: controller.api.services.v1.SessionRecordingService.ReApplyStoragePolicy:input_type -> controller.api.services.v1.ReApplyStoragePolicyRequest
10, // 10: controller.api.services.v1.SessionRecordingService.Download:output_type -> google.api.HttpBody 7, // 10: controller.api.services.v1.SessionRecordingService.DeleteSessionRecording:input_type -> controller.api.services.v1.DeleteSessionRecordingRequest
6, // 11: controller.api.services.v1.SessionRecordingService.ReApplyStoragePolicy:output_type -> controller.api.services.v1.ReApplyStoragePolicyResponse 9, // 11: controller.api.services.v1.SessionRecordingService.CreateExport:input_type -> controller.api.services.v1.CreateExportRequest
8, // 12: controller.api.services.v1.SessionRecordingService.DeleteSessionRecording:output_type -> controller.api.services.v1.DeleteSessionRecordingResponse 11, // 12: controller.api.services.v1.SessionRecordingService.GetExport:input_type -> controller.api.services.v1.GetExportRequest
8, // [8:13] is the sub-list for method output_type 13, // 13: controller.api.services.v1.SessionRecordingService.ListExports:input_type -> controller.api.services.v1.ListExportsRequest
3, // [3:8] is the sub-list for method input_type 15, // 14: controller.api.services.v1.SessionRecordingService.CancelExport:input_type -> controller.api.services.v1.CancelExportRequest
3, // [3:3] is the sub-list for extension type_name 1, // 15: controller.api.services.v1.SessionRecordingService.GetSessionRecording:output_type -> controller.api.services.v1.GetSessionRecordingResponse
3, // [3:3] is the sub-list for extension extendee 3, // 16: controller.api.services.v1.SessionRecordingService.ListSessionRecordings:output_type -> controller.api.services.v1.ListSessionRecordingsResponse
0, // [0:3] is the sub-list for field type_name 19, // 17: controller.api.services.v1.SessionRecordingService.Download:output_type -> google.api.HttpBody
6, // 18: controller.api.services.v1.SessionRecordingService.ReApplyStoragePolicy:output_type -> controller.api.services.v1.ReApplyStoragePolicyResponse
8, // 19: controller.api.services.v1.SessionRecordingService.DeleteSessionRecording:output_type -> controller.api.services.v1.DeleteSessionRecordingResponse
10, // 20: controller.api.services.v1.SessionRecordingService.CreateExport:output_type -> controller.api.services.v1.CreateExportResponse
12, // 21: controller.api.services.v1.SessionRecordingService.GetExport:output_type -> controller.api.services.v1.GetExportResponse
14, // 22: controller.api.services.v1.SessionRecordingService.ListExports:output_type -> controller.api.services.v1.ListExportsResponse
16, // 23: controller.api.services.v1.SessionRecordingService.CancelExport:output_type -> controller.api.services.v1.CancelExportResponse
15, // [15:24] is the sub-list for method output_type
6, // [6:15] is the sub-list for method input_type
6, // [6:6] is the sub-list for extension type_name
6, // [6:6] is the sub-list for extension extendee
0, // [0:6] is the sub-list for field type_name
} }
func init() { file_controller_api_services_v1_session_recording_service_proto_init() } func init() { file_controller_api_services_v1_session_recording_service_proto_init() }
@@ -637,7 +1149,7 @@ func file_controller_api_services_v1_session_recording_service_proto_init() {
GoPackagePath: reflect.TypeOf(x{}).PkgPath(), GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: unsafe.Slice(unsafe.StringData(file_controller_api_services_v1_session_recording_service_proto_rawDesc), len(file_controller_api_services_v1_session_recording_service_proto_rawDesc)), RawDescriptor: unsafe.Slice(unsafe.StringData(file_controller_api_services_v1_session_recording_service_proto_rawDesc), len(file_controller_api_services_v1_session_recording_service_proto_rawDesc)),
NumEnums: 0, NumEnums: 0,
NumMessages: 9, NumMessages: 17,
NumExtensions: 0, NumExtensions: 0,
NumServices: 1, NumServices: 1,
}, },
@@ -224,6 +224,164 @@ func local_request_SessionRecordingService_DeleteSessionRecording_0(ctx context.
return msg, metadata, err return msg, metadata, err
} }
func request_SessionRecordingService_CreateExport_0(ctx context.Context, marshaler runtime.Marshaler, client SessionRecordingServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var (
protoReq CreateExportRequest
metadata runtime.ServerMetadata
err error
)
if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
if req.Body != nil {
_, _ = io.Copy(io.Discard, req.Body)
}
val, ok := pathParams["connection_recording_id"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "connection_recording_id")
}
protoReq.ConnectionRecordingId, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "connection_recording_id", err)
}
msg, err := client.CreateExport(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return msg, metadata, err
}
func local_request_SessionRecordingService_CreateExport_0(ctx context.Context, marshaler runtime.Marshaler, server SessionRecordingServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var (
protoReq CreateExportRequest
metadata runtime.ServerMetadata
err error
)
if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
val, ok := pathParams["connection_recording_id"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "connection_recording_id")
}
protoReq.ConnectionRecordingId, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "connection_recording_id", err)
}
msg, err := server.CreateExport(ctx, &protoReq)
return msg, metadata, err
}
func request_SessionRecordingService_GetExport_0(ctx context.Context, marshaler runtime.Marshaler, client SessionRecordingServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var (
protoReq GetExportRequest
metadata runtime.ServerMetadata
err error
)
if req.Body != nil {
_, _ = io.Copy(io.Discard, req.Body)
}
val, ok := pathParams["id"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "id")
}
protoReq.Id, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err)
}
msg, err := client.GetExport(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return msg, metadata, err
}
func local_request_SessionRecordingService_GetExport_0(ctx context.Context, marshaler runtime.Marshaler, server SessionRecordingServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var (
protoReq GetExportRequest
metadata runtime.ServerMetadata
err error
)
val, ok := pathParams["id"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "id")
}
protoReq.Id, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err)
}
msg, err := server.GetExport(ctx, &protoReq)
return msg, metadata, err
}
var filter_SessionRecordingService_ListExports_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)}
func request_SessionRecordingService_ListExports_0(ctx context.Context, marshaler runtime.Marshaler, client SessionRecordingServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var (
protoReq ListExportsRequest
metadata runtime.ServerMetadata
)
if req.Body != nil {
_, _ = io.Copy(io.Discard, req.Body)
}
if err := req.ParseForm(); err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_SessionRecordingService_ListExports_0); err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
msg, err := client.ListExports(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return msg, metadata, err
}
func local_request_SessionRecordingService_ListExports_0(ctx context.Context, marshaler runtime.Marshaler, server SessionRecordingServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var (
protoReq ListExportsRequest
metadata runtime.ServerMetadata
)
if err := req.ParseForm(); err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_SessionRecordingService_ListExports_0); err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
msg, err := server.ListExports(ctx, &protoReq)
return msg, metadata, err
}
func request_SessionRecordingService_CancelExport_0(ctx context.Context, marshaler runtime.Marshaler, client SessionRecordingServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var (
protoReq CancelExportRequest
metadata runtime.ServerMetadata
err error
)
if req.Body != nil {
_, _ = io.Copy(io.Discard, req.Body)
}
val, ok := pathParams["id"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "id")
}
protoReq.Id, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err)
}
msg, err := client.CancelExport(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return msg, metadata, err
}
func local_request_SessionRecordingService_CancelExport_0(ctx context.Context, marshaler runtime.Marshaler, server SessionRecordingServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var (
protoReq CancelExportRequest
metadata runtime.ServerMetadata
err error
)
val, ok := pathParams["id"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "id")
}
protoReq.Id, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err)
}
msg, err := server.CancelExport(ctx, &protoReq)
return msg, metadata, err
}
// RegisterSessionRecordingServiceHandlerServer registers the http handlers for service SessionRecordingService to "mux". // RegisterSessionRecordingServiceHandlerServer registers the http handlers for service SessionRecordingService to "mux".
// UnaryRPC :call SessionRecordingServiceServer directly. // UnaryRPC :call SessionRecordingServiceServer directly.
// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. // StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906.
@@ -317,6 +475,86 @@ func RegisterSessionRecordingServiceHandlerServer(ctx context.Context, mux *runt
} }
forward_SessionRecordingService_DeleteSessionRecording_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) forward_SessionRecordingService_DeleteSessionRecording_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
}) })
mux.Handle(http.MethodPost, pattern_SessionRecordingService_CreateExport_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
var stream runtime.ServerTransportStream
ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/controller.api.services.v1.SessionRecordingService/CreateExport", runtime.WithHTTPPathPattern("/v1/session-recordings/{connection_recording_id}:export"))
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := local_request_SessionRecordingService_CreateExport_0(annotatedContext, inboundMarshaler, server, req, pathParams)
md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer())
annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md)
if err != nil {
runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
return
}
forward_SessionRecordingService_CreateExport_0(annotatedContext, mux, outboundMarshaler, w, req, response_SessionRecordingService_CreateExport_0{resp.(*CreateExportResponse)}, mux.GetForwardResponseOptions()...)
})
mux.Handle(http.MethodGet, pattern_SessionRecordingService_GetExport_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
var stream runtime.ServerTransportStream
ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/controller.api.services.v1.SessionRecordingService/GetExport", runtime.WithHTTPPathPattern("/v1/session-recordings/{id}:export"))
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := local_request_SessionRecordingService_GetExport_0(annotatedContext, inboundMarshaler, server, req, pathParams)
md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer())
annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md)
if err != nil {
runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
return
}
forward_SessionRecordingService_GetExport_0(annotatedContext, mux, outboundMarshaler, w, req, response_SessionRecordingService_GetExport_0{resp.(*GetExportResponse)}, mux.GetForwardResponseOptions()...)
})
mux.Handle(http.MethodGet, pattern_SessionRecordingService_ListExports_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
var stream runtime.ServerTransportStream
ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/controller.api.services.v1.SessionRecordingService/ListExports", runtime.WithHTTPPathPattern("/v1/session-recordings:list-exports"))
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := local_request_SessionRecordingService_ListExports_0(annotatedContext, inboundMarshaler, server, req, pathParams)
md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer())
annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md)
if err != nil {
runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
return
}
forward_SessionRecordingService_ListExports_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle(http.MethodPost, pattern_SessionRecordingService_CancelExport_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
var stream runtime.ServerTransportStream
ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/controller.api.services.v1.SessionRecordingService/CancelExport", runtime.WithHTTPPathPattern("/v1/session-recordings/{id}:export:cancel"))
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := local_request_SessionRecordingService_CancelExport_0(annotatedContext, inboundMarshaler, server, req, pathParams)
md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer())
annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md)
if err != nil {
runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
return
}
forward_SessionRecordingService_CancelExport_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
return nil return nil
} }
@@ -442,6 +680,74 @@ func RegisterSessionRecordingServiceHandlerClient(ctx context.Context, mux *runt
} }
forward_SessionRecordingService_DeleteSessionRecording_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) forward_SessionRecordingService_DeleteSessionRecording_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
}) })
mux.Handle(http.MethodPost, pattern_SessionRecordingService_CreateExport_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/controller.api.services.v1.SessionRecordingService/CreateExport", runtime.WithHTTPPathPattern("/v1/session-recordings/{connection_recording_id}:export"))
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := request_SessionRecordingService_CreateExport_0(annotatedContext, inboundMarshaler, client, req, pathParams)
annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md)
if err != nil {
runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
return
}
forward_SessionRecordingService_CreateExport_0(annotatedContext, mux, outboundMarshaler, w, req, response_SessionRecordingService_CreateExport_0{resp.(*CreateExportResponse)}, mux.GetForwardResponseOptions()...)
})
mux.Handle(http.MethodGet, pattern_SessionRecordingService_GetExport_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/controller.api.services.v1.SessionRecordingService/GetExport", runtime.WithHTTPPathPattern("/v1/session-recordings/{id}:export"))
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := request_SessionRecordingService_GetExport_0(annotatedContext, inboundMarshaler, client, req, pathParams)
annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md)
if err != nil {
runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
return
}
forward_SessionRecordingService_GetExport_0(annotatedContext, mux, outboundMarshaler, w, req, response_SessionRecordingService_GetExport_0{resp.(*GetExportResponse)}, mux.GetForwardResponseOptions()...)
})
mux.Handle(http.MethodGet, pattern_SessionRecordingService_ListExports_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/controller.api.services.v1.SessionRecordingService/ListExports", runtime.WithHTTPPathPattern("/v1/session-recordings:list-exports"))
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := request_SessionRecordingService_ListExports_0(annotatedContext, inboundMarshaler, client, req, pathParams)
annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md)
if err != nil {
runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
return
}
forward_SessionRecordingService_ListExports_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle(http.MethodPost, pattern_SessionRecordingService_CancelExport_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/controller.api.services.v1.SessionRecordingService/CancelExport", runtime.WithHTTPPathPattern("/v1/session-recordings/{id}:export:cancel"))
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := request_SessionRecordingService_CancelExport_0(annotatedContext, inboundMarshaler, client, req, pathParams)
annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md)
if err != nil {
runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
return
}
forward_SessionRecordingService_CancelExport_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
return nil return nil
} }
@@ -463,12 +769,34 @@ func (m response_SessionRecordingService_ReApplyStoragePolicy_0) XXX_ResponseBod
return response.Item return response.Item
} }
type response_SessionRecordingService_CreateExport_0 struct {
*CreateExportResponse
}
func (m response_SessionRecordingService_CreateExport_0) XXX_ResponseBody() interface{} {
response := m.CreateExportResponse
return response.Item
}
type response_SessionRecordingService_GetExport_0 struct {
*GetExportResponse
}
func (m response_SessionRecordingService_GetExport_0) XXX_ResponseBody() interface{} {
response := m.GetExportResponse
return response.Item
}
var ( var (
pattern_SessionRecordingService_GetSessionRecording_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2}, []string{"v1", "session-recordings", "id"}, "")) pattern_SessionRecordingService_GetSessionRecording_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2}, []string{"v1", "session-recordings", "id"}, ""))
pattern_SessionRecordingService_ListSessionRecordings_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"v1", "session-recordings"}, "")) pattern_SessionRecordingService_ListSessionRecordings_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"v1", "session-recordings"}, ""))
pattern_SessionRecordingService_Download_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2}, []string{"v1", "session-recordings", "id"}, "download")) pattern_SessionRecordingService_Download_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2}, []string{"v1", "session-recordings", "id"}, "download"))
pattern_SessionRecordingService_ReApplyStoragePolicy_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2}, []string{"v1", "session-recordings", "id"}, "reapply-storage-policy")) pattern_SessionRecordingService_ReApplyStoragePolicy_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2}, []string{"v1", "session-recordings", "id"}, "reapply-storage-policy"))
pattern_SessionRecordingService_DeleteSessionRecording_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2}, []string{"v1", "session-recordings", "id"}, "")) pattern_SessionRecordingService_DeleteSessionRecording_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2}, []string{"v1", "session-recordings", "id"}, ""))
pattern_SessionRecordingService_CreateExport_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2}, []string{"v1", "session-recordings", "connection_recording_id"}, "export"))
pattern_SessionRecordingService_GetExport_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2}, []string{"v1", "session-recordings", "id"}, "export"))
pattern_SessionRecordingService_ListExports_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"v1", "session-recordings"}, "list-exports"))
pattern_SessionRecordingService_CancelExport_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2}, []string{"v1", "session-recordings", "id"}, "export:cancel"))
) )
var ( var (
@@ -477,4 +805,8 @@ var (
forward_SessionRecordingService_Download_0 = runtime.ForwardResponseStream forward_SessionRecordingService_Download_0 = runtime.ForwardResponseStream
forward_SessionRecordingService_ReApplyStoragePolicy_0 = runtime.ForwardResponseMessage forward_SessionRecordingService_ReApplyStoragePolicy_0 = runtime.ForwardResponseMessage
forward_SessionRecordingService_DeleteSessionRecording_0 = runtime.ForwardResponseMessage forward_SessionRecordingService_DeleteSessionRecording_0 = runtime.ForwardResponseMessage
forward_SessionRecordingService_CreateExport_0 = runtime.ForwardResponseMessage
forward_SessionRecordingService_GetExport_0 = runtime.ForwardResponseMessage
forward_SessionRecordingService_ListExports_0 = runtime.ForwardResponseMessage
forward_SessionRecordingService_CancelExport_0 = runtime.ForwardResponseMessage
) )
@@ -28,6 +28,10 @@ const (
SessionRecordingService_Download_FullMethodName = "/controller.api.services.v1.SessionRecordingService/Download" SessionRecordingService_Download_FullMethodName = "/controller.api.services.v1.SessionRecordingService/Download"
SessionRecordingService_ReApplyStoragePolicy_FullMethodName = "/controller.api.services.v1.SessionRecordingService/ReApplyStoragePolicy" SessionRecordingService_ReApplyStoragePolicy_FullMethodName = "/controller.api.services.v1.SessionRecordingService/ReApplyStoragePolicy"
SessionRecordingService_DeleteSessionRecording_FullMethodName = "/controller.api.services.v1.SessionRecordingService/DeleteSessionRecording" SessionRecordingService_DeleteSessionRecording_FullMethodName = "/controller.api.services.v1.SessionRecordingService/DeleteSessionRecording"
SessionRecordingService_CreateExport_FullMethodName = "/controller.api.services.v1.SessionRecordingService/CreateExport"
SessionRecordingService_GetExport_FullMethodName = "/controller.api.services.v1.SessionRecordingService/GetExport"
SessionRecordingService_ListExports_FullMethodName = "/controller.api.services.v1.SessionRecordingService/ListExports"
SessionRecordingService_CancelExport_FullMethodName = "/controller.api.services.v1.SessionRecordingService/CancelExport"
) )
// SessionRecordingServiceClient is the client API for SessionRecordingService service. // SessionRecordingServiceClient is the client API for SessionRecordingService service.
@@ -46,16 +50,35 @@ type SessionRecordingServiceClient interface {
// Supports both Session ID and Session recording ID for looking up a Session recording. // Supports both Session ID and Session recording ID for looking up a Session recording.
// Supports both Connection ID and Connection recording ID to look up a Connection recording. // Supports both Connection ID and Connection recording ID to look up a Connection recording.
// A Channel recording ID is required to look up a Channel recording. // A Channel recording ID is required to look up a Channel recording.
// The only supported mime type is "application/x-asciicast". // A Video ID is required to look up a Video recording.
// Supported mime types: "application/x-asciicast", "video/webm"
Download(ctx context.Context, in *DownloadRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[httpbody.HttpBody], error) Download(ctx context.Context, in *DownloadRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[httpbody.HttpBody], error)
// ReApplyStoragePolicy calculates the resultant set of policy for a given session recording // ReApplyStoragePolicy calculates the resultant set of policy for a given session recording
// and updates the retain until and delete after values. The provided request // and updates the retain until and delete after values. The provided request
// must include the Session recording ID for the Session recording to be updated. If that ID // must include the Session recording ID for the Session recording to be updated. If that ID
// is missing, malformed or reference a non existing resource, an error is returned. // is missing, malformed or reference a non existing resource, an error is returned.
ReApplyStoragePolicy(ctx context.Context, in *ReApplyStoragePolicyRequest, opts ...grpc.CallOption) (*ReApplyStoragePolicyResponse, error) ReApplyStoragePolicy(ctx context.Context, in *ReApplyStoragePolicyRequest, opts ...grpc.CallOption) (*ReApplyStoragePolicyResponse, error)
// DeleteSessionRecording removes a Session Recording from Boundary. If the Session Recording id // DeleteSessionRecording deletes a Session Recording or Video recording.
// is malformed or not provided an error is returned. // Supports Session Recording ID to delete a Session Recording.
// Supports Video ID to delete a Video recording.
// If the Session Recording id is malformed or not provided an error is returned.
DeleteSessionRecording(ctx context.Context, in *DeleteSessionRecordingRequest, opts ...grpc.CallOption) (*DeleteSessionRecordingResponse, error) DeleteSessionRecording(ctx context.Context, in *DeleteSessionRecordingRequest, opts ...grpc.CallOption) (*DeleteSessionRecordingResponse, error)
// CreateExport creates an export of the specified Connection Recording in the requested mime type.
// The provided request must include the Connection Recording ID. The export is processed
// asynchronously; use GetExport to poll the status of the export. If the ID is missing,
// malformed, or references a non-existing resource, an error is returned.
CreateExport(ctx context.Context, in *CreateExportRequest, opts ...grpc.CallOption) (*CreateExportResponse, error)
// GetExport returns a stored Export if present. The provided request must include the Export ID
// for the Export being retrieved. If that ID is missing, malformed, or references a non-existing
// resource, an error is returned.
GetExport(ctx context.Context, in *GetExportRequest, opts ...grpc.CallOption) (*GetExportResponse, error)
// ListExports lists all Exports. Exports are ordered by create time descending
// (most recently created first).
ListExports(ctx context.Context, in *ListExportsRequest, opts ...grpc.CallOption) (*ListExportsResponse, error)
// CancelExport cancels an Export that is in progress. The provided request must include the
// Export ID for the Export being cancelled. If that ID is missing, malformed, or references a
// non-existing resource, an error is returned. Returns the Export in its cancelled state.
CancelExport(ctx context.Context, in *CancelExportRequest, opts ...grpc.CallOption) (*CancelExportResponse, error)
} }
type sessionRecordingServiceClient struct { type sessionRecordingServiceClient struct {
@@ -125,6 +148,46 @@ func (c *sessionRecordingServiceClient) DeleteSessionRecording(ctx context.Conte
return out, nil return out, nil
} }
func (c *sessionRecordingServiceClient) CreateExport(ctx context.Context, in *CreateExportRequest, opts ...grpc.CallOption) (*CreateExportResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(CreateExportResponse)
err := c.cc.Invoke(ctx, SessionRecordingService_CreateExport_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *sessionRecordingServiceClient) GetExport(ctx context.Context, in *GetExportRequest, opts ...grpc.CallOption) (*GetExportResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(GetExportResponse)
err := c.cc.Invoke(ctx, SessionRecordingService_GetExport_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *sessionRecordingServiceClient) ListExports(ctx context.Context, in *ListExportsRequest, opts ...grpc.CallOption) (*ListExportsResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(ListExportsResponse)
err := c.cc.Invoke(ctx, SessionRecordingService_ListExports_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *sessionRecordingServiceClient) CancelExport(ctx context.Context, in *CancelExportRequest, opts ...grpc.CallOption) (*CancelExportResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(CancelExportResponse)
err := c.cc.Invoke(ctx, SessionRecordingService_CancelExport_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
// SessionRecordingServiceServer is the server API for SessionRecordingService service. // SessionRecordingServiceServer is the server API for SessionRecordingService service.
// All implementations must embed UnimplementedSessionRecordingServiceServer // All implementations must embed UnimplementedSessionRecordingServiceServer
// for forward compatibility. // for forward compatibility.
@@ -141,16 +204,35 @@ type SessionRecordingServiceServer interface {
// Supports both Session ID and Session recording ID for looking up a Session recording. // Supports both Session ID and Session recording ID for looking up a Session recording.
// Supports both Connection ID and Connection recording ID to look up a Connection recording. // Supports both Connection ID and Connection recording ID to look up a Connection recording.
// A Channel recording ID is required to look up a Channel recording. // A Channel recording ID is required to look up a Channel recording.
// The only supported mime type is "application/x-asciicast". // A Video ID is required to look up a Video recording.
// Supported mime types: "application/x-asciicast", "video/webm"
Download(*DownloadRequest, grpc.ServerStreamingServer[httpbody.HttpBody]) error Download(*DownloadRequest, grpc.ServerStreamingServer[httpbody.HttpBody]) error
// ReApplyStoragePolicy calculates the resultant set of policy for a given session recording // ReApplyStoragePolicy calculates the resultant set of policy for a given session recording
// and updates the retain until and delete after values. The provided request // and updates the retain until and delete after values. The provided request
// must include the Session recording ID for the Session recording to be updated. If that ID // must include the Session recording ID for the Session recording to be updated. If that ID
// is missing, malformed or reference a non existing resource, an error is returned. // is missing, malformed or reference a non existing resource, an error is returned.
ReApplyStoragePolicy(context.Context, *ReApplyStoragePolicyRequest) (*ReApplyStoragePolicyResponse, error) ReApplyStoragePolicy(context.Context, *ReApplyStoragePolicyRequest) (*ReApplyStoragePolicyResponse, error)
// DeleteSessionRecording removes a Session Recording from Boundary. If the Session Recording id // DeleteSessionRecording deletes a Session Recording or Video recording.
// is malformed or not provided an error is returned. // Supports Session Recording ID to delete a Session Recording.
// Supports Video ID to delete a Video recording.
// If the Session Recording id is malformed or not provided an error is returned.
DeleteSessionRecording(context.Context, *DeleteSessionRecordingRequest) (*DeleteSessionRecordingResponse, error) DeleteSessionRecording(context.Context, *DeleteSessionRecordingRequest) (*DeleteSessionRecordingResponse, error)
// CreateExport creates an export of the specified Connection Recording in the requested mime type.
// The provided request must include the Connection Recording ID. The export is processed
// asynchronously; use GetExport to poll the status of the export. If the ID is missing,
// malformed, or references a non-existing resource, an error is returned.
CreateExport(context.Context, *CreateExportRequest) (*CreateExportResponse, error)
// GetExport returns a stored Export if present. The provided request must include the Export ID
// for the Export being retrieved. If that ID is missing, malformed, or references a non-existing
// resource, an error is returned.
GetExport(context.Context, *GetExportRequest) (*GetExportResponse, error)
// ListExports lists all Exports. Exports are ordered by create time descending
// (most recently created first).
ListExports(context.Context, *ListExportsRequest) (*ListExportsResponse, error)
// CancelExport cancels an Export that is in progress. The provided request must include the
// Export ID for the Export being cancelled. If that ID is missing, malformed, or references a
// non-existing resource, an error is returned. Returns the Export in its cancelled state.
CancelExport(context.Context, *CancelExportRequest) (*CancelExportResponse, error)
mustEmbedUnimplementedSessionRecordingServiceServer() mustEmbedUnimplementedSessionRecordingServiceServer()
} }
@@ -176,6 +258,18 @@ func (UnimplementedSessionRecordingServiceServer) ReApplyStoragePolicy(context.C
func (UnimplementedSessionRecordingServiceServer) DeleteSessionRecording(context.Context, *DeleteSessionRecordingRequest) (*DeleteSessionRecordingResponse, error) { func (UnimplementedSessionRecordingServiceServer) DeleteSessionRecording(context.Context, *DeleteSessionRecordingRequest) (*DeleteSessionRecordingResponse, error) {
return nil, status.Error(codes.Unimplemented, "method DeleteSessionRecording not implemented") return nil, status.Error(codes.Unimplemented, "method DeleteSessionRecording not implemented")
} }
func (UnimplementedSessionRecordingServiceServer) CreateExport(context.Context, *CreateExportRequest) (*CreateExportResponse, error) {
return nil, status.Error(codes.Unimplemented, "method CreateExport not implemented")
}
func (UnimplementedSessionRecordingServiceServer) GetExport(context.Context, *GetExportRequest) (*GetExportResponse, error) {
return nil, status.Error(codes.Unimplemented, "method GetExport not implemented")
}
func (UnimplementedSessionRecordingServiceServer) ListExports(context.Context, *ListExportsRequest) (*ListExportsResponse, error) {
return nil, status.Error(codes.Unimplemented, "method ListExports not implemented")
}
func (UnimplementedSessionRecordingServiceServer) CancelExport(context.Context, *CancelExportRequest) (*CancelExportResponse, error) {
return nil, status.Error(codes.Unimplemented, "method CancelExport not implemented")
}
func (UnimplementedSessionRecordingServiceServer) mustEmbedUnimplementedSessionRecordingServiceServer() { func (UnimplementedSessionRecordingServiceServer) mustEmbedUnimplementedSessionRecordingServiceServer() {
} }
func (UnimplementedSessionRecordingServiceServer) testEmbeddedByValue() {} func (UnimplementedSessionRecordingServiceServer) testEmbeddedByValue() {}
@@ -281,6 +375,78 @@ func _SessionRecordingService_DeleteSessionRecording_Handler(srv interface{}, ct
return interceptor(ctx, in, info, handler) return interceptor(ctx, in, info, handler)
} }
func _SessionRecordingService_CreateExport_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(CreateExportRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(SessionRecordingServiceServer).CreateExport(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: SessionRecordingService_CreateExport_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(SessionRecordingServiceServer).CreateExport(ctx, req.(*CreateExportRequest))
}
return interceptor(ctx, in, info, handler)
}
func _SessionRecordingService_GetExport_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(GetExportRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(SessionRecordingServiceServer).GetExport(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: SessionRecordingService_GetExport_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(SessionRecordingServiceServer).GetExport(ctx, req.(*GetExportRequest))
}
return interceptor(ctx, in, info, handler)
}
func _SessionRecordingService_ListExports_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(ListExportsRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(SessionRecordingServiceServer).ListExports(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: SessionRecordingService_ListExports_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(SessionRecordingServiceServer).ListExports(ctx, req.(*ListExportsRequest))
}
return interceptor(ctx, in, info, handler)
}
func _SessionRecordingService_CancelExport_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(CancelExportRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(SessionRecordingServiceServer).CancelExport(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: SessionRecordingService_CancelExport_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(SessionRecordingServiceServer).CancelExport(ctx, req.(*CancelExportRequest))
}
return interceptor(ctx, in, info, handler)
}
// SessionRecordingService_ServiceDesc is the grpc.ServiceDesc for SessionRecordingService service. // SessionRecordingService_ServiceDesc is the grpc.ServiceDesc for SessionRecordingService service.
// It's only intended for direct use with grpc.RegisterService, // It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy) // and not to be introspected or modified (even as a copy)
@@ -304,6 +470,22 @@ var SessionRecordingService_ServiceDesc = grpc.ServiceDesc{
MethodName: "DeleteSessionRecording", MethodName: "DeleteSessionRecording",
Handler: _SessionRecordingService_DeleteSessionRecording_Handler, Handler: _SessionRecordingService_DeleteSessionRecording_Handler,
}, },
{
MethodName: "CreateExport",
Handler: _SessionRecordingService_CreateExport_Handler,
},
{
MethodName: "GetExport",
Handler: _SessionRecordingService_GetExport_Handler,
},
{
MethodName: "ListExports",
Handler: _SessionRecordingService_ListExports_Handler,
},
{
MethodName: "CancelExport",
Handler: _SessionRecordingService_CancelExport_Handler,
},
}, },
Streams: []grpc.StreamDesc{ Streams: []grpc.StreamDesc{
{ {
@@ -44,6 +44,29 @@ message ChannelRecording {
// MimeTypes define the mime types that can // MimeTypes define the mime types that can
// be used to consume the recording of this Channel. // be used to consume the recording of this Channel.
// The only supported mime type is "application/x-asciicast". // The only supported mime type is "application/x-asciicast".
// Deprecated: This field has been moved to SSH-specific attributes and will be removed
// entirely in a future Boundary version.
repeated string mime_types = 9 [
json_name = "mime_types",
deprecated = true
]; // @gotags: class:"public" eventstream:"observation"
// The detailed state of the channel recording.
RecordingState recording_state = 23 [json_name = "recording_state"]; // @gotags: class:"public" eventstream:"observation"
oneof attrs {
// The attributes that are applicable for the specific Channel Recording type.
google.protobuf.Struct attributes = 10 [(custom_options.v1.subtype) = "default"];
SshChannelRecording ssh_channel_recording = 11 [
(google.api.field_visibility).restriction = "INTERNAL",
(custom_options.v1.subtype) = "ssh_channel_recording"
];
}
}
// SshChannelRecording contains SSH-specific attributes for a channel recording.
message SshChannelRecording {
repeated string mime_types = 9 [json_name = "mime_types"]; // @gotags: class:"public" eventstream:"observation" repeated string mime_types = 9 [json_name = "mime_types"]; // @gotags: class:"public" eventstream:"observation"
} }
@@ -83,6 +106,17 @@ message ConnectionRecording {
// Optionally, the channels used in this Connection, // Optionally, the channels used in this Connection,
// if it is using a multiplexed protocol, such as SSH. // if it is using a multiplexed protocol, such as SSH.
repeated ChannelRecording channel_recordings = 10 [json_name = "channel_recordings"]; repeated ChannelRecording channel_recordings = 10 [json_name = "channel_recordings"];
// The detailed state of the connection recording.
RecordingState recording_state = 11 [json_name = "recording_state"]; // @gotags: class:"public" eventstream:"observation"
// Optionally, exports that may have been created for this Connection
// Recording.
repeated Export exports = 12 [json_name = "exports"]; // @gotags: class:"public"
// Optionally, videos that may have been recorded for this Connection
// Recording.
repeated Video videos = 13 [json_name = "videos"]; // @gotags: class:"public"
} }
// User describes an authenticated user in Boundary. // User describes an authenticated user in Boundary.
@@ -216,6 +250,10 @@ message Target {
(google.api.field_visibility).restriction = "INTERNAL", (google.api.field_visibility).restriction = "INTERNAL",
(custom_options.v1.subtype) = "ssh" (custom_options.v1.subtype) = "ssh"
]; ];
RdpTargetAttributes rdp_target_attributes = 13 [
(google.api.field_visibility).restriction = "INTERNAL",
(custom_options.v1.subtype) = "rdp"
];
} }
} }
@@ -228,6 +266,15 @@ message SshTargetAttributes {
uint32 default_client_port = 2 [json_name = "default_client_port"]; // @gotags: class:"public" uint32 default_client_port = 2 [json_name = "default_client_port"]; // @gotags: class:"public"
} }
// RdpTargetAttributes contains attributes relevant to Targets of type "rdp"
message RdpTargetAttributes {
// The default RDP port used when connecting to the endpoint.
uint32 default_port = 1 [json_name = "default_port"]; // @gotags: class:"public"
// The default TCP port listened on by the client's local proxy.
uint32 default_client_port = 2 [json_name = "default_client_port"]; // @gotags: class:"public"
}
// CredentialStore contains all fields related to a Credential Store resource // CredentialStore contains all fields related to a Credential Store resource
message CredentialStore { message CredentialStore {
// The ID of the Credential Store. // The ID of the Credential Store.
@@ -312,6 +359,10 @@ message Credential {
(google.api.field_visibility).restriction = "INTERNAL", (google.api.field_visibility).restriction = "INTERNAL",
(custom_options.v1.subtype) = "password" (custom_options.v1.subtype) = "password"
]; ];
UsernamePasswordDomainCredentialAttributes username_password_domain_attributes = 12 [
(google.api.field_visibility).restriction = "INTERNAL",
(custom_options.v1.subtype) = "username_password_domain"
];
} }
} }
@@ -324,6 +375,18 @@ message UsernamePasswordCredentialAttributes {
string password_hmac = 2; // @gotags: class:"public" string password_hmac = 2; // @gotags: class:"public"
} }
// The attributes of a UsernamePasswordDomain Credential.
message UsernamePasswordDomainCredentialAttributes {
// The username associated with the credential.
string username = 1; // @gotags: class:"sensitive"
// The hmac value of the password.
string password_hmac = 2; // @gotags: class:"public"
// The domain associated with the credential.
string domain = 3; // @gotags: class:"public"
}
// The attributes of a SshPrivateKey Credential. // The attributes of a SshPrivateKey Credential.
message SshPrivateKeyCredentialAttributes { message SshPrivateKeyCredentialAttributes {
// The username associated with the credential. // The username associated with the credential.
@@ -383,6 +446,10 @@ message CredentialLibrary {
(google.api.field_visibility).restriction = "INTERNAL", (google.api.field_visibility).restriction = "INTERNAL",
(custom_options.v1.subtype) = "vault-ssh-certificate" (custom_options.v1.subtype) = "vault-ssh-certificate"
]; ];
VaultLdapCredentialLibraryAttributes vault_ldap_credential_library_attributes = 11 [
(google.api.field_visibility).restriction = "INTERNAL",
(custom_options.v1.subtype) = "vault-ldap"
];
} }
} }
@@ -398,6 +465,12 @@ message VaultCredentialLibraryAttributes {
string http_request_body = 3; // @gotags: `class:"secret"` string http_request_body = 3; // @gotags: `class:"secret"`
} }
// The attributes of a Vault typed LDAP Credential Library.
message VaultLdapCredentialLibraryAttributes {
// The path in Vault to request credentials from.
string path = 1; // @gotags: class:"public"
}
// The attributes of a vault SSH Certificate Credential Library. // The attributes of a vault SSH Certificate Credential Library.
message VaultSSHCertificateCredentialLibraryAttributes { message VaultSSHCertificateCredentialLibraryAttributes {
// The path in Vault to request credentials from. // The path in Vault to request credentials from.
@@ -444,6 +517,59 @@ message ValuesAtTime {
repeated CredentialLibrary credential_libraries = 5 [json_name = "credential_libraries"]; repeated CredentialLibrary credential_libraries = 5 [json_name = "credential_libraries"];
} }
// RecordingState contain information about the state of a recording.
message RecordingState {
// Information about the storage state of the recording.
string storage_state = 1; // @gotags: class:"public"
// Information about the syncing error details of the recording.
string syncing_error_details = 2; // @gotags: class:"public"
// Information about the verification error details of the recording.
string verification_error_details = 3; // @gotags: class:"public"
}
// Export contains information about the export of a session recording.
message Export {
// The ID of the Export.
string id = 10; // @gotags: class:"public"
// The scope that the Export is in. This is inferred from the storage bucket
// associated with the session recording.
resources.scopes.v1.ScopeInfo scope = 20; // @gotags: class:"public"
// The mime type of the Export.
string mime_type = 30; // @gotags: class:"public" eventstream:"observation"
// The current state of the Export.
string state = 40; // @gotags: class:"public" eventstream:"observation"
// The export's current progress.
uint32 progress_percent = 50; // @gotags: class:"public" eventstream:"observation"
// The ID of the worker processing the Export.
string worker_id = 60; // @gotags: class:"public" eventstream:"observation"
// The time the Export was created.
google.protobuf.Timestamp created_time = 70; // @gotags: class:"public" eventstream:"observation"
// The time of the most recent update to the Export.
google.protobuf.Timestamp updated_time = 80; // @gotags: class:"public" eventstream:"observation"
// The version of the Export.
uint32 version = 90; // @gotags: `class:"public"`
// The ID of the Connection Recording being exported.
string connection_recording_id = 100; // @gotags: class:"public" eventstream:"observation"
// Any error encountered during the Export, if the Export failed.
string error = 110; // @gotags: class:"public"
// The available actions on this resource for this user.
repeated string authorized_actions = 300 [json_name = "authorized_actions"]; // @gotags: class:"public"
}
// Video contains information about the video recording of a Session Recording.
message Video {
// The ID of the Video.
string id = 10; // @gotags: class:"public"
// The time the Video was created.
google.protobuf.Timestamp created_time = 20; // @gotags: class:"public" eventstream:"observation"
// The duration of the Video in seconds.
uint64 length_seconds = 30; // @gotags: class:"public" eventstream:"observation"
// The size of the Video in bytes.
uint64 size_bytes = 40; // @gotags: class:"public" eventstream:"observation"
}
// SessionRecording contains information about the recording of a Session. // SessionRecording contains information about the recording of a Session.
message SessionRecording { message SessionRecording {
// The ID of the Session recording. // The ID of the Session recording.
@@ -490,10 +616,16 @@ message SessionRecording {
// The current state of the session recording. One of // The current state of the session recording. One of
// "started", "available" and "unknown". // "started", "available" and "unknown".
//
// Note: this field will eventually be deprecated two release after 1.0.0
// in favor of the availability field.
string state = 13; // @gotags: class:"public" eventstream:"observation" string state = 13; // @gotags: class:"public" eventstream:"observation"
// Any error seen during the closing of the session recording. // Any error seen during the closing of the session recording.
// Currently only set if state is "unknown". // Currently only set if state is "unknown".
//
// Note: this field will eventually be deprecated two release after 1.0.0
// in favor of the error details contained in the recording_state field.
string error_details = 14; // @gotags: class:"public" string error_details = 14; // @gotags: class:"public"
// MimeTypes define the mime types that can // MimeTypes define the mime types that can
@@ -520,4 +652,10 @@ message SessionRecording {
// The time a session recording is scheduled to be automatically deleted. // The time a session recording is scheduled to be automatically deleted.
google.protobuf.Timestamp delete_after = 21 [json_name = "delete_after"]; // @gotags: class:"public" eventstream:"observation" google.protobuf.Timestamp delete_after = 21 [json_name = "delete_after"]; // @gotags: class:"public" eventstream:"observation"
// The availability of the session recording. One of "available" or "not available".
string availability = 22 [json_name = "availability"]; // @gotags: class:"public" eventstream:"observation"
// The detailed state of the session recording.
RecordingState recording_state = 23 [json_name = "recording_state"]; // @gotags: class:"public" eventstream:"observation"
} }
@@ -350,6 +350,26 @@ message RdpTargetAttributes {
that: "DefaultClientPort" that: "DefaultClientPort"
} }
]; // @gotags: `class:"public"` ]; // @gotags: `class:"public"`
// PublicId of the storage bucket associated with the target
google.protobuf.StringValue storage_bucket_id = 30 [
json_name = "storage_bucket_id",
(custom_options.v1.generate_sdk_option) = true,
(custom_options.v1.mask_mapping) = {
this: "attributes.storage_bucket_id"
that: "StorageBucketId"
}
]; // @gotags: `class:"public" eventstream:"observation"`
// A boolean indicating if session recording has been enabled
google.protobuf.BoolValue enable_session_recording = 40 [
json_name = "enable_session_recording",
(custom_options.v1.generate_sdk_option) = true,
(custom_options.v1.mask_mapping) = {
this: "attributes.enable_session_recording"
that: "EnableSessionRecording"
}
]; // @gotags: `class:"public" eventstream:"observation"`
} }
// WorkerInfo contains information about workers, returned in to the client in SessionAuthorization // WorkerInfo contains information about workers, returned in to the client in SessionAuthorization
@@ -20,8 +20,8 @@ service SessionRecordingService {
"It provides an audit trail of user activity and lets administrators monitor access. " "It provides an audit trail of user activity and lets administrators monitor access. "
"The session recording service provides endpoints that let you manage session recordings in Boundary." "The session recording service provides endpoints that let you manage session recordings in Boundary."
external_docs: { external_docs: {
url: "https://developer.hashicorp.com/boundary/docs/concepts/domain-model/session-recordings"; url: "https://developer.hashicorp.com/boundary/docs/concepts/domain-model/session-recordings"
description: "Read about session recordings in the Boundary domain model"; description: "Read about session recordings in the Boundary domain model"
} }
}; };
@@ -48,10 +48,11 @@ service SessionRecordingService {
// Supports both Session ID and Session recording ID for looking up a Session recording. // Supports both Session ID and Session recording ID for looking up a Session recording.
// Supports both Connection ID and Connection recording ID to look up a Connection recording. // Supports both Connection ID and Connection recording ID to look up a Connection recording.
// A Channel recording ID is required to look up a Channel recording. // A Channel recording ID is required to look up a Channel recording.
// The only supported mime type is "application/x-asciicast". // A Video ID is required to look up a Video recording.
// Supported mime types: "application/x-asciicast", "video/webm"
rpc Download(DownloadRequest) returns (stream google.api.HttpBody) { rpc Download(DownloadRequest) returns (stream google.api.HttpBody) {
option (google.api.http) = {get: "/v1/session-recordings/{id}:download"}; option (google.api.http) = {get: "/v1/session-recordings/{id}:download"};
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {summary: "Download returns the contents of the specified resource in the specified mime type. Supports both Session ID and Session recording ID for looking up a Session recording. Supports both Connection ID and Connection recording ID to look up a Connection recording. A Channel recording ID is required to look up a Channel recording. The only supported mime type is \"application/x-asciicast\"."}; option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {summary: "Download returns the contents of the specified resource in the specified mime type. Supports both Session ID and Session recording ID for looking up a Session recording. Supports both Connection ID and Connection recording ID to look up a Connection recording. A Channel recording ID is required to look up a Channel recording. A Video ID is required to look up a Video recording. Supported mime types: \"application/x-asciicast\", \"video/webm\"."};
} }
// ReApplyStoragePolicy calculates the resultant set of policy for a given session recording // ReApplyStoragePolicy calculates the resultant set of policy for a given session recording
@@ -66,11 +67,52 @@ service SessionRecordingService {
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {summary: "ReApplyStoragePolicy will recalculate the resultant set of policy and apply the result to the given session recording."}; option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {summary: "ReApplyStoragePolicy will recalculate the resultant set of policy and apply the result to the given session recording."};
} }
// DeleteSessionRecording removes a Session Recording from Boundary. If the Session Recording id // DeleteSessionRecording deletes a Session Recording or Video recording.
// is malformed or not provided an error is returned. // Supports Session Recording ID to delete a Session Recording.
// Supports Video ID to delete a Video recording.
// If the Session Recording id is malformed or not provided an error is returned.
rpc DeleteSessionRecording(DeleteSessionRecordingRequest) returns (DeleteSessionRecordingResponse) { rpc DeleteSessionRecording(DeleteSessionRecordingRequest) returns (DeleteSessionRecordingResponse) {
option (google.api.http) = {delete: "/v1/session-recordings/{id}"}; option (google.api.http) = {delete: "/v1/session-recordings/{id}"};
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {summary: "Deletes a Session Recording"}; option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {summary: "Deletes a Session Recording when provided a Session Recording ID, or deletes a Video recording when provided a Video ID. If the ID is malformed or not provided an error is returned."};
}
// CreateExport creates an export of the specified Connection Recording in the requested mime type.
// The provided request must include the Connection Recording ID. The export is processed
// asynchronously; use GetExport to poll the status of the export. If the ID is missing,
// malformed, or references a non-existing resource, an error is returned.
rpc CreateExport(CreateExportRequest) returns (CreateExportResponse) {
option (google.api.http) = {
post: "/v1/session-recordings/{connection_recording_id}:export"
body: "*"
response_body: "item"
};
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {summary: "CreateExport creates an export of the specified Connection Recording in the requested mime type. The export is processed asynchronously; use GetExport to poll the status of the export. If the ID is missing, malformed, or references a non-existing resource, an error is returned."};
}
// GetExport returns a stored Export if present. The provided request must include the Export ID
// for the Export being retrieved. If that ID is missing, malformed, or references a non-existing
// resource, an error is returned.
rpc GetExport(GetExportRequest) returns (GetExportResponse) {
option (google.api.http) = {
get: "/v1/session-recordings/{id}:export"
response_body: "item"
};
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {summary: "GetExport returns a stored Export if present. The provided request must include the Export ID for the Export being retrieved. If that ID is missing, malformed, or references a non-existing resource, an error is returned."};
}
// ListExports lists all Exports. Exports are ordered by create time descending
// (most recently created first).
rpc ListExports(ListExportsRequest) returns (ListExportsResponse) {
option (google.api.http) = {get: "/v1/session-recordings:list-exports"};
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {summary: "ListExports lists all exports. Exports are ordered by created_time descending (most recently created first)."};
}
// CancelExport cancels an Export that is in progress. The provided request must include the
// Export ID for the Export being cancelled. If that ID is missing, malformed, or references a
// non-existing resource, an error is returned. Returns the Export in its cancelled state.
rpc CancelExport(CancelExportRequest) returns (CancelExportResponse) {
option (google.api.http) = {post: "/v1/session-recordings/{id}:export:cancel"};
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {summary: "CancelExport cancels an Export that is in progress. The provided request must include the Export ID for the Export being cancelled. If that ID is missing, malformed, or references a non-existing resource, an error is returned. Returns the Export in its cancelled state."};
} }
} }
@@ -134,8 +176,9 @@ message DownloadRequest {
// - Session ID and Session recording ID for Session recordings // - Session ID and Session recording ID for Session recordings
// - Connection ID and Connection recording ID for Connection recordings // - Connection ID and Connection recording ID for Connection recordings
// - Channel recording ID for Channel recordings // - Channel recording ID for Channel recordings
// - Video ID for Video recordings
string id = 1; // @gotags: class:"public" eventstream:"observation" string id = 1; // @gotags: class:"public" eventstream:"observation"
// The format of the response. The only supported mime type is "application/x-asciicast". // The format of the response. Supports "application/x-asciicast" and "video/webm".
// Defaults to "application/x-asciicast" if not set. // Defaults to "application/x-asciicast" if not set.
string mime_type = 2 [json_name = "mime_type"]; // @gotags: class:"public" eventstream:"observation" string mime_type = 2 [json_name = "mime_type"]; // @gotags: class:"public" eventstream:"observation"
} }
@@ -155,3 +198,77 @@ message DeleteSessionRecordingRequest {
} }
message DeleteSessionRecordingResponse {} message DeleteSessionRecordingResponse {}
message CreateExportRequest {
// The ID of the Connection Recording to export.
string connection_recording_id = 1; // @gotags: class:"public" eventstream:"observation"
// The mime type of the export.
string mime_type = 2 [json_name = "mime_type"]; // @gotags: class:"public" eventstream:"observation"
}
message CreateExportResponse {
// The created export.
resources.sessionrecordings.v1.Export item = 1;
}
message GetExportRequest {
// The ID of the Export to retrieve.
string id = 1; // @gotags: class:"public" eventstream:"observation"
}
message GetExportResponse {
// The requested export.
resources.sessionrecordings.v1.Export item = 1;
}
message ListExportsRequest {
// The scope in which to list exports.
// Must be set unless recursive is set.
string scope_id = 1; // @gotags: class:"public" eventstream:"observation"
// Whether to recurse into child scopes when listing.
// If set and scope_id is empty, shows exports in
// all scopes the caller has access to.
bool recursive = 2; // @gotags: class:"public" eventstream:"observation"
// An opaque token that Boundary uses to continue an existing iteration or
// request updated items. If you do not specify a token, pagination
// starts from the beginning. To learn more about list pagination
// in Boundary, refer to [list pagination](https://developer.hashicorp.com/boundary/docs/api-clients/api/pagination).
string list_token = 3 [json_name = "list_token"]; // @gotags: `class:"public"`
// The maximum size of a page in this iteration.
// If you do not set a page size, Boundary uses the configured default page size.
// If the page_size is greater than the default page size configured,
// Boundary truncates the page size to this number.
uint32 page_size = 4 [json_name = "page_size"]; // @gotags: class:"public" eventstream:"observation"
}
message ListExportsResponse {
// The items returned in this page.
repeated resources.sessionrecordings.v1.Export items = 1;
// The type of response, either "delta" or "complete".
// Delta signifies that this is part of a paginated result
// or an update to a previously completed pagination.
// Complete signifies that it is the last page.
string response_type = 2 [json_name = "response_type"]; // @gotags: class:"public" eventstream:"observation"
// An opaque token used to continue an existing pagination or
// request updated items. Use this token in the next list request
// to request the next page.
string list_token = 3 [json_name = "list_token"]; // @gotags: `class:"public"`
// The name of the field which the items are sorted by.
string sort_by = 4 [json_name = "sort_by"]; // @gotags: class:"public" eventstream:"observation"
// The direction of the sort, either "asc" or "desc".
string sort_dir = 5 [json_name = "sort_dir"]; // @gotags: class:"public" eventstream:"observation"
// A list of item IDs that have been removed since they were returned
// as part of a pagination. They should be dropped from any client cache.
// This may contain items that are not known to the cache, if they were
// created and deleted between listings.
repeated string removed_ids = 6 [json_name = "removed_ids"]; // @gotags: class:"public" eventstream:"observation"
// An estimate at the total items available. This may change during pagination.
uint32 est_item_count = 7 [json_name = "est_item_count"]; // @gotags: class:"public" eventstream:"observation"
}
message CancelExportRequest {
// The ID of the Export to cancel.
string id = 1; // @gotags: class:"public" eventstream:"observation"
}
message CancelExportResponse {}
File diff suppressed because it is too large. Load diff
@@ -936,8 +936,12 @@ type RdpTargetAttributes struct {
DefaultPort *wrapperspb.UInt32Value `protobuf:"bytes,10,opt,name=default_port,proto3" json:"default_port,omitempty" class:"public"` // @gotags: `class:"public"` DefaultPort *wrapperspb.UInt32Value `protobuf:"bytes,10,opt,name=default_port,proto3" json:"default_port,omitempty" class:"public"` // @gotags: `class:"public"`
// The default RDP port that will be listened on by the client's local proxy. // The default RDP port that will be listened on by the client's local proxy.
DefaultClientPort *wrapperspb.UInt32Value `protobuf:"bytes,20,opt,name=default_client_port,proto3" json:"default_client_port,omitempty" class:"public"` // @gotags: `class:"public"` DefaultClientPort *wrapperspb.UInt32Value `protobuf:"bytes,20,opt,name=default_client_port,proto3" json:"default_client_port,omitempty" class:"public"` // @gotags: `class:"public"`
unknownFields protoimpl.UnknownFields // PublicId of the storage bucket associated with the target
sizeCache protoimpl.SizeCache StorageBucketId *wrapperspb.StringValue `protobuf:"bytes,30,opt,name=storage_bucket_id,proto3" json:"storage_bucket_id,omitempty" class:"public" eventstream:"observation"` // @gotags: `class:"public" eventstream:"observation"`
// A boolean indicating if session recording has been enabled
EnableSessionRecording *wrapperspb.BoolValue `protobuf:"bytes,40,opt,name=enable_session_recording,proto3" json:"enable_session_recording,omitempty" class:"public" eventstream:"observation"` // @gotags: `class:"public" eventstream:"observation"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
} }
func (x *RdpTargetAttributes) Reset() { func (x *RdpTargetAttributes) Reset() {
@@ -984,6 +988,20 @@ func (x *RdpTargetAttributes) GetDefaultClientPort() *wrapperspb.UInt32Value {
return nil return nil
} }
func (x *RdpTargetAttributes) GetStorageBucketId() *wrapperspb.StringValue {
if x != nil {
return x.StorageBucketId
}
return nil
}
func (x *RdpTargetAttributes) GetEnableSessionRecording() *wrapperspb.BoolValue {
if x != nil {
return x.EnableSessionRecording
}
return nil
}
// WorkerInfo contains information about workers, returned in to the client in SessionAuthorization // WorkerInfo contains information about workers, returned in to the client in SessionAuthorization
type WorkerInfo struct { type WorkerInfo struct {
state protoimpl.MessageState `protogen:"open.v1"` state protoimpl.MessageState `protogen:"open.v1"`
@@ -1697,13 +1715,17 @@ const file_controller_api_resources_targets_v1_target_proto_rawDesc = "" +
"\x11storage_bucket_id\x18\x1e \x01(\v2\x1c.google.protobuf.StringValueB7\xa0\xda)\x01\xc2\xdd)/\n" + "\x11storage_bucket_id\x18\x1e \x01(\v2\x1c.google.protobuf.StringValueB7\xa0\xda)\x01\xc2\xdd)/\n" +
"\x1cattributes.storage_bucket_id\x12\x0fStorageBucketIdR\x11storage_bucket_id\x12\x9d\x01\n" + "\x1cattributes.storage_bucket_id\x12\x0fStorageBucketIdR\x11storage_bucket_id\x12\x9d\x01\n" +
"\x18enable_session_recording\x18( \x01(\v2\x1a.google.protobuf.BoolValueBE\xa0\xda)\x01\xc2\xdd)=\n" + "\x18enable_session_recording\x18( \x01(\v2\x1a.google.protobuf.BoolValueBE\xa0\xda)\x01\xc2\xdd)=\n" +
"#attributes.enable_session_recording\x12\x16EnableSessionRecordingR\x18enable_session_recording\"\x95\x02\n" + "#attributes.enable_session_recording\x12\x16EnableSessionRecordingR\x18enable_session_recording\"\xbb\x04\n" +
"\x13RdpTargetAttributes\x12p\n" + "\x13RdpTargetAttributes\x12p\n" +
"\fdefault_port\x18\n" + "\fdefault_port\x18\n" +
" \x01(\v2\x1c.google.protobuf.UInt32ValueB.\xa0\xda)\x01\xc2\xdd)&\n" + " \x01(\v2\x1c.google.protobuf.UInt32ValueB.\xa0\xda)\x01\xc2\xdd)&\n" +
"\x17attributes.default_port\x12\vDefaultPortR\fdefault_port\x12\x8b\x01\n" + "\x17attributes.default_port\x12\vDefaultPortR\fdefault_port\x12\x8b\x01\n" +
"\x13default_client_port\x18\x14 \x01(\v2\x1c.google.protobuf.UInt32ValueB;\xa0\xda)\x01\xc2\xdd)3\n" + "\x13default_client_port\x18\x14 \x01(\v2\x1c.google.protobuf.UInt32ValueB;\xa0\xda)\x01\xc2\xdd)3\n" +
"\x1eattributes.default_client_port\x12\x11DefaultClientPortR\x13default_client_port\"&\n" + "\x1eattributes.default_client_port\x12\x11DefaultClientPortR\x13default_client_port\x12\x83\x01\n" +
"\x11storage_bucket_id\x18\x1e \x01(\v2\x1c.google.protobuf.StringValueB7\xa0\xda)\x01\xc2\xdd)/\n" +
"\x1cattributes.storage_bucket_id\x12\x0fStorageBucketIdR\x11storage_bucket_id\x12\x9d\x01\n" +
"\x18enable_session_recording\x18( \x01(\v2\x1a.google.protobuf.BoolValueBE\xa0\xda)\x01\xc2\xdd)=\n" +
"#attributes.enable_session_recording\x12\x16EnableSessionRecordingR\x18enable_session_recording\"&\n" +
"\n" + "\n" +
"WorkerInfo\x12\x18\n" + "WorkerInfo\x12\x18\n" +
"\aaddress\x18\n" + "\aaddress\x18\n" +
@@ -1839,19 +1861,21 @@ var file_controller_api_resources_targets_v1_target_proto_depIdxs = []int32{
24, // 31: controller.api.resources.targets.v1.SshTargetAttributes.enable_session_recording:type_name -> google.protobuf.BoolValue 24, // 31: controller.api.resources.targets.v1.SshTargetAttributes.enable_session_recording:type_name -> google.protobuf.BoolValue
22, // 32: controller.api.resources.targets.v1.RdpTargetAttributes.default_port:type_name -> google.protobuf.UInt32Value 22, // 32: controller.api.resources.targets.v1.RdpTargetAttributes.default_port:type_name -> google.protobuf.UInt32Value
22, // 33: controller.api.resources.targets.v1.RdpTargetAttributes.default_client_port:type_name -> google.protobuf.UInt32Value 22, // 33: controller.api.resources.targets.v1.RdpTargetAttributes.default_client_port:type_name -> google.protobuf.UInt32Value
19, // 34: controller.api.resources.targets.v1.SessionAuthorizationData.scope:type_name -> controller.api.resources.scopes.v1.ScopeInfo 20, // 34: controller.api.resources.targets.v1.RdpTargetAttributes.storage_bucket_id:type_name -> google.protobuf.StringValue
21, // 35: controller.api.resources.targets.v1.SessionAuthorizationData.created_time:type_name -> google.protobuf.Timestamp 24, // 35: controller.api.resources.targets.v1.RdpTargetAttributes.enable_session_recording:type_name -> google.protobuf.BoolValue
21, // 36: controller.api.resources.targets.v1.SessionAuthorizationData.expiration:type_name -> google.protobuf.Timestamp 19, // 36: controller.api.resources.targets.v1.SessionAuthorizationData.scope:type_name -> controller.api.resources.scopes.v1.ScopeInfo
11, // 37: controller.api.resources.targets.v1.SessionAuthorizationData.worker_info:type_name -> controller.api.resources.targets.v1.WorkerInfo 21, // 37: controller.api.resources.targets.v1.SessionAuthorizationData.created_time:type_name -> google.protobuf.Timestamp
19, // 38: controller.api.resources.targets.v1.SessionAuthorization.scope:type_name -> controller.api.resources.scopes.v1.ScopeInfo 21, // 38: controller.api.resources.targets.v1.SessionAuthorizationData.expiration:type_name -> google.protobuf.Timestamp
21, // 39: controller.api.resources.targets.v1.SessionAuthorization.created_time:type_name -> google.protobuf.Timestamp 11, // 39: controller.api.resources.targets.v1.SessionAuthorizationData.worker_info:type_name -> controller.api.resources.targets.v1.WorkerInfo
21, // 40: controller.api.resources.targets.v1.SessionAuthorization.expiration:type_name -> google.protobuf.Timestamp 19, // 40: controller.api.resources.targets.v1.SessionAuthorization.scope:type_name -> controller.api.resources.scopes.v1.ScopeInfo
6, // 41: controller.api.resources.targets.v1.SessionAuthorization.credentials:type_name -> controller.api.resources.targets.v1.SessionCredential 21, // 41: controller.api.resources.targets.v1.SessionAuthorization.created_time:type_name -> google.protobuf.Timestamp
42, // [42:42] is the sub-list for method output_type 21, // 42: controller.api.resources.targets.v1.SessionAuthorization.expiration:type_name -> google.protobuf.Timestamp
42, // [42:42] is the sub-list for method input_type 6, // 43: controller.api.resources.targets.v1.SessionAuthorization.credentials:type_name -> controller.api.resources.targets.v1.SessionCredential
42, // [42:42] is the sub-list for extension type_name 44, // [44:44] is the sub-list for method output_type
42, // [42:42] is the sub-list for extension extendee 44, // [44:44] is the sub-list for method input_type
0, // [0:42] is the sub-list for field type_name 44, // [44:44] is the sub-list for extension type_name
44, // [44:44] is the sub-list for extension extendee
0, // [0:44] is the sub-list for field type_name
} }
func init() { file_controller_api_resources_targets_v1_target_proto_init() } func init() { file_controller_api_resources_targets_v1_target_proto_init() }