# LVSAPI
---------

API front end for the Live Video Service

## Code Coverage

[![codecov](https://codecov.internal.justin.tv/ghe/video/lvsapi/branch/master/graph/badge.svg)](https://codecov.internal.justin.tv/ghe/video/lvsapi)


## Overview

#### Summary

LVS (Live Video Service) is a generic solution to allow users to stream video-only
jobs into the twitch system, simplifying the integration requirements in terms of
being tightly coupled with the api, account, and payments ecosystems.
LVS allows a broadcaster to ingest a video job, and then users to be able to
playback such stream via an embedded or externalized player core.

The service consists of an API service - LVSAPI which is hosted in AWS Elastic Beanstalk.
This service manages:
* Creation of encrypted streamkeys (external)
* Authorization of encrypted streamkeys (internal)
* Listing of all streams info for a customer (external)
* Getting a stream’s info for a customerId and contentId (external)

Examples:
CustomerId: twitch-dev, AmazonLive-Tools, AmazonLive-Prod
ContentId: uuid

#### More details and architecture diagrams in [Technical Specification](https://docs.google.com/document/d/1SJi5ix390jXNtW2xTx5R1SANLEXiyxxg-BgqhdFpols/edit) 

### Endpoints

#### External Service

* /twirp/lvs.LiveVideoService/CreateStreamKey
* /twirp/lvs.LiveVideoService/ListStreams
* /twirp/lvs.LiveVideoService/GetStream
* /twirp/lvs.LiveVideoService/DecodeStreamKey

#### Internal Service
* /twirp/lvs.LiveVideoServiceInternal/AuthorizeBroadcast
* /twirp/lvs.LiveVideoServiceInternal/ResetStreamKeySecret


### Location
[The App](https://us-west-2.console.aws.amazon.com/elasticbeanstalk/home?region=us-west-2#/application/overview?applicationName=lvsapi) is deployed on AWS only - under twitch-video-aws account


### Prerequisites
* Go environment setup
* Go version >= 1.9
* Twitch-video-aws account under Elastic Beanstalk


### Local development

The external and internal APIs are exposed through different binaries

#### External APIs

```shell
       export GOPATH=<your go dev path>
       go get code.justin.tv/video/lvsapi
       cd $GOPATH/src/code.justin.tv/video/lvsapi
       go build ./cmd/lvsapi
       ./lvsapi -strict-auth=false -twitch-env=dev
```

#### Internal APIs

```shell
       export GOPATH=<your go dev path>
       go get code.justin.tv/video/lvsapi
       cd $GOPATH/src/code.justin.tv/video/lvsapi
       go build ./cmd/lvsapiinternal
       ./lvsapiinternal -twitch-env=dev
```

### Configuring for Production

Currently, the configuration is handled via beanstalk environment variables.


### Dependencies

LVSAPI is the only component in LVS which is outside of the video system, so listing the dependencies for LVS here:

* **Sandstorm**: We use sandstorm to manage client-root, client-crt, server-crt, server-key
* **S3**: We use S3 to store per-env, per-customer secrets that are used for encryption and decryption of the streamkeys.
	https://s3.console.aws.amazon.com/s3/buckets/twitch-lvs-streamkey-secrets/?region=us-west-2&tab=overview
    For VODs, we use customer’s bucket directly.

* **Usher**: We call Usher backend to get stream info for a customerid, contentid, or to get all streams info for a customerid


### Generated code

This requires retool to be installed. You can install retool with:

```
go get -u github.com/twitchtv/retool
```
All generated code can be re-generated with

```
retool do go generate ./cmd/... ./internal/... ./rpc/... ./streamkey/...
```

### Authentication

Production authentication is handled exclusively via TLS two-way authentication.
The certificate produced by a client must have been signed by the client-root.key
and client-root.crt files which are currently stored in sandstorm.


#### Key Generation
All client keys must be signed by the root client certificate and key. These files
are currently stored in sandstorm, and may be retrieved via the sandstorm cli. For
more information on how to retrieve those files see the section below titled Sandstorm.

This section assumes the following
- client-root.crt and client-root.key are available
- openssl is installed and available to both the customer and Twitch

* Generate a new Certificate Signing Request and key

```
openssl req -out client.csr -new -newkey rsa:2048 -nodes -keyout client.key
```

You will be prompted to enter data into various fields for this certificate. All
fields are optional in this case with the exception of the "Common Name" field, which
must be populated with a valid LvsCustomerId value. Typical values may look like
"twitch-dev" or "Amazon-Live".

Also worth noting is that this step would typically be taken by a customer. The customer
would then share the generated client.csr file (but not the key file) with us.

* Verify the certificate request has the "Common Name" field set properly

```
openssl req -in client.csr -subject -noout
```

The output from this command will look like

```
subject=/C=AU/ST=Some-State/O=Internet Widgits Pty Ltd/CN=this-is-the-common-name
```

Look for the `CN=` and ensure the name that follows is correct

* Generate a signed certificate from the Certificate Signing Request and client-root

```
openssl x509 -req -days 365 -CAcreateserial -CAkey /path/to/client-root.key -CA /path/to/client-root.crt -in client.csr -out client.crt
```

* Ensure that these certificates are valid:

Curl
```
curl -k --key client.key --cert client.crt -H 'Content-Type: application/json' -XPOST -k https://lvs.twitch.tv/twirp/code.justin.tv.video.lvsapi.rpc.lvs.LiveVideoService/CheckAuth -d '{}' | jq
```

For complex reasons curl doesn't work like this on OS X, on osx try checkauth.go instead

checkauth.go
```
go run cmd/lvsapi/testdata/checkauth.go -client-cert client.crt -client-key client.key -server-cert lvs.twitch.tv.crt -server-url https://lvs.twitch.tv
```

#### Sandstorm
Sandstorm is used to store certificate key pairs for both the server and client root
certificate. Retrieving them is a fairly standard sandstorm operation, but here are
some simple steps as a primer:

- Ensure you have AWS credentials properly configured for your environments
- Add your user's ARN to the video-lvsapi-production role in the sandstorm dashboard
- Run the following commands:

```
sandstorm get --role-arn arn:aws:iam::734326455073:role/sandstorm/production/templated/role/video-lvsapi-production video/lvsapi/production/client-root.crt > client-root.crt
sandstorm get --role-arn arn:aws:iam::734326455073:role/sandstorm/production/templated/role/video-lvsapi-production video/lvsapi/production/client-root.key > client-root.key
```

### Use

#### Staging

The staging service has a dev authentication mechanism that works via HTTP to ease
testing and development of this software. To make an authenticated request against
staging, use the header `X-Twitch-Lvs-Force-Auth`. Example:

```
curl -vv -H 'X-Twitch-Lvs-Force-Auth: testauth' -H 'Content-Type: application/json' -XPOST -k http://lvs-staging.twitch.tv/twirp/code.justin.tv.video.lvsapi.rpc.lvs.LiveVideoService/CheckAuth -d '{}' | jq
```

#### Production

Alternately, it's possible to use the key and certificate file includued in this repository
(twitch-dev.key and twitch-dev.crt) to authenticate as the LvsCustomerId: "twitch-dev"
The source file at cmd/lvsapi/testdata/checkauth.go can be used to run an authentication
test of this flow, and as a sample for how to generate a valid golang http client. The
tool itself can be used like this:

```
go run cmd/lvsapi/testdata/checkauth.go -client-cert keys/twitch-dev.crt -client-key keys/twitch-dev.key -server-cert keys/lvs.twitch.tv.crt -server-url https://lvs.twitch.tv
```

### Testing

To test locally
```shell
    cd $GOPATH/src/code.justin.tv/video/lvsapi
    bingo test
```


### Operations runbook

Currently the runbook is located on [google drive](https://docs.google.com/document/d/1QUthvZbGw0EkLXNWsnlRxZkN79ZSUQ4oDn3Vi4ykwTo/edit#)


### Contact Information

* Email: video-ingest@justin.tv
* Slack: #ingest
