forked from gitea/gitea
		
	Provide configuration to allow camo-media proxying (#12802)
* Provide configuration to allow camo-media proxying Fix #916 Signed-off-by: Andrew Thornton <art27@cantab.net> Co-authored-by: 6543 <6543@obermui.de> Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
This commit is contained in:
		
							parent
							
								
									76aa33d884
								
							
						
					
					
						commit
						97625b44e7
					
				| @ -424,6 +424,23 @@ INTERNAL_TOKEN= | ||||
| ;; This cache will store the successfully hashed tokens in a LRU cache as a balance between performance and security. | ||||
| ;SUCCESSFUL_TOKENS_CACHE_SIZE = 20 | ||||
| 
 | ||||
| ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||||
| ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||||
| [camo] | ||||
| ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||||
| ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||||
| ;; | ||||
| ;; At the moment we only support images | ||||
| ;; | ||||
| ;; if the camo is enabled | ||||
| ;ENABLED = false | ||||
| ;; url to a camo image proxy, it **is required** if camo is enabled. | ||||
| ;SERVER_URL = | ||||
| ;; HMAC to encode urls with, it **is required** if camo is enabled. | ||||
| ;HMAC_KEY = | ||||
| ;; Set to true to use camo for https too lese only non https urls are proxyed | ||||
| ;ALLWAYS = false | ||||
| 
 | ||||
| ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||||
| ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||||
| [oauth2] | ||||
|  | ||||
| @ -513,7 +513,14 @@ Certain queues have defaults that override the defaults set in `[queue]` (this o | ||||
|     - spec - use one or more special characters as ``!"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~`` | ||||
|     - off - do not check password complexity | ||||
| - `PASSWORD_CHECK_PWN`: **false**: Check [HaveIBeenPwned](https://haveibeenpwned.com/Passwords) to see if a password has been exposed. | ||||
| - `SUCCESSFUL_TOKENS_CACHE_SIZE`: **20**: Cache successful token hashes. API tokens are stored in the DB as pbkdf2 hashes however, this means that there is a potentially significant hashing load when there are multiple API operations. This cache will store the successfully hashed tokens in a LRU cache as a balance between performance and security.  | ||||
| - `SUCCESSFUL_TOKENS_CACHE_SIZE`: **20**: Cache successful token hashes. API tokens are stored in the DB as pbkdf2 hashes however, this means that there is a potentially significant hashing load when there are multiple API operations. This cache will store the successfully hashed tokens in a LRU cache as a balance between performance and security. | ||||
| 
 | ||||
| ## Camo (`camo`) | ||||
| 
 | ||||
| - `ENABLED`: **false**: Enable media proxy, we support images only at the moment. | ||||
| - `SERVER_URL`: **<empty>**: url of camo server, it **is required** if camo is enabled. | ||||
| - `HMAC_KEY`: **<empty>**: Provide the HMAC key for encoding urls, it **is required** if camo is enabled. | ||||
| - `ALLWAYS`: **false**: Set to true to use camo for https too lese only non https urls are proxyed | ||||
| 
 | ||||
| ## OpenID (`openid`) | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										47
									
								
								modules/markup/camo.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								modules/markup/camo.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,47 @@ | ||||
| // Copyright 2022 The Gitea Authors. All rights reserved. | ||||
| // Use of this source code is governed by a MIT-style | ||||
| // license that can be found in the LICENSE file. | ||||
| 
 | ||||
| package markup | ||||
| 
 | ||||
| import ( | ||||
| 	"crypto/hmac" | ||||
| 	"crypto/sha1" | ||||
| 	"encoding/base64" | ||||
| 	"net/url" | ||||
| 	"strings" | ||||
| 
 | ||||
| 	"code.gitea.io/gitea/modules/setting" | ||||
| 	"code.gitea.io/gitea/modules/util" | ||||
| ) | ||||
| 
 | ||||
| // CamoEncode encodes a lnk to fit with the go-camo and camo proxy links. The purposes of camo-proxy are: | ||||
| // 1. Allow accessing "http://" images on a HTTPS site by using the "https://" URLs provided by camo-proxy. | ||||
| // 2. Hide the visitor's real IP (protect privacy) when accessing external images. | ||||
| func CamoEncode(link string) string { | ||||
| 	if strings.HasPrefix(link, setting.Camo.ServerURL) { | ||||
| 		return link | ||||
| 	} | ||||
| 
 | ||||
| 	mac := hmac.New(sha1.New, []byte(setting.Camo.HMACKey)) | ||||
| 	_, _ = mac.Write([]byte(link)) // hmac does not return errors | ||||
| 	macSum := b64encode(mac.Sum(nil)) | ||||
| 	encodedURL := b64encode([]byte(link)) | ||||
| 
 | ||||
| 	return util.URLJoin(setting.Camo.ServerURL, macSum, encodedURL) | ||||
| } | ||||
| 
 | ||||
| func b64encode(data []byte) string { | ||||
| 	return strings.TrimRight(base64.URLEncoding.EncodeToString(data), "=") | ||||
| } | ||||
| 
 | ||||
| func camoHandleLink(link string) string { | ||||
| 	if setting.Camo.Enabled { | ||||
| 		lnkURL, err := url.Parse(link) | ||||
| 		if err == nil && lnkURL.IsAbs() && !strings.HasPrefix(link, setting.AppURL) && | ||||
| 			(setting.Camo.Allways || lnkURL.Scheme != "https") { | ||||
| 			return CamoEncode(link) | ||||
| 		} | ||||
| 	} | ||||
| 	return link | ||||
| } | ||||
							
								
								
									
										45
									
								
								modules/markup/camo_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								modules/markup/camo_test.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,45 @@ | ||||
| // Copyright 2022 The Gitea Authors. All rights reserved. | ||||
| // Use of this source code is governed by a MIT-style | ||||
| // license that can be found in the LICENSE file. | ||||
| 
 | ||||
| package markup | ||||
| 
 | ||||
| import ( | ||||
| 	"testing" | ||||
| 
 | ||||
| 	"code.gitea.io/gitea/modules/setting" | ||||
| 
 | ||||
| 	"github.com/stretchr/testify/assert" | ||||
| ) | ||||
| 
 | ||||
| func TestCamoHandleLink(t *testing.T) { | ||||
| 	setting.AppURL = "https://gitea.com" | ||||
| 	// Test media proxy | ||||
| 	setting.Camo.Enabled = true | ||||
| 	setting.Camo.ServerURL = "https://image.proxy" | ||||
| 	setting.Camo.HMACKey = "geheim" | ||||
| 
 | ||||
| 	assert.Equal(t, | ||||
| 		"https://gitea.com/img.jpg", | ||||
| 		camoHandleLink("https://gitea.com/img.jpg")) | ||||
| 	assert.Equal(t, | ||||
| 		"https://testimages.org/img.jpg", | ||||
| 		camoHandleLink("https://testimages.org/img.jpg")) | ||||
| 	assert.Equal(t, | ||||
| 		"https://image.proxy/eivin43gJwGVIjR9MiYYtFIk0mw/aHR0cDovL3Rlc3RpbWFnZXMub3JnL2ltZy5qcGc", | ||||
| 		camoHandleLink("http://testimages.org/img.jpg")) | ||||
| 
 | ||||
| 	setting.Camo.Allways = true | ||||
| 	assert.Equal(t, | ||||
| 		"https://gitea.com/img.jpg", | ||||
| 		camoHandleLink("https://gitea.com/img.jpg")) | ||||
| 	assert.Equal(t, | ||||
| 		"https://image.proxy/tkdlvmqpbIr7SjONfHNgEU622y0/aHR0cHM6Ly90ZXN0aW1hZ2VzLm9yZy9pbWcuanBn", | ||||
| 		camoHandleLink("https://testimages.org/img.jpg")) | ||||
| 	assert.Equal(t, | ||||
| 		"https://image.proxy/eivin43gJwGVIjR9MiYYtFIk0mw/aHR0cDovL3Rlc3RpbWFnZXMub3JnL2ltZy5qcGc", | ||||
| 		camoHandleLink("http://testimages.org/img.jpg")) | ||||
| 
 | ||||
| 	// Restore previous settings | ||||
| 	setting.Camo.Enabled = false | ||||
| } | ||||
| @ -386,6 +386,7 @@ func visitNode(ctx *RenderContext, procs, textProcs []processor, node *html.Node | ||||
| 
 | ||||
| 					attr.Val = util.URLJoin(prefix, attr.Val) | ||||
| 				} | ||||
| 				attr.Val = camoHandleLink(attr.Val) | ||||
| 				node.Attr[i] = attr | ||||
| 			} | ||||
| 		} else if node.Data == "a" { | ||||
|  | ||||
| @ -197,6 +197,13 @@ var ( | ||||
| 	PasswordCheckPwn                   bool | ||||
| 	SuccessfulTokensCacheSize          int | ||||
| 
 | ||||
| 	Camo = struct { | ||||
| 		Enabled   bool | ||||
| 		ServerURL string `ini:"SERVER_URL"` | ||||
| 		HMACKey   string `ini:"HMAC_KEY"` | ||||
| 		Allways   bool | ||||
| 	}{} | ||||
| 
 | ||||
| 	// UI settings | ||||
| 	UI = struct { | ||||
| 		ExplorePagingNum      int | ||||
| @ -1019,6 +1026,14 @@ func loadFromConf(allowEmpty bool, extraConfig string) { | ||||
| 		log.Fatal("Failed to map API settings: %v", err) | ||||
| 	} else if err = Cfg.Section("metrics").MapTo(&Metrics); err != nil { | ||||
| 		log.Fatal("Failed to map Metrics settings: %v", err) | ||||
| 	} else if err = Cfg.Section("camo").MapTo(&Camo); err != nil { | ||||
| 		log.Fatal("Failed to map Camo settings: %v", err) | ||||
| 	} | ||||
| 
 | ||||
| 	if Camo.Enabled { | ||||
| 		if Camo.ServerURL == "" || Camo.HMACKey == "" { | ||||
| 			log.Fatal(`Camo settings require "SERVER_URL" and HMAC_KEY`) | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	u := *appURL | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 zeripath
						zeripath