github.com/argoproj/argo-cd/v3@v3.2.1/server/server_norace_test.go (about) 1 //go:build !race 2 // +build !race 3 4 package server 5 6 import ( 7 "context" 8 "fmt" 9 "net/http" 10 "os" 11 "strings" 12 "testing" 13 "time" 14 15 "github.com/stretchr/testify/assert" 16 "github.com/stretchr/testify/require" 17 18 "github.com/argoproj/argo-cd/v3/common" 19 "github.com/argoproj/argo-cd/v3/pkg/apiclient" 20 applicationpkg "github.com/argoproj/argo-cd/v3/pkg/apiclient/application" 21 "github.com/argoproj/argo-cd/v3/test" 22 ) 23 24 func TestUserAgent(t *testing.T) { 25 // !race: 26 // A data race in go-client's `shared_informer.go`, between `sharedProcessor.run(...)` and itself. Based on 27 // the data race, it APPEARS to be intentional, but in any case it's nothing we are doing in Argo CD 28 // that is causing this issue. 29 30 s, closer := fakeServer(t) 31 defer closer() 32 lns, err := s.Listen() 33 require.NoError(t, err) 34 35 cancelInformer := test.StartInformer(s.projInformer) 36 defer cancelInformer() 37 ctx, cancel := context.WithCancel(t.Context()) 38 defer cancel() 39 s.Init(ctx) 40 go s.Run(ctx, lns) 41 defer time.Sleep(3 * time.Second) 42 43 type testData struct { 44 userAgent string 45 errorMsg string 46 } 47 currentVersionBytes, err := os.ReadFile("../VERSION") 48 require.NoError(t, err) 49 currentVersion := strings.TrimSpace(string(currentVersionBytes)) 50 tests := []testData{ 51 { 52 // Reject out-of-date user-agent 53 userAgent: common.ArgoCDUserAgentName + "/0.10.0", 54 errorMsg: "unsatisfied client version constraint", 55 }, 56 { 57 // Accept up-to-date user-agent 58 userAgent: fmt.Sprintf("%s/%s", common.ArgoCDUserAgentName, currentVersion), 59 }, 60 { 61 // Accept up-to-date pre-release user-agent 62 userAgent: fmt.Sprintf("%s/%s-rc1", common.ArgoCDUserAgentName, currentVersion), 63 }, 64 { 65 // Permit custom clients 66 userAgent: "foo/1.2.3", 67 }, 68 } 69 70 for _, test := range tests { 71 opts := apiclient.ClientOptions{ 72 ServerAddr: fmt.Sprintf("localhost:%d", s.ListenPort), 73 PlainText: true, 74 UserAgent: test.userAgent, 75 } 76 clnt, err := apiclient.NewClient(&opts) 77 require.NoError(t, err) 78 conn, appClnt := clnt.NewApplicationClientOrDie() 79 _, err = appClnt.List(ctx, &applicationpkg.ApplicationQuery{}) 80 if test.errorMsg != "" { 81 require.Error(t, err) 82 assert.Regexp(t, test.errorMsg, err.Error()) 83 } else { 84 require.NoError(t, err) 85 } 86 _ = conn.Close() 87 } 88 } 89 90 func Test_StaticHeaders(t *testing.T) { 91 // !race: 92 // Same as TestUserAgent 93 94 // Test default policy "sameorigin" and "frame-ancestors 'self';" 95 { 96 s, closer := fakeServer(t) 97 defer closer() 98 lns, err := s.Listen() 99 require.NoError(t, err) 100 cancelInformer := test.StartInformer(s.projInformer) 101 defer cancelInformer() 102 ctx, cancel := context.WithCancel(t.Context()) 103 defer cancel() 104 s.Init(ctx) 105 go s.Run(ctx, lns) 106 defer time.Sleep(3 * time.Second) 107 108 // Allow server startup 109 time.Sleep(1 * time.Second) 110 111 client := http.Client{} 112 url := fmt.Sprintf("http://127.0.0.1:%d/test.html", s.ListenPort) 113 req, err := http.NewRequest(http.MethodGet, url, http.NoBody) 114 require.NoError(t, err) 115 resp, err := client.Do(req) 116 require.NoError(t, err) 117 assert.Equal(t, "sameorigin", resp.Header.Get("X-Frame-Options")) 118 assert.Equal(t, "frame-ancestors 'self';", resp.Header.Get("Content-Security-Policy")) 119 } 120 121 // Test custom policy for X-Frame-Options and Content-Security-Policy 122 { 123 s, closer := fakeServer(t) 124 defer closer() 125 s.XFrameOptions = "deny" 126 s.ContentSecurityPolicy = "frame-ancestors 'none';" 127 cancelInformer := test.StartInformer(s.projInformer) 128 defer cancelInformer() 129 lns, err := s.Listen() 130 require.NoError(t, err) 131 ctx, cancel := context.WithCancel(t.Context()) 132 defer cancel() 133 s.Init(ctx) 134 go s.Run(ctx, lns) 135 defer time.Sleep(3 * time.Second) 136 137 // Allow server startup 138 time.Sleep(1 * time.Second) 139 140 client := http.Client{} 141 url := fmt.Sprintf("http://127.0.0.1:%d/test.html", s.ListenPort) 142 req, err := http.NewRequest(http.MethodGet, url, http.NoBody) 143 require.NoError(t, err) 144 resp, err := client.Do(req) 145 require.NoError(t, err) 146 assert.Equal(t, "deny", resp.Header.Get("X-Frame-Options")) 147 assert.Equal(t, "frame-ancestors 'none';", resp.Header.Get("Content-Security-Policy")) 148 } 149 150 // Test disabled X-Frame-Options and Content-Security-Policy 151 { 152 s, closer := fakeServer(t) 153 defer closer() 154 s.XFrameOptions = "" 155 s.ContentSecurityPolicy = "" 156 cancelInformer := test.StartInformer(s.projInformer) 157 defer cancelInformer() 158 lns, err := s.Listen() 159 require.NoError(t, err) 160 ctx, cancel := context.WithCancel(t.Context()) 161 defer cancel() 162 s.Init(ctx) 163 go s.Run(ctx, lns) 164 defer time.Sleep(3 * time.Second) 165 166 err = test.WaitForPortListen(fmt.Sprintf("127.0.0.1:%d", s.ListenPort), 10*time.Second) 167 require.NoError(t, err) 168 169 // Allow server startup 170 time.Sleep(1 * time.Second) 171 172 client := http.Client{} 173 url := fmt.Sprintf("http://127.0.0.1:%d/test.html", s.ListenPort) 174 req, err := http.NewRequest(http.MethodGet, url, http.NoBody) 175 require.NoError(t, err) 176 resp, err := client.Do(req) 177 require.NoError(t, err) 178 assert.Empty(t, resp.Header.Get("X-Frame-Options")) 179 assert.Empty(t, resp.Header.Get("Content-Security-Policy")) 180 } 181 }