Skip to content

Commit

Permalink
feat: Add CLI for simple gateway registration
Browse files Browse the repository at this point in the history
Signed-off-by: Christine Wang <christinewang@fb.com>
  • Loading branch information
christinewang5 committed Feb 22, 2022
1 parent 42eebde commit c0b4922
Show file tree
Hide file tree
Showing 8 changed files with 170 additions and 22 deletions.
4 changes: 2 additions & 2 deletions orc8r/cloud/docker/controller/supervisord.conf
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ stdout_events_enabled=true
stderr_events_enabled=true

[program:bootstrapper]
command=/usr/bin/envdir /var/opt/magma/envdir /var/opt/magma/bin/bootstrapper -cak=/var/opt/magma/certs/bootstrapper.key -logtostderr=true -v=0
command=/usr/bin/envdir /var/opt/magma/envdir /var/opt/magma/bin/bootstrapper -cak=/var/opt/magma/certs/bootstrapper.key -logtostderr=true -v=20
autorestart=true
stdout_logfile=NONE
stderr_logfile=NONE
Expand Down Expand Up @@ -143,7 +143,7 @@ stdout_events_enabled=true
stderr_events_enabled=true

[program:obsidian]
command=/usr/bin/envdir /var/opt/magma/envdir /var/opt/magma/bin/obsidian -logtostderr=true -v=0
command=/usr/bin/envdir /var/opt/magma/envdir /var/opt/magma/bin/obsidian -logtostderr=true -v=20
autorestart=true
stdout_logfile=NONE
stderr_logfile=NONE
Expand Down
1 change: 0 additions & 1 deletion orc8r/cloud/docker/run.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,6 @@ def main() -> None:
cmd = ['docker-compose', 'up', '-d']
if args.down:
cmd = ['docker-compose', 'down']

