Skip to content

Commit

Permalink
feat: add service tokens
Browse files Browse the repository at this point in the history
  • Loading branch information
NathanFlurry committed Apr 12, 2024
1 parent e768e8f commit 214bf51
Show file tree
Hide file tree
Showing 57 changed files with 1,611 additions and 58 deletions.
19 changes: 19 additions & 0 deletions docs/infrastructure/fern/GENERATING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Generating

## Step 1: Cloud & build Fern

```sh
gh repo clone rivet-gg/fern
cd fern
yarn install
yarn husky install
yarn dist:cli:dev
```

## Step 2: Generate

In the Rivet repo:

```
FERN_REPO_PATH=/path/to/fern ./scripts/fern/gen.sh
```
26 changes: 26 additions & 0 deletions fern/definition/cloud/games/namespaces/__package__.yml
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,19 @@ service:
type: uuid
response: CreateGameNamespaceTokenPublicResponse

createGameNamespaceTokenService:
path: /games/{game_id}/namespaces/{namespace_id}/tokens/service
method: POST
docs: Creates a service token for the given namespace.
path-parameters:
game_id:
type: uuid
namespace_id:
type: uuid
request:
body: CreateGameNamespaceTokenServiceRequest
response: CreateGameNamespaceTokenServiceResponse

updateGameNamespaceVersion:
path: /games/{game_id}/namespaces/{namespace_id}/version
method: PUT
Expand Down Expand Up @@ -373,6 +386,19 @@ types:
JSON.
type: string

CreateGameNamespaceTokenServiceRequest:
properties:
ttl: integer

CreateGameNamespaceTokenServiceResponse:
properties:
token:
docs: |-
A JSON Web Token.
Slightly modified to include a description prefix and use Protobufs of
JSON.
type: string

UpdateGameNamespaceVersionRequest:
properties:
version_id:
Expand Down
33 changes: 33 additions & 0 deletions lib/claims/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,21 @@ pub mod ent {
Ok(Server {})
}
}

#[derive(Clone, Debug)]
pub struct GameNamespaceService {
pub namespace_id: Uuid,
}

impl TryFrom<&schema::entitlement::GameNamespaceService> for GameNamespaceService {
type Error = GlobalError;

fn try_from(value: &schema::entitlement::GameNamespaceService) -> GlobalResult<Self> {
Ok(GameNamespaceService {
namespace_id: unwrap!(value.namespace_id).as_uuid(),
})
}
}
}

pub trait ClaimsDecode {
Expand All @@ -368,6 +383,7 @@ pub trait ClaimsDecode {
fn as_bypass(&self) -> GlobalResult<ent::Bypass>;
fn as_access_token(&self) -> GlobalResult<ent::AccessToken>;
fn as_server(&self) -> GlobalResult<ent::Server>;
fn as_game_namespace_service(&self) -> GlobalResult<ent::GameNamespaceService>;
}

impl ClaimsDecode for schema::Claims {
Expand Down Expand Up @@ -647,6 +663,22 @@ impl ClaimsDecode for schema::Claims {
))
.and_then(std::convert::identity)
}

fn as_game_namespace_service(&self) -> GlobalResult<ent::GameNamespaceService> {
self.entitlements
.iter()
.find_map(|ent| match &ent.kind {
Some(schema::entitlement::Kind::GameNamespaceService(ent)) => {
Some(ent::GameNamespaceService::try_from(ent))
}
_ => None,
})
.ok_or(err_code!(
CLAIMS_MISSING_ENTITLEMENT,
entitlements = "GameNamespaceService"
))
.and_then(std::convert::identity)
}
}

pub trait EntitlementTag {
Expand Down Expand Up @@ -674,6 +706,7 @@ impl EntitlementTag for schema::Entitlement {
schema::entitlement::Kind::Bypass(_) => 15,
schema::entitlement::Kind::AccessToken(_) => 16,
schema::entitlement::Kind::Server(_) => 17,
schema::entitlement::Kind::GameNamespaceService(_) => 18,
})
}
}
Expand Down
8 changes: 7 additions & 1 deletion proto/claims.proto
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ message Entitlement {
rivet.common.Uuid run_id = 1;
}

