Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 11 additions & 3 deletions src/cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"fmt"
"os"

"github.com/phasehq/cli/pkg/config"
phaseerrors "github.com/phasehq/cli/pkg/errors"
"github.com/phasehq/cli/pkg/version"
"github.com/spf13/cobra"
Expand All @@ -25,9 +26,9 @@ const phaseASCii = `
const description = "Keep Secrets."

var rootCmd = &cobra.Command{
Use: "phase",
Short: description,
Long: description + "\n" + phaseASCii,
Use: "phase",
Short: description,
Long: description + "\n" + phaseASCii,
SilenceUsage: true,
SilenceErrors: true,
}
Expand All @@ -40,6 +41,13 @@ func Execute() {
}

func init() {
// Honor PHASE_VERIFY_SSL=False before any command runs so it applies to
// every network call β€” including pre-auth flows like
// `phase auth --mode aws-iam` / `--mode azure` that don't go through
// NewPhase(). The SDK caches its HTTP client on first use, so this must
// happen before any request is made.
config.ConfigureSSLVerification()

rootCmd.Version = version.Version
rootCmd.SetVersionTemplate("{{ .Version }}\n")

Expand Down
24 changes: 24 additions & 0 deletions src/pkg/config/env.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package config

import (
"os"
"strings"

"github.com/phasehq/golang-sdk/v2/phase/misc"
)

// ConfigureSSLVerification reads the PHASE_VERIFY_SSL environment variable and
// disables TLS certificate verification in the SDK when it is set to "false"
// (case-insensitive). Any other value β€” or the variable being unset β€” keeps
// verification enabled. This mirrors the Python CLI's behavior
// (os.environ.get("PHASE_VERIFY_SSL", "True").lower() != "false") and makes
// the hint shown in SSL error messages ("You may set PHASE_VERIFY_SSL=False
// to bypass this check") actually work.
//
// It must run before any SDK network call: the SDK caches its HTTP client on
// first use, so changes to misc.VerifySSL after that have no effect.
func ConfigureSSLVerification() {
if strings.EqualFold(os.Getenv("PHASE_VERIFY_SSL"), "false") {
misc.VerifySSL = false
}
}
50 changes: 50 additions & 0 deletions src/pkg/config/env_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package config

import (
"os"
"testing"

"github.com/phasehq/golang-sdk/v2/phase/misc"
)

func TestConfigureSSLVerification(t *testing.T) {
tests := []struct {
name string
value string
unset bool
wantVerify bool
}{
{name: "unset keeps verification enabled", unset: true, wantVerify: true},
{name: "empty keeps verification enabled", value: "", wantVerify: true},
{name: "False disables verification", value: "False", wantVerify: false},
{name: "false disables verification", value: "false", wantVerify: false},
{name: "FALSE disables verification", value: "FALSE", wantVerify: false},
{name: "true keeps verification enabled", value: "true", wantVerify: true},
{name: "True keeps verification enabled", value: "True", wantVerify: true},
{name: "zero keeps verification enabled", value: "0", wantVerify: true},
{name: "no keeps verification enabled", value: "no", wantVerify: true},
{name: "arbitrary value keeps verification enabled", value: "banana", wantVerify: true},
}

original := misc.VerifySSL
t.Cleanup(func() { misc.VerifySSL = original })

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
misc.VerifySSL = true // reset the global before each case

// t.Setenv registers restoration of the original value; for the
// unset case we additionally clear it after registration.
t.Setenv("PHASE_VERIFY_SSL", tt.value)
if tt.unset {
os.Unsetenv("PHASE_VERIFY_SSL")
}

ConfigureSSLVerification()

if misc.VerifySSL != tt.wantVerify {
t.Errorf("PHASE_VERIFY_SSL=%q: misc.VerifySSL = %v, want %v", tt.value, misc.VerifySSL, tt.wantVerify)
}
})
}
}
Loading