print("Running '%s'..." % ' '.join(cmd))
try:
subprocess.run(cmd, check=True)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ package unary
// bypass Identity verification checks.
// For now, the only service in this category is Bootstrapper.
var identityDecoratorBypassList = map[string]struct{}{
"/magma.orc8r.Bootstrapper/GetChallenge": {},
"/magma.orc8r.Bootstrapper/RequestSign": {},
"/magma.orc8r.Bootstrapper/GetChallenge": {},
"/magma.orc8r.Bootstrapper/RequestSign": {},
"/magma.orc8r.Registration/Register": {},
"/magma.orc8r.CloudRegistration/GetGatewayDeviceInfo": {},
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,7 @@ func NewRegistrationServicer() protos.RegistrationServer {
}

func (r *RegistrationService) Register(c context.Context, request *protos.RegisterRequest) (*protos.RegisterResponse, error) {
nonce, err := NonceFromToken(request.Token)
if err != nil {
return nil, err
}

deviceInfo, err := r.GetGatewayDeviceInfo(context.Background(), nonce)
deviceInfo, err := r.GetGatewayDeviceInfo(context.Background(), request.Token)
if err != nil {
clientErr := makeErr(fmt.Sprintf("could not get device info from token %v: %v", request.Token, err))
return clientErr, nil
Expand Down
47 changes: 37 additions & 10 deletions orc8r/gateway/python/magma/common/service_registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,33 @@ def reset():
"""
ServiceRegistry.get_registry()["services"] = {}

@staticmethod
def get_bare_rpc_channel(rootca_path=None):
"""
Returns a RPC channel to bootstrap service in CLOUD before having
control proxy config.
Returns:
grpc channel
"""
ip = 'bootstrapper-controller.magma.test'
port = '7444'
rootca_path = '/var/opt/magma/certs/rootCA.pem' if not rootca_path else rootca_path

with open(rootca_path, 'rb') as rootca_f:
rootca = rootca_f.read()
ssl_creds = grpc.ssl_channel_credentials(
root_certificates=rootca,
)
authority = 'bootstrapper-controller.magma.test'
grpc_options = [('grpc.default_authority', authority)]
channel = grpc.secure_channel(
target='%s:%s' % (ip, port),
credentials=ssl_creds,
options=grpc_options,
)
return channel

@staticmethod
def get_bootstrap_rpc_channel():
"""
Expand All @@ -109,8 +136,8 @@ def get_bootstrap_rpc_channel():

@staticmethod
def get_rpc_channel(
service, destination, proxy_cloud_connections=True,
grpc_options=None,
service, destination, proxy_cloud_connections=True,
grpc_options=None,
):
"""
Returns a RPC channel to the service. The connection params
Expand All @@ -137,13 +164,13 @@ def get_rpc_channel(
authority = '%s-%s' % (service, proxy_config['cloud_address'])

should_use_proxy = proxy_config['proxy_cloud_connections'] and \
proxy_cloud_connections
proxy_cloud_connections

# If speaking to a local service or to the proxy, the grpc channel
# can be reused. If speaking to the cloud directly, the client cert
# could become stale after the next bootstrapper run.
should_reuse_channel = should_use_proxy or \
(destination == ServiceRegistry.LOCAL)
(destination == ServiceRegistry.LOCAL)
if should_reuse_channel:
channel = ServiceRegistry._CHANNELS_CACHE.get(authority, None)
if channel is not None:
Expand Down Expand Up @@ -232,12 +259,12 @@ def set_grpc_cipher_suites():
and delete this. The current nghttpx version doesn't support the
ciphers needed by default for gRPC.
"""
os.environ["GRPC_SSL_CIPHER_SUITES"] = "ECDHE-ECDSA-AES256-GCM-SHA384:"\
"ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:"\
"ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:"\
"ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:"\
"ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:"\
"ECDHE-RSA-AES128-SHA256"
os.environ["GRPC_SSL_CIPHER_SUITES"] = "ECDHE-ECDSA-AES256-GCM-SHA384:" \
"ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:" \
"ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:" \
"ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:" \
"ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:" \
"ECDHE-RSA-AES128-SHA256"


def get_ssl_creds():
Expand Down
2 changes: 1 addition & 1 deletion orc8r/gateway/python/scripts/generate_nghttpx_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ def get_context():

def main():
logging.basicConfig(
level=logging.INFO,
level=logging.DEBUG,
format='[%(asctime)s %(levelname)s %(name)s] %(message)s',
)
generate_template_config(
Expand Down
124 changes: 124 additions & 0 deletions orc8r/gateway/python/scripts/register.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
#!/usr/bin/env python3

"""
Copyright 2020 The Magma Authors.
This source code is licensed under the BSD-style license found in the
LICENSE file in the root directory of this source tree.
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
"""

import argparse
import asyncio
import os

import grpc
import snowflake

from orc8r.protos.identity_pb2 import AccessGatewayID, Identity
from orc8r.protos.bootstrapper_pb2_grpc import BootstrapperStub
from magma.common.cert_utils import load_public_key_to_base64der
from orc8r.protos.bootstrapper_pb2 import (
RegisterRequest,
GetGatewayDeviceInfoRequest,
)
from orc8r.protos.bootstrapper_pb2_grpc import (
RegistrationStub, # Register
CloudRegistrationStub, # Register
)
from magma.common.service_registry import ServiceRegistry

def bare_grpc_wrapper(func):
"""
Wraps a function with a gRPC wrapper which creates a RPC client to
the service and handles any RPC Exceptions.
Usage:
@cloud_grpc_wrapper
def func(client, args):
pass
func(args, ProtoStubClass, 'service')
"""

def wrapper(*alist):
args = alist[0]
stub_cls = alist[1]
chan = ServiceRegistry.get_bare_rpc_channel()
client = stub_cls(chan)
try:
func(client, args)
except Exception as err:
print(err)
exit(1)

return wrapper


@bare_grpc_wrapper
def register_handler(client, args):
req = RegisterRequest()
req.token = args.token
req.hwid.id = snowflake.snowflake()
req.challenge_key.key = load_public_key_to_base64der(
"/var/opt/magma/certs/gw_challenge.key")
req.challenge_key.key_type = 0

res = client.Register(req)
if res.HasField("error"):
raise Exception(res.error)

print("Successfully registered gateway")
print("Hardware ID\n-----------\n%s" % req.hwid)
print("Challenge Key\n-----------\n%s\n" % req.challenge_key)
print("Control Proxy\n-----------\n%s\n\n" % res.control_proxy)
return res


@bare_grpc_wrapper
def get_gateway_device_info_handler(client, args):
device_info_request = GetGatewayDeviceInfoRequest()
device_info_request.token = args.token

res = client.GetGatewayDeviceInfo(device_info_request)
if res.HasField("error"):
raise grpc.RpcError(res)

print("Successfully retrieved gateway device info")
print("Network ID\n-----------\n%s" % res.gateway_device_info.network_id)
print("Logical ID\n-----------\n%s\n\n" % res.gateway_device_info.logical_id)
return res


def main():
"""Register a gateway"""
parser = argparse.ArgumentParser(description="Register a gateway.")
parser.add_argument(
"domain",
metavar="DOMAIN_NAME",
type=str,
help="orc8r's domain name",
)
parser.add_argument(
"token",
metavar="REGISTRATION_TOKEN",
type=str,
help="registration token after API call",
)
parser.add_argument(
"--ca_file",
type=str,
help="orc8r's root CA file"
)
args = parser.parse_args()

register_handler(args, RegistrationStub)
get_gateway_device_info_handler(args, CloudRegistrationStub)


if __name__ == "__main__":
main()
1 change: 1 addition & 0 deletions orc8r/gateway/python/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
'scripts/magma_conditional_service.py',
'scripts/magma_get_config.py',
'scripts/magmad_cli.py',
'scripts/register.py',
'scripts/service_util.py',
'scripts/service303_cli.py',
'scripts/show_gateway_info.py',
Expand Down

0 comments on commit c0b4922

Please sign in to comment.