Skip to content

Commit c778c3d

Browse files
authored
feat(mock): proxy and server auth (#412)
* chore: upgrade actions checkout v4 * feat(mock): add proxy, proxy-user and user flags * feat(mock): add insecure flag
1 parent 2ff0161 commit c778c3d

File tree

8 files changed

+95
-8
lines changed

8 files changed

+95
-8
lines changed

.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ jobs:
2323
# Steps represent a sequence of tasks that will be executed as part of the job
2424
steps:
2525
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
26-
- uses: actions/checkout@v2
26+
- uses: actions/checkout@v4
2727
with:
2828
fetch-depth: 0
2929

.github/workflows/codeql-analysis.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ jobs:
3939

4040
steps:
4141
- name: Checkout repository
42-
uses: actions/checkout@v2
42+
uses: actions/checkout@v4
4343

4444
# Initializes the CodeQL tools for scanning.
4545
- name: Initialize CodeQL

.github/workflows/release.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ jobs:
2121
# Steps represent a sequence of tasks that will be executed as part of the job
2222
steps:
2323
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
24-
- uses: actions/checkout@v2
24+
- uses: actions/checkout@v4
2525
with:
2626
fetch-depth: 0
2727

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@ Types of changes
1414
- `Fixed` for any bug fixes.
1515
- `Security` in case of vulnerabilities.
1616

17+
## [1.31.0]
18+
19+
- `Added` insecure, proxy, proxy-user and user flags to mock command
20+
1721
## [1.30.2]
1822

1923
- `Fixed` mask `findInCSV` memory usage

cmd/pimo/mock.go

Lines changed: 83 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
package main
22

33
import (
4+
"crypto/tls"
45
"net/http"
56
"net/url"
7+
"os"
8+
"strings"
69

710
over "github.com/adrienaury/zeromdc"
811
"github.com/cgi-fr/pimo/internal/app/pimo"
@@ -11,13 +14,31 @@ import (
1114
"github.com/cgi-fr/pimo/pkg/uri"
1215
"github.com/rs/zerolog/log"
1316
"github.com/spf13/cobra"
17+
"golang.org/x/term"
1418
)
1519

1620
// pimo --serve ":8080" --mask 'name=[{add: true}, {randomChoiceInUri: "pimo://nameFR"}]'
1721
// pimo -v5 mock -p :8081 http://localhost:8080
1822

23+
func askPassword(prompt string) string {
24+
if term.IsTerminal(int(os.Stdin.Fd())) {
25+
os.Stdout.Write([]byte(prompt))
26+
bytePassword, err := term.ReadPassword(int(os.Stdin.Fd()))
27+
os.Stdout.Write([]byte("\n"))
28+
if err != nil {
29+
os.Exit(1)
30+
}
31+
return string(bytePassword)
32+
}
33+
return ""
34+
}
35+
1936
func setupMockCommand(rootCmd *cobra.Command) {
2037
mockAddr := ":8080"
38+
proxyURL := ""
39+
proxyAuth := ""
40+
serverAuth := ""
41+
insecure := false
2142

2243
mockCmd := &cobra.Command{
2344
Use: "mock",
@@ -34,12 +55,57 @@ func setupMockCommand(rootCmd *cobra.Command) {
3455
if cmd.Flags().Changed("seed") {
3556
globalSeed = &seedValue
3657
}
37-
runMockCommand(backendURL, mockAddr, mockConfigFile, globalSeed)
58+
59+
client := http.DefaultClient
60+
if proxyURL != "" {
61+
proxyURLParsed, err := url.Parse(proxyURL)
62+
if err != nil {
63+
log.Fatal().Err(err).Msg("Failed to parse proxy URL")
64+
}
65+
if proxyAuth != "" {
66+
if !strings.Contains(proxyAuth, ":") {
67+
password := askPassword("enter password for proxy authentication: ")
68+
proxyAuth = proxyAuth + ":" + password
69+
}
70+
proxyURLParsed.User = url.UserPassword(strings.Split(proxyAuth, ":")[0], strings.Split(proxyAuth, ":")[1])
71+
}
72+
client.Transport = &http.Transport{
73+
Proxy: http.ProxyURL(proxyURLParsed),
74+
}
75+
}
76+
77+
if insecure {
78+
if client.Transport == nil {
79+
client.Transport = &http.Transport{
80+
TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, //nolint:gosec
81+
}
82+
} else {
83+
client.Transport.(*http.Transport).TLSClientConfig = &tls.Config{InsecureSkipVerify: true} //nolint:gosec
84+
}
85+
}
86+
87+
if serverAuth != "" {
88+
if !strings.Contains(serverAuth, ":") {
89+
password := askPassword("enter password for server authentication: ")
90+
proxyAuth = proxyAuth + ":" + password
91+
}
92+
client.Transport = &TransportWithAuth{
93+
wrapped: client.Transport,
94+
user: strings.Split(serverAuth, ":")[0],
95+
pass: strings.Split(serverAuth, ":")[1],
96+
}
97+
}
98+
99+
runMockCommand(backendURL, mockAddr, mockConfigFile, globalSeed, client)
38100
},
39101
Args: cobra.ExactArgs(1),
40102
}
41103

42104
mockCmd.PersistentFlags().StringVarP(&mockAddr, "port", "p", mockAddr, "address and port number")
105+
mockCmd.PersistentFlags().StringVarP(&proxyURL, "proxy", "x", proxyURL, "use the specified proxy to perform backend request")
106+
mockCmd.PersistentFlags().StringVarP(&proxyAuth, "proxy-user", "U", proxyAuth, "specify user:password to use for proxy authentication")
107+
mockCmd.PersistentFlags().StringVarP(&serverAuth, "user", "u", serverAuth, "specify user:password to use for server authentication")
108+
mockCmd.PersistentFlags().BoolVarP(&insecure, "insecure", "k", insecure, "allow insecure server connections when using SSL")
43109
addFlag(mockCmd, flagBufferSize)
44110
// addFlag(mockCmd, flagCatchErrors) // could use
45111
addFlag(mockCmd, flagConfigRoute)
@@ -56,7 +122,21 @@ func setupMockCommand(rootCmd *cobra.Command) {
56122
rootCmd.AddCommand(mockCmd)
57123
}
58124

59-
func runMockCommand(backendURL, mockAddr, configFile string, globalSeed *int64) {
125+
type TransportWithAuth struct {
126+
wrapped http.RoundTripper
127+
user string
128+
pass string
129+
}
130+
131+
func (t *TransportWithAuth) RoundTrip(req *http.Request) (*http.Response, error) {
132+
req.SetBasicAuth(t.user, t.pass)
133+
if t.wrapped == nil {
134+
return http.DefaultTransport.RoundTrip(req)
135+
}
136+
return t.wrapped.RoundTrip(req)
137+
}
138+
139+
func runMockCommand(backendURL, mockAddr, configFile string, globalSeed *int64, client *http.Client) {
60140
pimo.InjectMasks()
61141
statistics.Reset()
62142

@@ -72,7 +152,7 @@ func runMockCommand(backendURL, mockAddr, configFile string, globalSeed *int64)
72152
log.Fatal().Err(err).Msg("Failed to parse backend URL")
73153
}
74154

75-
ctx, err := cfg.Build(backend, globalSeed, cachesToLoad)
155+
ctx, err := cfg.Build(backend, globalSeed, cachesToLoad, client)
76156
if err != nil {
77157
log.Fatal().Err(err).Msgf("Failed to build routes from %s", configFile)
78158
}

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ require (
2424
github.com/zach-klippenstein/goregen v0.0.0-20160303162051-795b5e3961ea
2525
golang.org/x/crypto v0.36.0
2626
golang.org/x/exp v0.0.0-20240707233637-46b078467d37
27+
golang.org/x/term v0.30.0
2728
golang.org/x/text v0.23.0
2829
)
2930

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,8 @@ golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
178178
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
179179
golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik=
180180
golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
181+
golang.org/x/term v0.30.0 h1:PQ39fJZ+mfadBm0y5WlL4vlM7Sx1Hgf13sMIY2+QS9Y=
182+
golang.org/x/term v0.30.0/go.mod h1:NYYFdzHoI5wRh/h5tDMdMqCqPJZEuNqVR5xJLd/n67g=
181183
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
182184
golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY=
183185
golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4=

internal/app/pimo/mock/routes.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,9 @@ func LoadConfigFromFile(filename string) (*Config, error) {
3939
return config, nil
4040
}
4141

42-
func (cfg *Config) Build(backend *url.URL, globalSeed *int64, cachesToLoad map[string]string) (Context, error) {
42+
func (cfg *Config) Build(backend *url.URL, globalSeed *int64, cachesToLoad map[string]string, client *http.Client) (Context, error) {
4343
ctx := Context{
44-
client: http.DefaultClient,
44+
client: client,
4545
backend: backend,
4646
routes: []ContextRoute{},
4747
caches: map[string]model.Cache{},

0 commit comments

Comments
 (0)