// Manage a game's cloud status.
// Manage a game's cloud resources.
message GameCloud {
rivet.common.Uuid game_id = 1;
}
Expand Down Expand Up @@ -109,7 +109,12 @@ message Entitlement {

// Issued to provisioned servers for communication with our API.
message Server {

}

// Token used to access Rivet via an API backend.
message GameNamespaceService {
rivet.common.Uuid namespace_id = 1;
}

oneof kind {
Expand All @@ -129,6 +134,7 @@ message Entitlement {
Bypass bypass = 15;
AccessToken access_token = 16;
Server server = 17;
GameNamespaceService game_namespace_service = 18;
}

reserved 13;
Expand Down
79 changes: 79 additions & 0 deletions sdks/full/go/cloud/games/namespaces/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -1226,6 +1226,85 @@ func (c *Client) CreateGameNamespaceTokenPublic(ctx context.Context, gameId uuid
return response, nil
}

// Creates a service token for the given namespace.
func (c *Client) CreateGameNamespaceTokenService(ctx context.Context, gameId uuid.UUID, namespaceId uuid.UUID, request *namespaces.CreateGameNamespaceTokenServiceRequest) (*namespaces.CreateGameNamespaceTokenServiceResponse, error) {
baseURL := "https://api.rivet.gg"
if c.baseURL != "" {
baseURL = c.baseURL
}
endpointURL := fmt.Sprintf(baseURL+"/"+"cloud/games/%v/namespaces/%v/tokens/service", gameId, namespaceId)

errorDecoder := func(statusCode int, body io.Reader) error {
raw, err := io.ReadAll(body)
if err != nil {
return err
}
apiError := core.NewAPIError(statusCode, errors.New(string(raw)))
decoder := json.NewDecoder(bytes.NewReader(raw))
switch statusCode {
case 500:
value := new(sdk.InternalError)
value.APIError = apiError
if err := decoder.Decode(value); err != nil {
return apiError
}
return value
case 429:
value := new(sdk.RateLimitError)
value.APIError = apiError
if err := decoder.Decode(value); err != nil {
return apiError
}
return value
case 403:
value := new(sdk.ForbiddenError)
value.APIError = apiError
if err := decoder.Decode(value); err != nil {
return apiError
}
return value
case 408:
value := new(sdk.UnauthorizedError)
value.APIError = apiError
if err := decoder.Decode(value); err != nil {
return apiError
}
return value
case 404:
value := new(sdk.NotFoundError)
value.APIError = apiError
if err := decoder.Decode(value); err != nil {
return apiError
}
return value
case 400:
value := new(sdk.BadRequestError)
value.APIError = apiError
if err := decoder.Decode(value); err != nil {
return apiError
}
return value
}
return apiError
}

var response *namespaces.CreateGameNamespaceTokenServiceResponse
if err := c.caller.Call(
ctx,
&core.CallParams{
URL: endpointURL,
Method: http.MethodPost,
Headers: c.header,
Request: request,
Response: &response,
ErrorDecoder: errorDecoder,
},
); err != nil {
return nil, err
}
return response, nil
}

// Updates the version of a game namespace.
func (c *Client) UpdateGameNamespaceVersion(ctx context.Context, gameId uuid.UUID, namespaceId uuid.UUID, request *namespaces.UpdateGameNamespaceVersionRequest) error {
baseURL := "https://api.rivet.gg"
Expand Down
61 changes: 61 additions & 0 deletions sdks/full/go/cloud/games/namespaces/namespaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,67 @@ func (c *CreateGameNamespaceTokenPublicResponse) String() string {
return fmt.Sprintf("%#v", c)
}

type CreateGameNamespaceTokenServiceRequest struct {
Ttl int `json:"ttl"`

_rawJSON json.RawMessage
}

func (c *CreateGameNamespaceTokenServiceRequest) UnmarshalJSON(data []byte) error {
type unmarshaler CreateGameNamespaceTokenServiceRequest
var value unmarshaler
if err := json.Unmarshal(data, &value); err != nil {
return err
}
*c = CreateGameNamespaceTokenServiceRequest(value)
c._rawJSON = json.RawMessage(data)
return nil
}

func (c *CreateGameNamespaceTokenServiceRequest) String() string {
if len(c._rawJSON) > 0 {
if value, err := core.StringifyJSON(c._rawJSON); err == nil {
return value
}
}
if value, err := core.StringifyJSON(c); err == nil {
return value
}
return fmt.Sprintf("%#v", c)
}

type CreateGameNamespaceTokenServiceResponse struct {
// A JSON Web Token.
// Slightly modified to include a description prefix and use Protobufs of
// JSON.
Token string `json:"token"`

_rawJSON json.RawMessage
}

func (c *CreateGameNamespaceTokenServiceResponse) UnmarshalJSON(data []byte) error {
type unmarshaler CreateGameNamespaceTokenServiceResponse
var value unmarshaler
if err := json.Unmarshal(data, &value); err != nil {
return err
}
*c = CreateGameNamespaceTokenServiceResponse(value)
c._rawJSON = json.RawMessage(data)
return nil
}

func (c *CreateGameNamespaceTokenServiceResponse) String() string {
if len(c._rawJSON) > 0 {
if value, err := core.StringifyJSON(c._rawJSON); err == nil {
return value
}
}
if value, err := core.StringifyJSON(c); err == nil {
return value
}
return fmt.Sprintf("%#v", c)
}

type GetGameNamespaceByIdResponse struct {
Namespace *cloud.NamespaceFull `json:"namespace,omitempty"`

Expand Down
10 changes: 8 additions & 2 deletions sdks/full/go/cloud/version/matchmaker/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,11 @@ func (p PortProtocol) Ptr() *PortProtocol {
return &p
}

// Range of ports that can be connected to. Note that the port range values returned by /find
// Range of ports that can be connected to.
// If configured, `network_mode` must equal `host`.
// Port ranges may overlap between containers, it is the responsibility of the developer to ensure ports are available before using.
// Read more about host networking [here](https://rivet.gg/docs/dynamic-servers/concepts/host-bridge-networking).
// Only available on Rivet Open Source & Enterprise.
//
// ### Related
//
Expand Down Expand Up @@ -246,7 +250,9 @@ func (p *PortRange) String() string {
return fmt.Sprintf("%#v", p)
}

// Denotes what type of proxying to use for ports. Rivet GameGuard adds DoS and DDoS mitigation to incoming connections.
// Range of ports that can be connected to.
// `game_guard` (default) proxies all traffic through [Game Guard](https://rivet.gg/docs/dynamic-servers/concepts/game-guard) to mitigate DDoS attacks and provide TLS termination.
// `none` sends traffic directly to the game server. If configured, `network_mode` must equal `host`. Read more about host networking [here](https://rivet.gg/docs/dynamic-servers/concepts/host-bridge-networking). Only available on Rivet Open Source & Enterprise.
//
// ### Related - /docs/dynamic-servers/concepts/game-guard - cloud.version.matchmaker.PortProtocol
type ProxyKind string
Expand Down
Loading

0 comments on commit 214bf51

Please sign in to comment.