@@ -30,11 +30,16 @@ package commands
3030
3131import (
3232 "context"
33+ "crypto/tls"
34+ "crypto/x509"
3335 _ "embed"
3436 "fmt"
37+ "net/http"
38+ "net/url"
3539 "os"
3640 "regexp"
3741 "strings"
42+ "time"
3843
3944 "github.com/argoproj-labs/argocd-autopilot/pkg/git"
4045 "github.com/codefresh-io/cli-v2/pkg/config"
@@ -90,6 +95,10 @@ func IsValidName(s string) (bool, error) {
9095 return regexp .MatchString (`^[a-z]([-a-z0-9]{0,61}[a-z0-9])?$` , s )
9196}
9297
98+ func IsValidIngressHost (ingress string ) (bool , error ) {
99+ return regexp .MatchString (`^(http|https)://` , ingress )
100+ }
101+
93102func askUserIfToInstallDemoResources (cmd * cobra.Command , sampleInstall * bool ) error {
94103 if ! store .Get ().Silent && ! cmd .Flags ().Changed ("sample-install" ) {
95104 templates := & promptui.SelectTemplates {
@@ -360,3 +369,94 @@ func getIngressHostFromUserInput(cmd *cobra.Command, ingressHost *string) error
360369
361370 return nil
362371}
372+
373+ func checkIngressHostCertificate (ctx context.Context , ingress string ) (bool , error ) {
374+ var err error
375+ match , _ := regexp .MatchString (`^http://` , ingress )
376+ if match { //if user provided http ingress
377+ log .G (ctx ).Warn ("The ingress host uses an insecure protocol. The browser may block subsequent runtime requests from the UI unless explicitly approved." )
378+
379+ return true , nil
380+ }
381+
382+ res , err := http .Get (ingress )
383+
384+ if err == nil {
385+ res .Body .Close ()
386+ return true , nil
387+ }
388+
389+ urlErr , ok := err .(* url.Error )
390+ if ! ok {
391+ return false , err
392+ }
393+ _ , ok1 := urlErr .Err .(x509.CertificateInvalidError )
394+ _ , ok2 := urlErr .Err .(x509.SystemRootsError )
395+ _ , ok3 := urlErr .Err .(x509.UnknownAuthorityError )
396+ _ , ok4 := urlErr .Err .(x509.ConstraintViolationError )
397+ _ , ok5 := urlErr .Err .(x509.HostnameError )
398+
399+ certErr := ok1 || ok2 || ok3 || ok4 || ok5
400+ if ! certErr {
401+ return false , fmt .Errorf ("failed with non-certificate error: %w" , err )
402+ }
403+
404+ insecureOk := checkIngressHostWithInsecure (ingress )
405+ if ! insecureOk {
406+ return false , fmt .Errorf ("insecure call failed: %w" , err )
407+ }
408+
409+ return false , nil
410+ }
411+
412+ func checkIngressHostWithInsecure (ingress string ) bool {
413+ httpClient := & http.Client {}
414+ httpClient .Timeout = 10 * time .Second
415+ customTransport := http .DefaultTransport .(* http.Transport ).Clone ()
416+ customTransport .TLSClientConfig = & tls.Config {InsecureSkipVerify : true }
417+ httpClient .Transport = customTransport
418+ req , err := http .NewRequest ("GET" , ingress , nil )
419+ if err != nil {
420+ return false
421+ }
422+ res , err := httpClient .Do (req )
423+ if err != nil {
424+ return false
425+ }
426+ res .Body .Close ()
427+ return true
428+ }
429+
430+ func askUserIfToProceedWithInsecure (ctx context.Context ) error {
431+ if store .Get ().InsecureIngressHost {
432+ return nil
433+ }
434+ if store .Get ().Silent {
435+ return fmt .Errorf ("cancelled installation due to invalid ingress host certificate" )
436+ }
437+
438+ templates := & promptui.SelectTemplates {
439+ Selected : "{{ . | yellow }} " ,
440+ }
441+
442+ log .G (ctx ).Warnf ("The provided ingressHost does not have a valid certificate." )
443+ labelStr := fmt .Sprintf ("%vDo you wish to continue the installation with insecure ingress host mode?%v" , CYAN , COLOR_RESET )
444+
445+ prompt := promptui.Select {
446+ Label : labelStr ,
447+ Items : []string {"Yes" , "Cancel installation" },
448+ Templates : templates ,
449+ }
450+
451+ _ , result , err := prompt .Run ()
452+ if err != nil {
453+ return fmt .Errorf ("Prompt error: %w" , err )
454+ }
455+
456+ if result == "Yes" {
457+ store .Get ().InsecureIngressHost = true
458+ } else {
459+ return fmt .Errorf ("cancelled installation due to invalid ingress host certificate" )
460+ }
461+ return nil
462+ }
0 commit comments