@@ -2,6 +2,7 @@ package cli
2
2
3
3
import (
4
4
"context"
5
+ "crypto/tls"
5
6
"encoding/json"
6
7
"errors"
7
8
"fmt"
@@ -27,6 +28,7 @@ import (
27
28
ecv1beta1 "github.com/replicatedhq/embedded-cluster/kinds/apis/v1beta1"
28
29
"github.com/replicatedhq/embedded-cluster/kinds/types"
29
30
newconfig "github.com/replicatedhq/embedded-cluster/pkg-new/config"
31
+ "github.com/replicatedhq/embedded-cluster/pkg-new/tlsutils"
30
32
"github.com/replicatedhq/embedded-cluster/pkg/addons"
31
33
"github.com/replicatedhq/embedded-cluster/pkg/addons/adminconsole"
32
34
"github.com/replicatedhq/embedded-cluster/pkg/addons/embeddedclusteroperator"
@@ -85,6 +87,9 @@ type InstallCmdFlags struct {
85
87
// guided UI flags
86
88
managerPort int
87
89
guidedUI bool
90
+ certFile string
91
+ keyFile string
92
+ hostname string
88
93
}
89
94
90
95
// InstallCmd returns a cobra command for installing the embedded cluster.
@@ -207,13 +212,25 @@ func addInstallAdminConsoleFlags(cmd *cobra.Command, flags *InstallCmdFlags) err
207
212
func addGuidedUIFlags (cmd * cobra.Command , flags * InstallCmdFlags ) error {
208
213
cmd .Flags ().BoolVarP (& flags .guidedUI , "guided-ui" , "g" , false , "Run the installation in guided UI mode." )
209
214
cmd .Flags ().IntVar (& flags .managerPort , "manager-port" , ecv1beta1 .DefaultManagerPort , "Port on which the Manager will be served" )
215
+ cmd .Flags ().StringVar (& flags .certFile , "cert-file" , "" , "Path to the TLS certificate file" )
216
+ cmd .Flags ().StringVar (& flags .keyFile , "key-file" , "" , "Path to the TLS key file" )
217
+ cmd .Flags ().StringVar (& flags .hostname , "hostname" , "" , "Hostname to use for TLS configuration" )
210
218
211
219
if err := cmd .Flags ().MarkHidden ("guided-ui" ); err != nil {
212
220
return err
213
221
}
214
222
if err := cmd .Flags ().MarkHidden ("manager-port" ); err != nil {
215
223
return err
216
224
}
225
+ if err := cmd .Flags ().MarkHidden ("cert-file" ); err != nil {
226
+ return err
227
+ }
228
+ if err := cmd .Flags ().MarkHidden ("key-file" ); err != nil {
229
+ return err
230
+ }
231
+ if err := cmd .Flags ().MarkHidden ("hostname" ); err != nil {
232
+ return err
233
+ }
217
234
218
235
return nil
219
236
}
@@ -261,13 +278,30 @@ func preRunInstall(cmd *cobra.Command, flags *InstallCmdFlags) error {
261
278
configChan := make (chan * apitypes.InstallationConfig )
262
279
defer close (configChan )
263
280
264
- if err := preRunInstallAPI (cmd .Context (), flags .adminConsolePassword , flags .managerPort , configChan ); err != nil {
281
+ // this is necessary because the api listens on all interfaces,
282
+ // and we only know the interface to use when the user selects it in the ui
283
+ ipAddresses , err := netutils .ListAllValidIPAddresses ()
284
+ if err != nil {
285
+ return fmt .Errorf ("unable to list all valid IP addresses: %w" , err )
286
+ }
287
+
288
+ cert , err := tlsutils .GetCertificate (tlsutils.Config {
289
+ CertFile : flags .certFile ,
290
+ KeyFile : flags .keyFile ,
291
+ Hostname : flags .hostname ,
292
+ IPAddresses : ipAddresses ,
293
+ })
294
+ if err != nil {
295
+ return fmt .Errorf ("get tls certificate: %w" , err )
296
+ }
297
+
298
+ if err := preRunInstallAPI (cmd .Context (), cert , flags .adminConsolePassword , flags .managerPort , configChan ); err != nil {
265
299
return fmt .Errorf ("unable to start install API: %w" , err )
266
300
}
267
301
268
302
// TODO: fix this message
269
303
logrus .Info ("" )
270
- logrus .Infof ("Visit %s to configure your cluster" , getManagerURL (flags .managerPort ))
304
+ logrus .Infof ("Visit %s to configure your cluster" , getManagerURL (flags .hostname , flags . managerPort ))
271
305
272
306
installConfig , ok := <- configChan
273
307
if ! ok {
@@ -363,7 +397,7 @@ func preRunInstall(cmd *cobra.Command, flags *InstallCmdFlags) error {
363
397
return nil
364
398
}
365
399
366
- func preRunInstallAPI (ctx context.Context , password string , managerPort int , configChan chan <- * apitypes.InstallationConfig ) error {
400
+ func preRunInstallAPI (ctx context.Context , cert tls. Certificate , password string , managerPort int , configChan chan <- * apitypes.InstallationConfig ) error {
367
401
logger , err := api .NewLogger ()
368
402
if err != nil {
369
403
logrus .Warnf ("Unable to setup API logging: %v" , err )
@@ -375,7 +409,7 @@ func preRunInstallAPI(ctx context.Context, password string, managerPort int, con
375
409
}
376
410
377
411
go func () {
378
- if err := runInstallAPI (ctx , listener , logger , password , configChan ); err != nil {
412
+ if err := runInstallAPI (ctx , listener , cert , logger , password , configChan ); err != nil {
379
413
if ! errors .Is (err , http .ErrServerClosed ) {
380
414
logrus .Errorf ("install API error: %v" , err )
381
415
}
@@ -389,7 +423,7 @@ func preRunInstallAPI(ctx context.Context, password string, managerPort int, con
389
423
return nil
390
424
}
391
425
392
- func runInstallAPI (ctx context.Context , listener net.Listener , logger logrus.FieldLogger , password string , configChan chan <- * apitypes.InstallationConfig ) error {
426
+ func runInstallAPI (ctx context.Context , listener net.Listener , cert tls. Certificate , logger logrus.FieldLogger , password string , configChan chan <- * apitypes.InstallationConfig ) error {
393
427
router := mux .NewRouter ()
394
428
395
429
api , err := api .New (
@@ -412,7 +446,8 @@ func runInstallAPI(ctx context.Context, listener net.Listener, logger logrus.Fie
412
446
router .PathPrefix ("/" ).Methods ("GET" ).Handler (webFs )
413
447
414
448
server := & http.Server {
415
- Handler : router ,
449
+ Handler : router ,
450
+ TLSConfig : tlsutils .GetTLSConfig (cert ),
416
451
}
417
452
418
453
go func () {
@@ -421,15 +456,17 @@ func runInstallAPI(ctx context.Context, listener net.Listener, logger logrus.Fie
421
456
server .Shutdown (context .Background ())
422
457
}()
423
458
424
- logrus .Debugf ("Install API listening on %s" , listener .Addr ().String ())
425
- return server .Serve (listener )
459
+ return server .ServeTLS (listener , "" , "" )
426
460
}
427
461
428
462
func waitForInstallAPI (ctx context.Context , addr string ) error {
429
463
httpClient := http.Client {
430
464
Timeout : 2 * time .Second ,
431
465
Transport : & http.Transport {
432
466
Proxy : nil ,
467
+ TLSClientConfig : & tls.Config {
468
+ InsecureSkipVerify : true ,
469
+ },
433
470
},
434
471
}
435
472
timeout := time .After (10 * time .Second )
@@ -442,7 +479,7 @@ func waitForInstallAPI(ctx context.Context, addr string) error {
442
479
}
443
480
return fmt .Errorf ("install API did not start in time" )
444
481
case <- time .Tick (1 * time .Second ):
445
- resp , err := httpClient .Get (fmt .Sprintf ("http ://%s/api/health" , addr ))
482
+ resp , err := httpClient .Get (fmt .Sprintf ("https ://%s/api/health" , addr ))
446
483
if err != nil {
447
484
lastErr = fmt .Errorf ("unable to connect to install API: %w" , err )
448
485
} else if resp .StatusCode == http .StatusOK {
@@ -578,7 +615,7 @@ func runInstall(ctx context.Context, name string, flags InstallCmdFlags, metrics
578
615
return fmt .Errorf ("unable to mark ui install complete: %w" , err )
579
616
}
580
617
} else {
581
- if err := printSuccessMessage (flags .license , flags .networkInterface ); err != nil {
618
+ if err := printSuccessMessage (flags .license , flags .hostname , flags . networkInterface ); err != nil {
582
619
return err
583
620
}
584
621
}
@@ -1484,8 +1521,8 @@ func copyLicenseFileToDataDir(licenseFile, dataDir string) error {
1484
1521
return nil
1485
1522
}
1486
1523
1487
- func printSuccessMessage (license * kotsv1beta1.License , networkInterface string ) error {
1488
- adminConsoleURL := getAdminConsoleURL (networkInterface , runtimeconfig .AdminConsolePort ())
1524
+ func printSuccessMessage (license * kotsv1beta1.License , hostname string , networkInterface string ) error {
1525
+ adminConsoleURL := getAdminConsoleURL (hostname , networkInterface , runtimeconfig .AdminConsolePort ())
1489
1526
1490
1527
// Create the message content
1491
1528
message := fmt .Sprintf ("Visit the Admin Console to configure and install %s:" , license .Spec .AppSlug )
@@ -1515,7 +1552,10 @@ func printSuccessMessage(license *kotsv1beta1.License, networkInterface string)
1515
1552
return nil
1516
1553
}
1517
1554
1518
- func getManagerURL (port int ) string {
1555
+ func getManagerURL (hostname string , port int ) string {
1556
+ if hostname != "" {
1557
+ return fmt .Sprintf ("https://%s:%v" , hostname , port )
1558
+ }
1519
1559
ipaddr := runtimeconfig .TryDiscoverPublicIP ()
1520
1560
if ipaddr == "" {
1521
1561
if addr := os .Getenv ("EC_PUBLIC_ADDRESS" ); addr != "" {
@@ -1525,10 +1565,13 @@ func getManagerURL(port int) string {
1525
1565
ipaddr = "NODE-IP-ADDRESS"
1526
1566
}
1527
1567
}
1528
- return fmt .Sprintf ("http ://%s:%v" , ipaddr , port )
1568
+ return fmt .Sprintf ("https ://%s:%v" , ipaddr , port )
1529
1569
}
1530
1570
1531
- func getAdminConsoleURL (networkInterface string , port int ) string {
1571
+ func getAdminConsoleURL (hostname string , networkInterface string , port int ) string {
1572
+ if hostname != "" {
1573
+ return fmt .Sprintf ("http://%s:%v" , hostname , port )
1574
+ }
1532
1575
ipaddr := runtimeconfig .TryDiscoverPublicIP ()
1533
1576
if ipaddr == "" {
1534
1577
var err error
0 commit comments