# Security for the GRPC Server with TLS
[gRPC](https://grpc.io/) has built-in support for [TLS](https://en.wikipedia.org/wiki/Transport_Layer_Security) both for the server and client applications.
From the [documentation](https://www.grpc.io/docs/guides/auth/):
> gRPC has SSL/TLS integration and promotes the use of SSL/TLS to authenticate the server, and to encrypt all the data exchanged between the client and the server. Optional mechanisms are available for clients to provide certificates for mutual authentication.
## Options for TLS
For the server case, the enumeration [grpc_ssl_client_certificate_request_type](https://grpc.github.io/grpc/cpp/grpc__security__constants_8h.html) can be used how to respond to an incoming gRPC client.
The values of this enumeration are described by the following table:
| Enumerator | Description |
|------------------------------------------|----------------------------------------------|
| GRPC_SSL_DONT_REQUEST_CLIENT_CERTIFICATE | Server does not request client certificate.
The certificate presented by the client is not checked by the server at all.
(A client may present a self signed or signed certificate or not present a certificate at all and any of those option would be accepted) |
| GRPC_SSL_REQUEST_CLIENT_CERTIFICATE_BUT_DONT_VERIFY | Server requests client certificate but does not enforce that the client presents a certificate.
If the client presents a certificate, the client authentication is left to the application (the necessary metadata will be available to the application via authentication context properties, see grpc_auth_context).
The client's key certificate pair must be valid for the SSL connection to be established. |
| GRPC_SSL_REQUEST_CLIENT_CERTIFICATE_AND_VERIFY | Server requests client certificate but does not enforce that the client presents a certificate.
If the client presents a certificate, the client authentication is done by the gRPC framework.
(For a successful connection the client needs to either present a certificate that can be verified against the root certificate configured by the server or not present a certificate at all)
The client's key certificate pair must be valid for the SSL connection to be established. |
| GRPC_SSL_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_BUT_DONT_VERIFY | Server requests client certificate and enforces that the client presents a certificate.
If the client presents a certificate, the client authentication is left to the application (the necessary metadata will be available to the application via authentication context properties, see grpc_auth_context).
The client's key certificate pair must be valid for the SSL connection to be established. |
| GRPC_SSL_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY | Server requests client certificate and enforces that the client presents a certificate.
The certificate presented by the client is verified by the gRPC framework. (For a successful connection the client needs to present a certificate that can be verified against the root certificate configured by the server)
The client's key certificate pair must be valid for the SSL connection to be established. |
## Initialization with TLS
The desired value is passed as an argument by the [init script](./agent/scripts/init.d/openolt) to the **openolt** application.
If the TLS option is an empty string the gRPC server is insecure, otherwise the corresponding TLS level is set.
## Certificate Files
TLS requires valid certificates.
The following certificate files must be present at the **keystore/** directory:
- root.crt (CA public key),
- server.crt (public key),
- server.key (private key)
Self-signed certificates can be used.
## Self-Signed Certificates
Self-signed certificates can be generated by the ubiquitous [OpenSSL](https://en.wikipedia.org/wiki/OpenSSL).
Note that the gRPC clients may require these certificates.
First create the **keystore** directory, if it is not created already.
A few definitions will be useful, here domain is the ma1 IP address of the OLT which is "192.168.31.251".
```
## on the test OLT
# openssl version
OpenSSL 1.0.1t 3 May 2016
# mkdir -p /broadcom/keystore
# cd /broadcom/keystore
# DOMAIN=192.168.31.251
# COMMON_NAME=$DOMAIN
# SUBJECT="/C=CA/ST=None/L=NB/O=None/CN=$COMMON_NAME"
# NUM_OF_DAYS=365
```
Generate the root certificates:
```
# openssl genrsa -out root.key 2048
Generating RSA private key, 2048 bit long modulus
........................................+++
..................................+++
e is 65537 (0x10001)
# openssl req -x509 -new -nodes -key root.key -sha256 -days $NUM_OF_DAYS -out root.crt
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:US
State or Province Name (full name) [Some-State]:California
Locality Name (eg, city) []:Santa Clara
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Netsia
Organizational Unit Name (eg, section) []:SEBA
Common Name (e.g. server FQDN or YOUR name) []:www.netsia.com
Email Address []:contact@netsia.com
```
Generate the extension file:
```
# cat << EOF > v3.ext
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
subjectAltName = @alt_names
[alt_names]
DNS.1 = $DOMAIN
IP.1 = $COMMON_NAME
EOF
# cat v3.ext
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
subjectAltName = @alt_names
[alt_names]
DNS.1 = 192.168.31.251
IP.1 = 192.168.31.251
```
Generate the server certificates:
```
# openssl req -new -newkey rsa:2048 -sha256 -nodes -keyout server.key -subj "$SUBJECT" -out server.csr
Generating a 2048 bit RSA private key
..........................................+++
..............................................................+++
writing new private key to 'server.key'
-----
# openssl x509 -req -in server.csr -CA root.crt -CAkey root.key -CAcreateserial -out server.crt -days $NUM_OF_DAYS -sha256 -extfile v3.ext
Signature ok
subject=/C=CA/ST=None/L=NB/O=None/CN=192.168.31.251
Getting CA Private Key
```
## Test with Browsers
Browsers are quite exacting when it comes to certificates, and gRPC is not designed for browsers.
Still the certificates may be checked with a common browser.
Assuming that the generated certificates will be used by the init script with the first and least-demanding TLS option, going to the URL https://192.168.31.251:9191/ will result in security warnings. Now the certificates can be checked using the browser itself.
Both Google Chrome and Mozilla Firefox respond in a similar way, since they don't know beforehand the Certificate Authority which issued this certificate (self-signed, unknown entitities), they give strong warnings:
- Google Chrome: NET::ERR_CERT_AUTHORITY_INVALID
- Mozilla Firefox: SEC_ERROR_UNKNOWN_ISSUER