This is an automated email from the ASF dual-hosted git repository.

rawlin pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/trafficcontrol.git


The following commit(s) were added to refs/heads/master by this push:
     new 9838c0e  Traffic router add https (#3436)
9838c0e is described below

commit 9838c0e0d6f98f6f0bde7c87e997403ee4db57cb
Author: mattjackson220 <[email protected]>
AuthorDate: Fri Aug 2 14:28:58 2019 -0600

    Traffic router add https (#3436)
    
    * Updated Traffic Router API to use HTTPS, updated TO to call TR API HTTPS 
if available, updated tests and documentation
    
    * Updated CHANGELOG
    
    * added licensing header
    
    * Updated Traffic Router API to use HTTPS, updated TO to call TR API HTTPS 
if available, updated tests and documentation
    
    * updated to separate API default cert from DS default cert
    
    * updated per comments
    
    * rebase with master
    
    * updates per comment
    
    * extended expiration of cert
---
 CHANGELOG.md                                       |  1 +
 docs/source/admin/quick_howto/ciab.rst             |  2 +-
 docs/source/api/cdns_name_snapshot.rst             | 20 +++---
 docs/source/api/cdns_name_snapshot_new.rst         | 20 +++---
 docs/source/development/traffic_router.rst         |  2 +-
 .../traffic_router/traffic_router_api.rst          |  8 +++
 .../cdn-in-a-box/docker-compose.expose-ports.yml   |  1 +
 .../traffic_ops_data/profiles/040-CCR_CIAB.json    |  5 ++
 .../cdn-in-a-box/traffic_router/Dockerfile         |  2 +-
 infrastructure/cdn-in-a-box/traffic_router/run.sh  |  2 +
 lib/go-tc/crconfig.go                              | 21 +++---
 traffic_ops/app/lib/API/Cdn.pm                     | 17 ++++-
 .../app/lib/MojoPlugins/TrafficRouterConnection.pm | 30 ++++++--
 traffic_ops/app/lib/Utils/CCR.pm                   | 25 +++++--
 traffic_ops/traffic_ops_golang/crconfig/servers.go | 31 ++++++---
 .../traffic_ops_golang/crconfig/servers_test.go    |  3 +
 .../traffic_router/protocol/RouterNioEndpoint.java | 15 ++--
 .../traffic_router/secure/CertificateRegistry.java | 80 +++++++++++++++++++---
 .../traffic_router/utils/HttpsProperties.java      | 53 ++++++++++++++
 traffic_router/core/src/main/conf/https.properties | 16 +++++
 traffic_router/core/src/main/conf/server.xml       |  4 ++
 .../traffic_router/core/http/RouterFilter.java     |  2 +-
 .../core/router/TrafficRouterManager.java          | 10 +++
 .../traffic_router/core/util/LanguidState.java     | 14 ++++
 .../main/lib/systemd/system/traffic_router.service |  1 +
 .../core/src/main/scripts/postinstall.sh           | 16 ++++-
 traffic_router/core/src/test/conf/https.properties | 16 +++++
 .../traffic_router/core/CatalinaTrafficRouter.java | 13 ++++
 28 files changed, 356 insertions(+), 74 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 0d17ecd..a9494fa 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -57,6 +57,7 @@ The format is based on [Keep a 
Changelog](http://keepachangelog.com/en/1.0.0/).
 - Database migrations have been collapsed. Rollbacks to migrations that 
previously existed are no longer possible.
 - Issue #3750: Fixed Grove access log fractional seconds.
 - Issue #3646: Fixed Traffic Monitor Thresholds.
+- Modified Traffic Router API to be available via HTTPS.
 
 ## [3.0.0] - 2018-10-30
 ### Added
diff --git a/docs/source/admin/quick_howto/ciab.rst 
b/docs/source/admin/quick_howto/ciab.rst
index abee210..cf04022 100644
--- a/docs/source/admin/quick_howto/ciab.rst
+++ b/docs/source/admin/quick_howto/ciab.rst
@@ -69,7 +69,7 @@ In a typical scenario, if the steps in `Building`_ have been 
followed, all that'
        | Traffic Portal                  | Web interface on 443 (Javascript 
required)                   | ``TO_ADMIN_USER`` in `variables.env`_ | 
``TO_ADMIN_PASSWORD`` in `variables.env`_ |
        
+---------------------------------+--------------------------------------------------------------+---------------------------------------+-------------------------------------------+
        | Traffic Router                  | Web interfaces on ports 3080 (HTTP) 
and 3443 (HTTPS), with a | N/A                                   | N/A          
                             |
-       |                                 | DNS service on 53 and an API on 
3333                         |                                       |          
                                 |
+       |                                 | DNS service on 53 and an API on 
3333 (HTTP) and 2222 (HTTPS) |                                       |          
                                 |
        
+---------------------------------+--------------------------------------------------------------+---------------------------------------+-------------------------------------------+
        | Traffic Vault                   | Riak key-value store on port 8010   
                         | ``TV_ADMIN_USER`` in `variables.env`_ | 
``TV_ADMIN_PASSWORD`` in `variables.env`_ |
        
+---------------------------------+--------------------------------------------------------------+---------------------------------------+-------------------------------------------+
diff --git a/docs/source/api/cdns_name_snapshot.rst 
b/docs/source/api/cdns_name_snapshot.rst
index e80f901..a79d138 100644
--- a/docs/source/api/cdns_name_snapshot.rst
+++ b/docs/source/api/cdns_name_snapshot.rst
@@ -108,15 +108,16 @@ Response Structure
 
 :contentRouters: An object containing keys which are the (short) hostnames of 
the Traffic Routers that serve requests for :term:`Delivery Service`\ s in this 
CDN
 
-       :api.port:  A string containing the port number on which the 
:ref:`tr-api` is served by this Traffic Router
-       :fqdn:      This Traffic Router's Fully Qualified Domain Name (FQDN)
-       :httpsPort: The port number on which this Traffic Router listens for 
incoming HTTPS requests
-       :ip:        This Traffic Router's IPv4 address
-       :ip6:       This Traffic Router's IPv6 address
-       :location:  The name of the Cache Group to which this Traffic Router 
belongs
-       :port:      The port number on which this Traffic Router listens for 
incoming HTTP requests
-       :profile:   The :ref:`profile-name` of the :term:`Profile` used by this 
Traffic Router
-       :status:    The health status of this Traffic Router
+       :api.port:        A string containing the port number on which the 
:ref:`tr-api` is served by this Traffic Router via HTTP
+       :secure.api.port: A string containing the port number on which the 
:ref:`tr-api` is served by this Traffic Router via HTTPS (optional)
+       :fqdn:            This Traffic Router's Fully Qualified Domain Name 
(FQDN)
+       :httpsPort:       The port number on which this Traffic Router listens 
for incoming HTTPS requests
+       :ip:              This Traffic Router's IPv4 address
+       :ip6:             This Traffic Router's IPv6 address
+       :location:        The name of the Cache Group to which this Traffic 
Router belongs
+       :port:            The port number on which this Traffic Router listens 
for incoming HTTP requests
+       :profile:         The :ref:`profile-name` of the :term:`Profile` used 
by this Traffic Router
+       :status:          The health status of this Traffic Router
 
                .. seealso:: :ref:`health-proto`
 
@@ -436,6 +437,7 @@ Response Structure
                "contentRouters": {
                        "trafficrouter": {
                                "api.port": "3333",
+                               "secure.api.port": "3443",
                                "fqdn": "trafficrouter.infra.ciab.test",
                                "httpsPort": 443,
                                "ip": "172.16.239.60",
diff --git a/docs/source/api/cdns_name_snapshot_new.rst 
b/docs/source/api/cdns_name_snapshot_new.rst
index 6c80789..f03d19c 100644
--- a/docs/source/api/cdns_name_snapshot_new.rst
+++ b/docs/source/api/cdns_name_snapshot_new.rst
@@ -107,15 +107,16 @@ Response Structure
 
 :contentRouters: An object containing keys which are the (short) hostnames of 
the Traffic Routers that serve requests for :term:`Delivery Service`\ s in this 
CDN
 
-       :api.port:  A string containing the port number on which the 
:ref:`tr-api` is served by this Traffic Router
-       :fqdn:      This Traffic Router's Fully Qualified Domain Name (FQDN)
-       :httpsPort: The port number on which this Traffic Router listens for 
incoming HTTPS requests
-       :ip:        This Traffic Router's IPv4 address
-       :ip6:       This Traffic Router's IPv6 address
-       :location:  The name of the :term:`Cache Group` to which this Traffic 
Router belongs
-       :port:      The port number on which this Traffic Router listens for 
incoming HTTP requests
-       :profile:   The :ref:`profile-name` of the :term:`Profile` used by this 
Traffic Router
-       :status:    The health status of this Traffic Router
+       :api.port:        A string containing the port number on which the 
:ref:`tr-api` is served by this Traffic Router via HTTP
+       :secure.api.port: A string containing the port number on which the 
:ref:`tr-api` is served by this Traffic Router via HTTPS (optional)
+       :fqdn:            This Traffic Router's Fully Qualified Domain Name 
(FQDN)
+       :httpsPort:       The port number on which this Traffic Router listens 
for incoming HTTPS requests
+       :ip:              This Traffic Router's IPv4 address
+       :ip6:             This Traffic Router's IPv6 address
+       :location:        The name of the :term:`Cache Group` to which this 
Traffic Router belongs
+       :port:            The port number on which this Traffic Router listens 
for incoming HTTP requests
+       :profile:         The :ref:`profile-name` of the :term:`Profile` used 
by this Traffic Router
+       :status:          The health status of this Traffic Router
 
                .. seealso:: :ref:`health-proto`
 
@@ -433,6 +434,7 @@ Response Structure
                "contentRouters": {
                        "trafficrouter": {
                                "api.port": "3333",
+                               "secure.api.port": "3443",
                                "fqdn": "trafficrouter.infra.ciab.test",
                                "httpsPort": 443,
                                "ip": "172.16.239.60",
diff --git a/docs/source/development/traffic_router.rst 
b/docs/source/development/traffic_router.rst
index e4385a1..4b60b6e 100644
--- a/docs/source/development/traffic_router.rst
+++ b/docs/source/development/traffic_router.rst
@@ -115,7 +115,7 @@ To install the Traffic Router Developer environment:
 
                ..  Note:: If an error is displayed in the Console, run ``mvn 
clean verify`` from the ``traffic_router`` directory
 
-Once running, the :ref:`tr-api` is available at http://localhost:3333, the 
HTTP routing interface is available on http://localhost:8888 and HTTPS is 
available on http://localhost:8443. The DNS server and routing interface is 
available on localhost:53 via TCP and UDP.
+Once running, the :ref:`tr-api` is available over HTTP at 
http://localhost:3333 and over HTTPS at https://localhost:3443,  the HTTP 
routing interface is available on http://localhost:8888 and HTTPS is available 
on http://localhost:8443. The DNS server and routing interface is available on 
localhost:53 via TCP and UDP.
 
 Manual Testing
 ==============
diff --git a/docs/source/development/traffic_router/traffic_router_api.rst 
b/docs/source/development/traffic_router/traffic_router_api.rst
index 5efabb4..df91b30 100644
--- a/docs/source/development/traffic_router/traffic_router_api.rst
+++ b/docs/source/development/traffic_router/traffic_router_api.rst
@@ -20,6 +20,14 @@ Traffic Router API
 ******************
 By default, Traffic Router serves its API via HTTP (not HTTPS) on port 3333. 
This can be configured in :file:`/opt/traffic_router/conf/server.xml` or by 
setting a :term:`Parameter` with the :ref:`parameter-name` "api.port", and the 
:ref:`parameter-config-file` "server.xml" on the Traffic Router's 
:term:`Profile`.
 
+The API can be configured via HTTPS on port 3443 in 
:file:`/opt/traffic_router/conf/server.xml` or by setting a :term:`Parameter` 
named ``secure.api.port`` with ``configFile`` ``server.xml`` on the Traffic 
Router's :term:`Profile`.  The post install script will generate self signed 
certificates at ``/opt/traffic_router/conf/``, create a new Java Keystore named 
:file:`/opt/traffic_router/conf/keyStore.jks`, and add the new certificate to 
the Keystore.  The password for the Java Keystore a [...]
+To override the self signed certificates with new ones from a certificate 
authority, update the properties for the Keystore location and password at 
:file:`/opt/traffic_router/conf/https.properties`.
+
+
+The API can be configured via HTTPS on port 3443 in 
:file:`/opt/traffic_router/conf/server.xml` or by setting a :term:`Parameter` 
named ``secure.api.port`` with ``configFile`` ``server.xml`` on the Traffic 
Router's :term:`Profile`.  When ``systemctl start traffic_router`` is run, it 
will generate self signed certificates at ``/opt/traffic_router/conf/``, create 
a new Java Keystore named :file:`/opt/traffic_router/conf/keyStore.jks`, and 
add the new certificate to the Keystore.  The passw [...]
+To override the self signed certificates with new ones from a certificate 
authority, either replace the Java Keystore in the default location or update 
the properties for the new Keystore location and password at 
:file:`/opt/traffic_router/conf/https.properties` and then restart the Traffic 
Router using ``systemctl``.
+
+
 Traffic Router API endpoints only respond to ``GET`` requests.
 
 ``/crs/stats``
diff --git a/infrastructure/cdn-in-a-box/docker-compose.expose-ports.yml 
b/infrastructure/cdn-in-a-box/docker-compose.expose-ports.yml
index 653479f..484e237 100644
--- a/infrastructure/cdn-in-a-box/docker-compose.expose-ports.yml
+++ b/infrastructure/cdn-in-a-box/docker-compose.expose-ports.yml
@@ -46,6 +46,7 @@ services:
       - "3080:80"
       - "3443:443"
       - "3333:3333"
+      - "2222:3443"
   influxdb:
     ports:
       - "8086:8086"
diff --git 
a/infrastructure/cdn-in-a-box/traffic_ops_data/profiles/040-CCR_CIAB.json 
b/infrastructure/cdn-in-a-box/traffic_ops_data/profiles/040-CCR_CIAB.json
index e4836fc..6d00ce8 100644
--- a/infrastructure/cdn-in-a-box/traffic_ops_data/profiles/040-CCR_CIAB.json
+++ b/infrastructure/cdn-in-a-box/traffic_ops_data/profiles/040-CCR_CIAB.json
@@ -81,6 +81,11 @@
       "value": "3333"
     },
     {
+      "configFile": "server.xml",
+      "name": "secure.api.port",
+      "value": "3443"
+    },
+    {
       "configFile": "CRConfig.json",
       "name": "api.cache-control.max-age",
       "value": "10"
diff --git a/infrastructure/cdn-in-a-box/traffic_router/Dockerfile 
b/infrastructure/cdn-in-a-box/traffic_router/Dockerfile
index 0548176..9e790c8 100644
--- a/infrastructure/cdn-in-a-box/traffic_router/Dockerfile
+++ b/infrastructure/cdn-in-a-box/traffic_router/Dockerfile
@@ -45,6 +45,6 @@ ADD enroller/server_template.json \
     traffic_ops/to-access.sh \
     /
 
-EXPOSE 53 80 3333
+EXPOSE 53 80 3333 3443
 
 CMD /run.sh
diff --git a/infrastructure/cdn-in-a-box/traffic_router/run.sh 
b/infrastructure/cdn-in-a-box/traffic_router/run.sh
index e7a935a..5c2f63e 100755
--- a/infrastructure/cdn-in-a-box/traffic_router/run.sh
+++ b/infrastructure/cdn-in-a-box/traffic_router/run.sh
@@ -90,6 +90,8 @@ do
   fi; 
 done
 
+/opt/traffic_router/conf/generatingCerts.sh
+
 # Configure TO properties
 # File: /opt/traffic_router/conf/traffic_ops.properties
 echo "" > $TO_PROPERTIES
diff --git a/lib/go-tc/crconfig.go b/lib/go-tc/crconfig.go
index e0080f8..7be488f 100644
--- a/lib/go-tc/crconfig.go
+++ b/lib/go-tc/crconfig.go
@@ -67,16 +67,17 @@ type CRConfigTTL struct {
 type CRConfigRouterStatus string
 
 type CRConfigRouter struct {
-       APIPort      *string               `json:"api.port,omitempty"`
-       FQDN         *string               `json:"fqdn,omitempty"`
-       HTTPSPort    *int                  `json:"httpsPort"`
-       HashCount    *int                  `json:"hashCount,omitempty"`
-       IP           *string               `json:"ip,omitempty"`
-       IP6          *string               `json:"ip6,omitempty"`
-       Location     *string               `json:"location,omitempty"`
-       Port         *int                  `json:"port,omitempty"`
-       Profile      *string               `json:"profile,omitempty"`
-       ServerStatus *CRConfigRouterStatus `json:"status,omitempty"`
+       APIPort       *string               `json:"api.port,omitempty"`
+       FQDN          *string               `json:"fqdn,omitempty"`
+       HTTPSPort     *int                  `json:"httpsPort"`
+       HashCount     *int                  `json:"hashCount,omitempty"`
+       IP            *string               `json:"ip,omitempty"`
+       IP6           *string               `json:"ip6,omitempty"`
+       Location      *string               `json:"location,omitempty"`
+       Port          *int                  `json:"port,omitempty"`
+       Profile       *string               `json:"profile,omitempty"`
+       SecureAPIPort *string               `json:"secure.api.port,omitempty"`
+       ServerStatus  *CRConfigRouterStatus `json:"status,omitempty"`
 }
 
 type CRConfigServerStatus string
diff --git a/traffic_ops/app/lib/API/Cdn.pm b/traffic_ops/app/lib/API/Cdn.pm
index 8b463a2..c54846a 100644
--- a/traffic_ops/app/lib/API/Cdn.pm
+++ b/traffic_ops/app/lib/API/Cdn.pm
@@ -523,8 +523,10 @@ sub routing {
                        # TODO: what happens when the request to CCR times out? 
-jse
                        my $c = $self->get_traffic_router_connection( { 
hostname => $ccr_host } );
                        my $s = $c->get_crs_stats();
+                       my $url = $c->get_url();
+
                        if ( !defined($s) ) {
-                               $self->app->log->error("Unable to contact 
$ccr_host for $cdn_name.");
+                               $self->app->log->error("Unable to contact 
$ccr_host for $cdn_name. Traffic Router Url = $url");
                                return $self->internal_server_error( { 
"Internal Server" => "Error: Unable to contact $ccr_host" } );
                        }
                        else {
@@ -740,6 +742,15 @@ sub gen_traffic_router_config {
                        my $api_port =
                                ( defined($r) && defined( $r->value ) ) ? 
$r->value : 3333;
 
+                       my $sap_param = 
$self->db->resultset('Parameter')->search(
+                               {
+                                       'profile_parameters.profile' => 
$row->profile->id,
+                                       'name'                       => 
'secure.api.port'
+                               },
+                               { join => 'profile_parameters' }
+                       );
+                       my $secure_api_port = $rs_param->single;
+
                        my $traffic_router;
 
                        $traffic_router->{'hostName'} = $row->host_name;
@@ -751,6 +762,10 @@ sub gen_traffic_router_config {
                        $traffic_router->{'ip'}       = $row->ip_address;
                        $traffic_router->{'ip6'}      = $row->ip6_address;
                        $traffic_router->{'profile'}  = $row->profile->name;
+                       if ( defined($secure_api_port) && defined( 
$secure_api_port->value ) ) {
+                               $traffic_router->{'secureApiPort'}  = 
int($secure_api_port->value);
+                       }
+
                        push( @{ $data_obj->{'trafficRouters'} }, 
$traffic_router );
                }
                elsif ( $row->type->name =~ m/^EDGE/ || $row->type->name =~ 
m/^MID/ ) {
diff --git a/traffic_ops/app/lib/MojoPlugins/TrafficRouterConnection.pm 
b/traffic_ops/app/lib/MojoPlugins/TrafficRouterConnection.pm
index 952fbf9..7742a8c 100755
--- a/traffic_ops/app/lib/MojoPlugins/TrafficRouterConnection.pm
+++ b/traffic_ops/app/lib/MojoPlugins/TrafficRouterConnection.pm
@@ -33,6 +33,7 @@ sub register {
 
                        my $hostname = undef;
                        my $port     = undef;
+                       my $secure_port = undef;
 
                        if ( exists( $args->{cdn} ) ) {
                                my $cdn                = $args->{cdn};
@@ -47,24 +48,41 @@ sub register {
                        }
                        elsif ( exists $args->{hostname} ) {
                                $hostname = $args->{hostname};
-
                        }
                        else {
                                confess("Supply a cdn or host in the argument 
hashref");
                        }
+
+                       my $traffic_router_connection = undef;
+
                        if ( defined( $args->{port} ) ) {
                                $port = $args->{port};
                        }
                        else {
                                my $hostonly = ( split( /\./, $hostname ) )[0];
                                my $server = 
$self->db->resultset('Server')->search( { host_name => $hostonly } )->single();
-                               my $pp =
+
+                               my $pp_secure_api_port =
                                        $self->db->resultset('ProfileParameter')
-                                       ->search( { -and => [ 'profile.id' => 
$server->profile->id, 'parameter.name' => 'api.port', 'parameter.config_file' 
=> 'server.xml' ] },
-                                       { prefetch => [ 'parameter', 'profile' 
] } )->single();
-                               $port = $pp->parameter->value;
+                                               ->search( { -and => [ 
'profile.id' => $server->profile->id, 'parameter.name' => 'secure.api.port', 
'parameter.config_file' => 'server.xml' ] },
+                                               { prefetch => [ 'parameter', 
'profile' ] } )->single();
+                                       if ( defined($pp_secure_api_port) ) {
+                                               $secure_port = 
$pp_secure_api_port->parameter->value;
+                                       }
+
+                               if ( defined( $secure_port ) ) {
+                                       $port = $secure_port;
+                                       $traffic_router_connection = new 
Utils::CCR( $hostname, $port, 1 );
+                               }
+                               else {
+                                       my $pp_api_port =
+                                               
$self->db->resultset('ProfileParameter')
+                                                       ->search( { -and => [ 
'profile.id' => $server->profile->id, 'parameter.name' => 'api.port', 
'parameter.config_file' => 'server.xml' ] },
+                                                       { prefetch => [ 
'parameter', 'profile' ] } )->single();
+                                               $port = 
$pp_api_port->parameter->value;
+                                       $traffic_router_connection = new 
Utils::CCR( $hostname, $port);
+                               }
                        }
-                       my $traffic_router_connection = new Utils::CCR( 
$hostname, $port );
                        my $proxy_param =
                                $self->db->resultset('Parameter')->search( { 
-and => [ name => 'tm.traffic_rtr_fwd_proxy', config_file => 'global' ] } 
)->single();
                        if ( defined($proxy_param) ) {
diff --git a/traffic_ops/app/lib/Utils/CCR.pm b/traffic_ops/app/lib/Utils/CCR.pm
index 50e1aa7..82f77b5 100644
--- a/traffic_ops/app/lib/Utils/CCR.pm
+++ b/traffic_ops/app/lib/Utils/CCR.pm
@@ -35,6 +35,7 @@ sub new {
        my $class    = shift;
        my $ccr_host = shift;
        my $ccr_port = shift || 80;
+       my $is_secure_port = shift || 0;
 
        if ( !defined($ccr_host) ) {
                confess("First constructor argument must be the CCR host");
@@ -43,10 +44,11 @@ sub new {
                confess("Second constructor argument must be the port number of 
the CCR host");
        }
 
-       $self->{CCR_HOST}   = $ccr_host;
-       $self->{CCR_PORT}   = $ccr_port;
-       $self->{USER_AGENT} = Mojo::UserAgent->new;
-       $self->{FWD_PROXY}  = undef;
+       $self->{CCR_HOST}          = $ccr_host;
+       $self->{CCR_PORT}          = $ccr_port;
+       $self->{USER_AGENT}        = Mojo::UserAgent->new;
+       $self->{FWD_PROXY}         = undef;
+       $self->{IS_SECURE_PORT}    = $is_secure_port;
 
        return ( bless( $self, $class ) );
 }
@@ -77,10 +79,21 @@ sub get_port {
        return ( $self->{CCR_PORT} );
 }
 
+sub get_is_secure_port {
+       my $self = shift || confess("Call on an instance of Utils::CCR");
+       return ( $self->{IS_SECURE_PORT} );
+}
+
 sub get_url {
        my $self = shift || confess("Call on an instance of Utils::CCR");
-       my $url = "http://"; . $self->get_host() . ":" . $self->get_port();
-       return ($url);
+
+       my $protocol = "http";
+       if ( $self->get_is_secure_port() ) {
+           $protocol = "https";
+       }
+
+       my $url = "$protocol://" . $self->get_host() . ":" . $self->get_port();
+       return ( $url );
 }
 
 sub get_location {
diff --git a/traffic_ops/traffic_ops_golang/crconfig/servers.go 
b/traffic_ops/traffic_ops_golang/crconfig/servers.go
index 286990a..b543ff0 100644
--- a/traffic_ops/traffic_ops_golang/crconfig/servers.go
+++ b/traffic_ops/traffic_ops_golang/crconfig/servers.go
@@ -59,15 +59,16 @@ func makeCRConfigServers(cdn string, tx *sql.Tx, cdnDomain 
string) (
                case *s.ServerType == tc.RouterTypeName:
                        status := tc.CRConfigRouterStatus(*s.ServerStatus)
                        routers[host] = tc.CRConfigRouter{
-                               APIPort:      s.APIPort,
-                               FQDN:         s.Fqdn,
-                               HTTPSPort:    s.HttpsPort,
-                               IP:           s.Ip,
-                               IP6:          s.Ip6,
-                               Location:     s.LocationId,
-                               Port:         s.Port,
-                               Profile:      s.Profile,
-                               ServerStatus: &status,
+                               APIPort:       s.APIPort,
+                               FQDN:          s.Fqdn,
+                               HTTPSPort:     s.HttpsPort,
+                               IP:            s.Ip,
+                               IP6:           s.Ip6,
+                               Location:      s.LocationId,
+                               Port:          s.Port,
+                               Profile:       s.Profile,
+                               SecureAPIPort: s.SecureAPIPort,
+                               ServerStatus:  &status,
                        }
                case *s.ServerType == tc.MonitorTypeName:
                        monitors[host] = tc.CRConfigMonitor{
@@ -93,7 +94,8 @@ func makeCRConfigServers(cdn string, tx *sql.Tx, cdnDomain 
string) (
 // ServerUnion has all fields from all servers. This is used to select all 
server data with a single query, and then convert each to the proper type 
afterwards.
 type ServerUnion struct {
        tc.CRConfigTrafficOpsServer
-       APIPort *string
+       APIPort       *string
+       SecureAPIPort *string
 }
 
 const DefaultWeightMultiplier = 1000.0
@@ -165,6 +167,10 @@ and (st.name = 'REPORTED' or st.name = 'ONLINE' or st.name 
= 'ADMIN_DOWN')
                        s.APIPort = params.APIPort
                }
 
+               if hasParams && params.SecureAPIPort != nil {
+                       s.SecureAPIPort = params.SecureAPIPort
+               }
+
                weightMultiplier := DefaultWeightMultiplier
                if hasParams && params.WeightMultiplier != nil {
                        weightMultiplier = *params.WeightMultiplier
@@ -301,6 +307,7 @@ order by dsr.set_number asc
 // ServerParams contains parameter data filled in the CRConfig Servers 
objects. If a given param doesn't exist on the given server, it will be nil.
 type ServerParams struct {
        APIPort          *string
+       SecureAPIPort    *string
        Weight           *float64
        WeightMultiplier *float64
 }
@@ -315,7 +322,7 @@ left join profile_parameter as pp on pp.profile = s.profile
 left join parameter as p on p.id = pp.parameter
 inner join status as st ON st.id = s.status
 where s.cdn_id = (select id from cdn where name = $1)
-and ((p.config_file = 'CRConfig.json' and (p.name = 'weight' or p.name = 
'weightMultiplier')) or (p.name = 'api.port'))
+and ((p.config_file = 'CRConfig.json' and (p.name = 'weight' or p.name = 
'weightMultiplier')) or (p.name = 'api.port') or (p.name = 'secure.api.port'))
 and (st.name = 'REPORTED' or st.name = 'ONLINE' or st.name = 'ADMIN_DOWN')
 `
        rows, err := tx.Query(q, cdn)
@@ -336,6 +343,8 @@ and (st.name = 'REPORTED' or st.name = 'ONLINE' or st.name 
= 'ADMIN_DOWN')
                switch name {
                case "api.port":
                        param.APIPort = &val
+               case "secure.api.port":
+                       param.SecureAPIPort = &val
                case "weight":
                        i, err := strconv.ParseFloat(val, 64)
                        if err != nil {
diff --git a/traffic_ops/traffic_ops_golang/crconfig/servers_test.go 
b/traffic_ops/traffic_ops_golang/crconfig/servers_test.go
index 603025a..dafa56a 100644
--- a/traffic_ops/traffic_ops_golang/crconfig/servers_test.go
+++ b/traffic_ops/traffic_ops_golang/crconfig/servers_test.go
@@ -82,6 +82,7 @@ func ExpectedGetServerParams() map[string]ServerParams {
        return map[string]ServerParams{
                "cache0": ServerParams{
                        APIPort:          randStr(),
+                       SecureAPIPort:    randStr(),
                        Weight:           randFloat64(),
                        WeightMultiplier: randFloat64(),
                },
@@ -96,6 +97,7 @@ func ExpectedGetServerParams() map[string]ServerParams {
 func MockGetServerParams(mock sqlmock.Sqlmock, expected 
map[string]ServerParams, cdn string) {
        rows := sqlmock.NewRows([]string{"host_name", "name", "value"})
        rows = rows.AddRow("cache0", "api.port", *expected["cache0"].APIPort)
+       rows = rows.AddRow("cache0", "secure.api.port", 
*expected["cache0"].SecureAPIPort)
        rows = rows.AddRow("cache0", "weight", *expected["cache0"].Weight)
        rows = rows.AddRow("cache0", "weightMultiplier", 
*expected["cache0"].WeightMultiplier)
        rows = rows.AddRow("cache1", "api.port", *expected["cache1"].APIPort)
@@ -151,6 +153,7 @@ func ExpectedGetAllServers(params map[string]ServerParams) 
map[string]ServerUnio
        for name, param := range params {
                s := ServerUnion{
                        APIPort:                  param.APIPort,
+                       SecureAPIPort:            param.SecureAPIPort,
                        CRConfigTrafficOpsServer: randServer(),
                }
                i := int(*param.Weight * *param.WeightMultiplier)
diff --git 
a/traffic_router/connector/src/main/java/com/comcast/cdn/traffic_control/traffic_router/protocol/RouterNioEndpoint.java
 
b/traffic_router/connector/src/main/java/com/comcast/cdn/traffic_control/traffic_router/protocol/RouterNioEndpoint.java
index 6fe6399..4648604 100644
--- 
a/traffic_router/connector/src/main/java/com/comcast/cdn/traffic_control/traffic_router/protocol/RouterNioEndpoint.java
+++ 
b/traffic_router/connector/src/main/java/com/comcast/cdn/traffic_control/traffic_router/protocol/RouterNioEndpoint.java
@@ -27,7 +27,6 @@ import org.apache.tomcat.util.net.SSLHostConfigCertificate;
 import org.apache.tomcat.util.net.SocketEvent;
 import org.apache.tomcat.util.net.SocketProcessorBase;
 import org.apache.tomcat.util.net.SocketWrapperBase;
-
 import java.util.Map;
 import java.util.Set;
 
@@ -40,8 +39,8 @@ public class RouterNioEndpoint extends NioEndpoint {
        // certificates.  When we are done we call the parent classes 
initialiseSsl.
        @SuppressWarnings({"PMD.SignatureDeclareThrowsException"})
        @Override
-       protected void initialiseSsl() throws Exception{
-               if (isSSLEnabled()){
+       protected void initialiseSsl() throws Exception {
+               if (isSSLEnabled()) {
                        destroySsl();
                        sslHostConfigs.clear();
                        final KeyManager keyManager = new KeyManager();
@@ -54,20 +53,22 @@ public class RouterNioEndpoint extends NioEndpoint {
                }
        }
 
-       synchronized public void replaceSSLHosts(final Map<String, 
HandshakeData> sslHostsData){
+       @SuppressWarnings({"PMD.NPathComplexity", 
"PMD.UseStringBufferForStringAppends"})
+       synchronized public void replaceSSLHosts(final Map<String, 
HandshakeData> sslHostsData) {
                final Set<String> aliases = sslHostsData.keySet();
                String lastHostName = "";
 
-               for (final String alias : aliases){
+               for (final String alias : aliases) {
                        final SSLHostConfig sslHostConfig = new SSLHostConfig();
                        final SSLHostConfigCertificate cert = new 
SSLHostConfigCertificate(sslHostConfig, SSLHostConfigCertificate.Type.RSA);
+                       
sslHostConfig.setHostName(sslHostsData.get(alias).getHostname());
                        cert.setCertificateKeyAlias(alias);
                        sslHostConfig.addCertificate(cert);
                        sslHostConfig.setCertificateKeyAlias(alias);
-                       
sslHostConfig.setHostName(sslHostsData.get(alias).getHostname());
                        sslHostConfig.setProtocols("all");
+                       sslHostConfig.setConfigType(getSslConfigType());
                        sslHostConfig.setCertificateVerification("none");
-                       LOGGER.info("sslHostConfig: " + 
sslHostConfig.getHostName() + " " + sslHostConfig.getTruststoreAlgorithm());
+                       LOGGER.info("sslHostConfig: 
"+sslHostConfig.getHostName() + " " + sslHostConfig.getTruststoreAlgorithm());
 
                        if (!sslHostConfig.getHostName().equals(lastHostName)){
                                addSslHostConfig(sslHostConfig, true);
diff --git 
a/traffic_router/connector/src/main/java/com/comcast/cdn/traffic_control/traffic_router/secure/CertificateRegistry.java
 
b/traffic_router/connector/src/main/java/com/comcast/cdn/traffic_control/traffic_router/secure/CertificateRegistry.java
index e098418..1452585 100644
--- 
a/traffic_router/connector/src/main/java/com/comcast/cdn/traffic_control/traffic_router/secure/CertificateRegistry.java
+++ 
b/traffic_router/connector/src/main/java/com/comcast/cdn/traffic_control/traffic_router/secure/CertificateRegistry.java
@@ -17,6 +17,7 @@ package com.comcast.cdn.traffic_control.traffic_router.secure;
 
 import 
com.comcast.cdn.traffic_control.traffic_router.protocol.RouterNioEndpoint;
 import com.comcast.cdn.traffic_control.traffic_router.shared.CertificateData;
+import com.comcast.cdn.traffic_control.traffic_router.utils.HttpsProperties;
 import org.apache.log4j.Logger;
 import sun.security.tools.keytool.CertAndKeyGen;
 import sun.security.util.ObjectIdentifier;
@@ -25,7 +26,16 @@ import sun.security.x509.CertificateExtensions;
 import sun.security.x509.ExtendedKeyUsageExtension;
 import sun.security.x509.KeyUsageExtension;
 
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.net.InetAddress;
+import java.security.KeyStore;
 import java.security.PrivateKey;
+import java.security.cert.CertificateFactory;
+import java.security.cert.Certificate;
+import java.security.cert.X509Certificate;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.HashMap;
@@ -33,7 +43,6 @@ import java.util.Map;
 import java.util.Vector;
 
 import sun.security.x509.X500Name;
-import java.security.cert.X509Certificate;
 import java.util.Date;
 
 public class CertificateRegistry {
@@ -43,10 +52,16 @@ public class CertificateRegistry {
        volatile private Map<String, HandshakeData>     handshakeDataMap = new 
HashMap<>();
        private RouterNioEndpoint sslEndpoint = null;
        final private Map<String, CertificateData> previousData = new 
HashMap<>();
+       public String defaultAlias;
 
        // Recommended Singleton Pattern implementation
        // https://community.oracle.com/docs/DOC-918906
        private CertificateRegistry() {
+               try {
+                       defaultAlias = InetAddress.getLocalHost().getHostName();
+               } catch (Exception e) {
+                       log.error("Error getting hostname");
+               }
        }
 
        public static CertificateRegistry getInstance() {
@@ -97,13 +112,49 @@ public class CertificateRegistry {
        }
 
        public Map<String, HandshakeData> getHandshakeData() {
-           return handshakeDataMap;
-    }
+               return handshakeDataMap;
+       }
 
        public void setEndPoint(final RouterNioEndpoint routerNioEndpoint) {
                sslEndpoint = routerNioEndpoint;
        }
 
+       private HandshakeData createApiDefaultSsl() {
+               try {
+                       final Map<String, String> httpsProperties = (new 
HttpsProperties()).getHttpsPropertiesMap();
+
+                       final KeyStore ks = KeyStore.getInstance("JKS");
+                       final String selfSignedKeystoreFile = 
httpsProperties.get("https.certificate.location");
+                       if (new File(selfSignedKeystoreFile).exists()) {
+                               final String password = 
httpsProperties.get("https.password");
+                               final InputStream readStream = new 
FileInputStream(selfSignedKeystoreFile);
+                               ks.load(readStream, password.toCharArray());
+                               readStream.close();
+                               final Certificate[] certs = 
ks.getCertificateChain(defaultAlias);
+                               final List<X509Certificate> x509certs = new 
ArrayList<>();
+
+                               for (final Certificate cert : certs) {
+                                       final CertificateFactory cf = 
CertificateFactory.getInstance("X.509");
+                                       final ByteArrayInputStream bais = new 
ByteArrayInputStream(cert.getEncoded());
+                                       final X509Certificate x509cert = 
(X509Certificate) cf.generateCertificate(bais);
+                                       x509certs.add(x509cert);
+                               }
+
+                               X509Certificate[] x509CertsArray = new 
X509Certificate[x509certs.size()];
+                               x509CertsArray = 
x509certs.toArray(x509CertsArray);
+
+                               final HandshakeData handshakeData = new 
HandshakeData(defaultAlias, defaultAlias,
+                                               x509CertsArray, (PrivateKey) 
ks.getKey(defaultAlias, password.toCharArray()));
+
+                               return handshakeData;
+                       }
+               } catch (Exception e) {
+                       log.error("Failed to load default certificate. Received 
" + e.getClass() + " with message: " + e.getMessage());
+                       return null;
+               }
+               return null;
+       }
+
        @SuppressWarnings("PMD.AccessorClassGeneration")
        private static class CertificateRegistryHolder {
                private static final CertificateRegistry 
DELIVERY_SERVICE_CERTIFICATES = new CertificateRegistry();
@@ -137,13 +188,11 @@ public class CertificateRegistry {
                        }
                }
                // find CertificateData which has been removed
-               for (final String alias : previousData.keySet())
-               {
-                       if (!master.containsKey(alias) && sslEndpoint != null)
-                       {
+               for (final String alias : previousData.keySet()) {
+                       if (!master.containsKey(alias) && sslEndpoint != null) {
                                final String hostname = 
previousData.get(alias).getHostname();
                                sslEndpoint.removeSslHostConfig(hostname);
-                           log.warn("Removed handshake data with hostname " + 
hostname);
+                               log.warn("Removed handshake data with hostname 
" + hostname);
                        }
                }
 
@@ -166,12 +215,25 @@ public class CertificateRegistry {
                                final HandshakeData defaultHd = 
createDefaultSsl();
                                if (defaultHd == null){
                                        log.error("Failed to initialize the 
CertificateRegistry because of a problem with the 'default' " +
-                                                       "certificate.  
Returning the Certificate Registry without a default.");
+                                                       "certificate. Returning 
the Certificate Registry without a default.");
                                        return;
                                }
                                master.put(DEFAULT_SSL_KEY, defaultHd);
                        }
                }
+
+               if (!master.containsKey(defaultAlias)) {
+                       if (handshakeDataMap.containsKey(defaultAlias)) {
+                               master.put(defaultAlias, 
handshakeDataMap.get(defaultAlias));
+                       } else {
+                               final HandshakeData apiDefault = 
createApiDefaultSsl();
+                               if (apiDefault == null) {
+                                       log.error("Failed to initialize the API 
Default certificate.");
+                               } else {
+                                       master.put(apiDefault.getHostname(), 
apiDefault);
+                               }
+                       }
+               }
                handshakeDataMap = master;
 
                if (sslEndpoint != null) {
diff --git 
a/traffic_router/connector/src/main/java/com/comcast/cdn/traffic_control/traffic_router/utils/HttpsProperties.java
 
b/traffic_router/connector/src/main/java/com/comcast/cdn/traffic_control/traffic_router/utils/HttpsProperties.java
new file mode 100644
index 0000000..259da8f
--- /dev/null
+++ 
b/traffic_router/connector/src/main/java/com/comcast/cdn/traffic_control/traffic_router/utils/HttpsProperties.java
@@ -0,0 +1,53 @@
+/*
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.
+ */
+
+package com.comcast.cdn.traffic_control.traffic_router.utils;
+
+import org.apache.log4j.Logger;
+
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.HashMap;
+import java.util.Map;
+
+public class HttpsProperties {
+    private static final Logger log = Logger.getLogger(HttpsProperties.class);
+    private static final String HTTPS_PROPERTIES_FILE = 
"/opt/traffic_router/conf/https.properties";
+    private final Map<String, String> httpsPropertiesMap;
+
+    public HttpsProperties() {
+        this.httpsPropertiesMap = loadHttpsProperties();
+    }
+
+    public Map<String, String> getHttpsPropertiesMap() {
+        return httpsPropertiesMap;
+    }
+
+    private static Map<String, String> loadHttpsProperties() {
+        try {
+            final Map<String, String> httpsProperties = new HashMap<>();
+            
Files.readAllLines(Paths.get(HTTPS_PROPERTIES_FILE)).forEach(propString -> {
+                if (!propString.startsWith("#")) { // Ignores comments in 
properties file
+                    final String[] prop = propString.split("=");
+                    httpsProperties.put(prop[0], prop[1]);
+                }
+            });
+            return httpsProperties;
+        } catch (Exception e) {
+            log.error("Error loading https properties file.");
+            return null;
+        }
+    }
+}
diff --git a/traffic_router/core/src/main/conf/https.properties 
b/traffic_router/core/src/main/conf/https.properties
new file mode 100644
index 0000000..e5c1791
--- /dev/null
+++ b/traffic_router/core/src/main/conf/https.properties
@@ -0,0 +1,16 @@
+#
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+# 
+# 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.
+#
+https.certificate.location=/opt/traffic_router/conf/keyStore.jks
+https.password=changeit
\ No newline at end of file
diff --git a/traffic_router/core/src/main/conf/server.xml 
b/traffic_router/core/src/main/conf/server.xml
index 7aeea6b..49750fb 100644
--- a/traffic_router/core/src/main/conf/server.xml
+++ b/traffic_router/core/src/main/conf/server.xml
@@ -39,6 +39,10 @@
                                        sendReasonPhrase="true"/>
                <Connector port="3333" 
protocol="com.comcast.cdn.traffic_control.traffic_router.protocol.LanguidNioProtocol"
 maxThreads="10000"
                                   connectionTimeout="10000" 
mbeanPath="traffic-router:name=languidState" readyAttribute="Ready" 
portAttribute="ApiPort"/>
+               <Connector port="3443" 
protocol="com.comcast.cdn.traffic_control.traffic_router.protocol.LanguidNioProtocol"
 maxThreads="10000"
+                                  scheme="https" secure="true" 
SSLEnabled="true" clientAuth="false" sslProtocol="TLS" connectionTimeout="10000"
+                                  mbeanPath="traffic-router:name=languidState" 
readyAttribute="Ready" portAttribute="SecureApiPort" sendReasonPhrase="true"
+                                  
sslImplementationName="com.comcast.cdn.traffic_control.traffic_router.protocol.RouterSslImplementation">
 </Connector>
                <Connector port="443" 
protocol="com.comcast.cdn.traffic_control.traffic_router.protocol.LanguidNioProtocol"
 maxThreads="10000"
                                   scheme="https" secure="true" 
SSLEnabled="true" clientAuth="false" sslProtocol="TLS" connectionTimeout="10000"
                                   mbeanPath="traffic-router:name=languidState" 
readyAttribute="Ready" portAttribute="SecurePort" sendReasonPhrase="true"
diff --git 
a/traffic_router/core/src/main/java/com/comcast/cdn/traffic_control/traffic_router/core/http/RouterFilter.java
 
b/traffic_router/core/src/main/java/com/comcast/cdn/traffic_control/traffic_router/core/http/RouterFilter.java
index d683c95..74d713c 100644
--- 
a/traffic_router/core/src/main/java/com/comcast/cdn/traffic_control/traffic_router/core/http/RouterFilter.java
+++ 
b/traffic_router/core/src/main/java/com/comcast/cdn/traffic_control/traffic_router/core/http/RouterFilter.java
@@ -56,7 +56,7 @@ public class RouterFilter extends OncePerRequestFilter {
        public void doFilterInternal(final HttpServletRequest request, final 
HttpServletResponse response, final FilterChain chain) throws IOException, 
ServletException {
                final Date requestDate = new Date();
 
-               if (request.getLocalPort() == 
trafficRouterManager.getApiPort()) {
+               if (request.getLocalPort() == trafficRouterManager.getApiPort() 
|| request.getLocalPort() == trafficRouterManager.getSecureApiPort()) {
                        chain.doFilter(request, response);
                        return;
                }
diff --git 
a/traffic_router/core/src/main/java/com/comcast/cdn/traffic_control/traffic_router/core/router/TrafficRouterManager.java
 
b/traffic_router/core/src/main/java/com/comcast/cdn/traffic_control/traffic_router/core/router/TrafficRouterManager.java
index 941ba51..163f996 100644
--- 
a/traffic_router/core/src/main/java/com/comcast/cdn/traffic_control/traffic_router/core/router/TrafficRouterManager.java
+++ 
b/traffic_router/core/src/main/java/com/comcast/cdn/traffic_control/traffic_router/core/router/TrafficRouterManager.java
@@ -38,6 +38,7 @@ public class TrafficRouterManager implements 
ApplicationListener<ContextRefreshe
        private static final Logger LOGGER = 
Logger.getLogger(TrafficRouterManager.class);
 
        public static final int DEFAULT_API_PORT = 3333;
+       public static final int DEFAULT_SECURE_API_PORT = 0; // Must be set 
through server.xml properties
 
        private JsonNode state;
        private TrafficRouter trafficRouter;
@@ -52,6 +53,7 @@ public class TrafficRouterManager implements 
ApplicationListener<ContextRefreshe
        private SteeringRegistry steeringRegistry;
        private ApplicationContext applicationContext;
        private int apiPort = DEFAULT_API_PORT;
+       private int secureApiPort = DEFAULT_SECURE_API_PORT;
 
        public NameServer getNameServer() {
                return nameServer;
@@ -164,4 +166,12 @@ public class TrafficRouterManager implements 
ApplicationListener<ContextRefreshe
        public int getApiPort() {
                return apiPort;
        }
+
+       public int getSecureApiPort() {
+               return secureApiPort;
+       }
+
+       public void setSecureApiPort(final int secureApiPort) {
+               this.secureApiPort = secureApiPort;
+       }
 }
diff --git 
a/traffic_router/core/src/main/java/com/comcast/cdn/traffic_control/traffic_router/core/util/LanguidState.java
 
b/traffic_router/core/src/main/java/com/comcast/cdn/traffic_control/traffic_router/core/util/LanguidState.java
index e229515..6218ddf 100644
--- 
a/traffic_router/core/src/main/java/com/comcast/cdn/traffic_control/traffic_router/core/util/LanguidState.java
+++ 
b/traffic_router/core/src/main/java/com/comcast/cdn/traffic_control/traffic_router/core/util/LanguidState.java
@@ -32,6 +32,7 @@ public class LanguidState {
        private int port = 0;
        private int apiPort = 0;
        private int securePort = 0;
+       private int secureApiPort = 0;
 
        public void init() {
                if (trafficRouterManager == null || 
trafficRouterManager.getTrafficRouter() == null) {
@@ -84,6 +85,11 @@ public class LanguidState {
                if (routerJson.has("secure.port")) {
                        setSecurePort(routerJson.get("secure.port").asInt());
                }
+
+               if (routerJson.has("secure.api.port")) {
+                       
setSecureApiPort(routerJson.get("secure.api.port").asInt());
+                       trafficRouterManager.setSecureApiPort(secureApiPort);
+               }
        }
 
        public boolean isReady() {
@@ -125,4 +131,12 @@ public class LanguidState {
        public void setSecurePort(final int securePort) {
                this.securePort = securePort;
        }
+
+       public int getSecureApiPort() {
+               return secureApiPort;
+       }
+
+       public void setSecureApiPort(final int secureApiPort) {
+               this.secureApiPort = secureApiPort;
+       }
 }
diff --git 
a/traffic_router/core/src/main/lib/systemd/system/traffic_router.service 
b/traffic_router/core/src/main/lib/systemd/system/traffic_router.service
index ffe4dee..2b26ca4 100755
--- a/traffic_router/core/src/main/lib/systemd/system/traffic_router.service
+++ b/traffic_router/core/src/main/lib/systemd/system/traffic_router.service
@@ -25,6 +25,7 @@ Environment=CATALINA_HOME=/opt/tomcat
 Environment=CATALINA_BASE=/opt/traffic_router
 Environment=CATALINA_OUT=/opt/tomcat/logs/catalina.log
 EnvironmentFile=/opt/traffic_router/conf/startup.properties
+ExecStartPre=/bin/bash /opt/traffic_router/conf/generatingCerts.sh
 ExecStart=/opt/tomcat/bin/startup.sh
 ExecStop=/opt/tomcat/bin/shutdown.sh
 LimitNOFILE=500000
diff --git a/traffic_router/core/src/main/scripts/postinstall.sh 
b/traffic_router/core/src/main/scripts/postinstall.sh
index c4c1e33..1c017ec 100644
--- a/traffic_router/core/src/main/scripts/postinstall.sh
+++ b/traffic_router/core/src/main/scripts/postinstall.sh
@@ -1,3 +1,4 @@
+#!/bin/bash
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -11,12 +12,12 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 #
+keytool=$(dirname $(readlink -f $(which java)))/keytool
+cd /opt/traffic_router/conf
 if [ -f /opt/traffic_router/conf/*.crt ]; then
-       cd /opt/traffic_router/conf
        for file in *.crt; do
                alias=$(echo $file |sed -e 's/.crt//g' |tr [:upper:] [:lower:])
                cacerts=$(/bin/find $(dirname $(readlink -f $(which java)))/.. 
-name cacerts)
-               keytool=$(dirname $(readlink -f $(which java)))/keytool
                $keytool -list -alias $alias -keystore $cacerts -storepass 
changeit -noprompt > /dev/null
 
                if [ $? -ne 0 ]; then
@@ -27,6 +28,17 @@ if [ -f /opt/traffic_router/conf/*.crt ]; then
 fi
 
 
+echo -e "
+cd /opt/traffic_router/conf
+
+keytool=\$(dirname \$(readlink -f \$(which java)))/keytool
+
+if [ ! -f /opt/traffic_router/conf/keyStore.jks ]; then \n
+    \$keytool -genkeypair -v -alias \$(hostname -f) -dname \"CN=\$(hostname 
-f), OU=APIDefault, O=Apache Traffic Control, L=Denver, ST=Colorado, C=US\" 
-keystore \$(pwd)/keyStore.jks -storepass changeit -keyalg RSA -ext 
KeyUsage=\"digitalSignature,keyEncipherment,keyCertSign\" -ext 
BasicConstraints:\"critical=ca:true\" -storetype JKS -validity 3650
+    \$keytool -exportcert -v -alias \$(hostname -f) -file \$(hostname -f).crt 
-keypass changeit -storepass changeit -keystore \$(pwd)/keyStore.jks -rfc
+fi" >> generatingCerts.sh
+chmod 755 generatingCerts.sh
+
 echo "Traffic Router installed successfully."
 
 systemctl daemon-reload
diff --git a/traffic_router/core/src/test/conf/https.properties 
b/traffic_router/core/src/test/conf/https.properties
new file mode 100644
index 0000000..e5c1791
--- /dev/null
+++ b/traffic_router/core/src/test/conf/https.properties
@@ -0,0 +1,16 @@
+#
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+# 
+# 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.
+#
+https.certificate.location=/opt/traffic_router/conf/keyStore.jks
+https.password=changeit
\ No newline at end of file
diff --git 
a/traffic_router/core/src/test/java/com/comcast/cdn/traffic_control/traffic_router/core/CatalinaTrafficRouter.java
 
b/traffic_router/core/src/test/java/com/comcast/cdn/traffic_control/traffic_router/core/CatalinaTrafficRouter.java
index 112c4c3..8e9eac5 100644
--- 
a/traffic_router/core/src/test/java/com/comcast/cdn/traffic_control/traffic_router/core/CatalinaTrafficRouter.java
+++ 
b/traffic_router/core/src/test/java/com/comcast/cdn/traffic_control/traffic_router/core/CatalinaTrafficRouter.java
@@ -22,7 +22,11 @@ import org.apache.catalina.core.StandardHost;
 import org.apache.catalina.core.StandardService;
 import org.apache.catalina.startup.Catalina;
 import org.springframework.util.SocketUtils;
+
+import java.util.Arrays;
+import java.util.List;
 import java.util.logging.Level;
+import java.util.stream.Collectors;
 
 public class CatalinaTrafficRouter {
        Catalina catalina;
@@ -46,6 +50,11 @@ public class CatalinaTrafficRouter {
                // Override the port and app base property of server.xml
                StandardService trafficRouterService = (StandardService) 
catalina.getServer().findService("traffic_router_core");
 
+               List<Connector> secureConnectorList = 
Arrays.stream(trafficRouterService.findConnectors()).filter(k -> 
k.getAttribute("portAttribute").equals("SecureApiPort")).collect(Collectors.toList());
+               boolean hasHttpsPort = secureConnectorList.size() > 0;
+               int securePort = hasHttpsPort ? 
secureConnectorList.get(0).getPort() : 0;
+               int apiPort = 
Arrays.stream(trafficRouterService.findConnectors()).filter(k -> 
k.getAttribute("portAttribute").equals("ApiPort")).collect(Collectors.toList()).get(0).getPort();
+
                Connector[] connectors = trafficRouterService.findConnectors();
                for (Connector connector : connectors) {
                        if (connector.getPort() == 80) {
@@ -57,6 +66,10 @@ public class CatalinaTrafficRouter {
                        if (connector.getPort() == 443) {
                                
connector.setPort(Integer.parseInt(System.getProperty("routerSecurePort", 
"8443")));
                        }
+
+                       if (connector.getPort() == 3443) {
+                               
connector.setPort(Integer.parseInt(System.getProperty("secureApiPort", 
"3443")));
+                       }
                        System.out.println("[" + System.currentTimeMillis() + 
"] >>>>>>>>>>>>>>>> Traffic Router listening on port " + connector.getPort() + 
" " + connector.getScheme());
 
                }

Reply via email to