Repository: NVIDIA/NVFlare

Issue:
[BUG] FLARE Console kits from dashboard are missing fields in fed_admin.json
**Describe the bug**
FLARE Console kits downloaded from the dashboard can't be launched because they are missing a bunch of fields in the $EMAIL/startup/fed_admin.json file including the ca_cert location.

There are a bunch of top-level fields in the fed_admin.json which are populated when running `nvflare provision` manually, but which are missing when downloading the provisioned kit from the dashboard.

The workaround is to manually add these missing fields to the downloaded fed_admin.json (see example below).

**To Reproduce**
Steps to reproduce the behavior:
1. Host the dashboard
2. Log in as the Project Admin
3. Enter Project Configuration details and make public
4. Enter Server Configuration server DNS name
5. Go to Project Home and Freeze the project
6. Go to Downloads then download and unzip the FLARE Console
7. Open the file $EMAIL/startup/fed_admin.json
8. Observe that some fields are missing under "admin": {...}
9. Attempt to launch the console by running `./$EMAIL/startup/fl_admin.sh` and entering the user name
10. Observe the following exception
```
Traceback (most recent call last):
  File "/opt/conda/lib/python3.8/runpy.py", line 194, in _run_module_as_main
    return _run_code(code, main_globals, None,
  File "/opt/conda/lib/python3.8/runpy.py", line 87, in _run_code
    exec(code, run_globals)
  File "/opt/conda/lib/python3.8/site-packages/nvflare/fuel/hci/tools/admin.py", line 115, in <module>
    main()
  File "/opt/conda/lib/python3.8/site-packages/nvflare/fuel/hci/tools/admin.py", line 97, in main
    client = AdminClient(
  File "/opt/conda/lib/python3.8/site-packages/nvflare/fuel/hci/client/cli.py", line 112, in __init__
    self.api = AdminAPI(
  File "/opt/conda/lib/python3.8/site-packages/nvflare/fuel/hci/client/api.py", line 370, in __init__
    if len(ca_cert) <= 0:
TypeError: object of type 'NoneType' has no len()
``` 

**Expected behavior**
The fields in fed_admin.json which show up when running `nvflare provision` should also be in the fed_admin.json when downloading from the dashboard. A freshly downloaded FLARE console should be launched successfully without modification needed.

**Screenshots**
Downloaded fed_admin.json:
```json
{
  "format_version": 1,
  "admin": {
    "overseer_agent": {
      "path": "nvflare.ha.dummy_overseer_agent.DummyOverseerAgent",
      "args": {
        "sp_end_point": "fl-server-nlb-singleAZ-ffc95222dc034180.elb.us-east-1.amazonaws.com:8003:8004"
      }
    }
  }
}
```

Correct fed_admin.json (produced via manual provision):
```json
{
  "format_version": 1,
  "admin": {
    "with_file_transfer": true,
    "upload_dir": "transfer",
    "download_dir": "transfer",
    "with_login": true,
    "with_ssl": true,
    "cred_type": "cert",
    "client_key": "client.key",
    "client_cert": "client.crt",
    "ca_cert": "rootCA.pem",
    "prompt": "> ",
    "overseer_agent": {
      "path": "nvflare.ha.dummy_overseer_agent.DummyOverseerAgent",
      "args": {
        "sp_end_point": "fl-server-nlb-singleAZ-ffc95222dc034180.elb.us-east-1.amazonaws.com:8003:8004"
      }
    }
  }
}
```

**Desktop (please complete the following information):**
 - OS: ubuntu 20.04
 - Python Version: 3.8.12
 - NVFlare Version: 2.2.1

**Additional context**
- Using startup kits downloaded from the dashboard on the latest nvflare/nvflare image, launched with `nvflare dashboard -p 8008 --start`



Discussion:
Thanks for reporting, @IsaacYangSLA  can you take a look for this one ? 
Thanks.  This will be fixed in #1215 .

Resolving patch:
diff --git a/nvflare/dashboard/application/blob.py b/nvflare/dashboard/application/blob.py
--- a/nvflare/dashboard/application/blob.py
+++ b/nvflare/dashboard/application/blob.py
@@ -74,12 +74,12 @@ def gen_server(key, first_server=True):
     project = Project.query.first()
     if first_server:
         entity = Entity(project.server1)
-        fl_port = 8003
-        admin_port = 8004
+        fl_port = 8002
+        admin_port = 8003
     else:
         entity = Entity(project.server2)
-        fl_port = 8103
-        admin_port = 8104
+        fl_port = 8102
+        admin_port = 8103
     issuer = Entity(project.short_name)
     signing_cert_pair = CertPair(issuer, project.root_key, project.root_cert)
     cert_pair = make_cert(entity, signing_cert_pair)
@@ -102,7 +102,7 @@ def gen_server(key, first_server=True):
         }
     else:
         overseer_agent = {"path": "nvflare.ha.dummy_overseer_agent.DummyOverseerAgent"}
-        overseer_agent["args"] = {"sp_end_point": f"{project.server1}:8003:8004"}
+        overseer_agent["args"] = {"sp_end_point": f"{project.server1}:8002:8003"}
 
     config["overseer_agent"] = overseer_agent
     replacement_dict = {
@@ -206,7 +206,7 @@ def gen_client(key, id):
         }
     else:
         overseer_agent = {"path": "nvflare.ha.dummy_overseer_agent.DummyOverseerAgent"}
-        overseer_agent["args"] = {"sp_end_point": f"{project.server1}:8003:8004"}
+        overseer_agent["args"] = {"sp_end_point": f"{project.server1}:8002:8003"}
     config["overseer_agent"] = overseer_agent
 
     with tempfile.TemporaryDirectory() as tmp_dir:
@@ -305,9 +305,8 @@ def gen_user(key, id):
         }
     else:
         overseer_agent = {"path": "nvflare.ha.dummy_overseer_agent.DummyOverseerAgent"}
-        overseer_agent["args"] = {"sp_end_point": f"{project.server1}:8003:8004"}
-    agent_config = {"overseer_agent": overseer_agent}
-    config["admin"] = agent_config
+        overseer_agent["args"] = {"sp_end_point": f"{project.server1}:8002:8003"}
+    config["admin"].update({"overseer_agent": overseer_agent})
 
     with tempfile.TemporaryDirectory() as tmp_dir:
         user_dir = os.path.join(tmp_dir, entity.name)


Test patch: