Add support for custom CA in actions.Client (#2199)
This commit is contained in:
		
							parent
							
								
									6e69c75637
								
							
						
					
					
						commit
						d57d17f161
					
				|  | @ -29,6 +29,7 @@ bin | ||||||
| .env | .env | ||||||
| .test.env | .test.env | ||||||
| *.pem | *.pem | ||||||
|  | !github/actions/testdata/*.pem | ||||||
| 
 | 
 | ||||||
| # OS | # OS | ||||||
| .DS_STORE | .DS_STORE | ||||||
|  |  | ||||||
|  | @ -3,6 +3,8 @@ package actions | ||||||
| import ( | import ( | ||||||
| 	"bytes" | 	"bytes" | ||||||
| 	"context" | 	"context" | ||||||
|  | 	"crypto/tls" | ||||||
|  | 	"crypto/x509" | ||||||
| 	"encoding/base64" | 	"encoding/base64" | ||||||
| 	"encoding/json" | 	"encoding/json" | ||||||
| 	"fmt" | 	"fmt" | ||||||
|  | @ -70,6 +72,9 @@ type Client struct { | ||||||
| 	githubConfigURL string | 	githubConfigURL string | ||||||
| 	logger          logr.Logger | 	logger          logr.Logger | ||||||
| 	userAgent       string | 	userAgent       string | ||||||
|  | 
 | ||||||
|  | 	rootCAs               *x509.CertPool | ||||||
|  | 	tlsInsecureSkipVerify bool | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| type ClientOption func(*Client) | type ClientOption func(*Client) | ||||||
|  | @ -98,6 +103,18 @@ func WithRetryWaitMax(retryWaitMax time.Duration) ClientOption { | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | func WithRootCAs(rootCAs *x509.CertPool) ClientOption { | ||||||
|  | 	return func(c *Client) { | ||||||
|  | 		c.rootCAs = rootCAs | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func WithoutTLSVerify() ClientOption { | ||||||
|  | 	return func(c *Client) { | ||||||
|  | 		c.tlsInsecureSkipVerify = true | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
| func NewClient(ctx context.Context, githubConfigURL string, creds *ActionsAuth, options ...ClientOption) (ActionsService, error) { | func NewClient(ctx context.Context, githubConfigURL string, creds *ActionsAuth, options ...ClientOption) (ActionsService, error) { | ||||||
| 	ac := &Client{ | 	ac := &Client{ | ||||||
| 		creds:           creds, | 		creds:           creds, | ||||||
|  | @ -121,6 +138,26 @@ func NewClient(ctx context.Context, githubConfigURL string, creds *ActionsAuth, | ||||||
| 
 | 
 | ||||||
| 	retryClient.RetryMax = ac.retryMax | 	retryClient.RetryMax = ac.retryMax | ||||||
| 	retryClient.RetryWaitMax = ac.retryWaitMax | 	retryClient.RetryWaitMax = ac.retryWaitMax | ||||||
|  | 
 | ||||||
|  | 	transport, ok := retryClient.HTTPClient.Transport.(*http.Transport) | ||||||
|  | 	if !ok { | ||||||
|  | 		// this should always be true, because retryablehttp.NewClient() uses
 | ||||||
|  | 		// cleanhttp.DefaultPooledTransport()
 | ||||||
|  | 		return nil, fmt.Errorf("failed to get http transport from retryablehttp client") | ||||||
|  | 	} | ||||||
|  | 	if transport.TLSClientConfig == nil { | ||||||
|  | 		transport.TLSClientConfig = &tls.Config{} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if ac.rootCAs != nil { | ||||||
|  | 		transport.TLSClientConfig.RootCAs = ac.rootCAs | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if ac.tlsInsecureSkipVerify { | ||||||
|  | 		transport.TLSClientConfig.InsecureSkipVerify = true | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	retryClient.HTTPClient.Transport = transport | ||||||
| 	ac.Client = retryClient.StandardClient() | 	ac.Client = retryClient.StandardClient() | ||||||
| 
 | 
 | ||||||
| 	rt, err := ac.getRunnerRegistrationToken(ctx, githubConfigURL, *creds) | 	rt, err := ac.getRunnerRegistrationToken(ctx, githubConfigURL, *creds) | ||||||
|  | @ -776,7 +813,7 @@ func (c *Client) getRunnerRegistrationToken(ctx context.Context, githubConfigUrl | ||||||
| 
 | 
 | ||||||
| 	c.logger.Info("getting runner registration token", "registrationTokenURL", registrationTokenURL) | 	c.logger.Info("getting runner registration token", "registrationTokenURL", registrationTokenURL) | ||||||
| 
 | 
 | ||||||
| 	resp, err := http.DefaultClient.Do(req) | 	resp, err := c.Do(req) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return nil, err | 		return nil, err | ||||||
| 	} | 	} | ||||||
|  | @ -832,7 +869,7 @@ func (c *Client) fetchAccessToken(ctx context.Context, gitHubConfigURL string, c | ||||||
| 
 | 
 | ||||||
| 	c.logger.Info("getting access token for GitHub App auth", "accessTokenURL", accessTokenURL.String()) | 	c.logger.Info("getting access token for GitHub App auth", "accessTokenURL", accessTokenURL.String()) | ||||||
| 
 | 
 | ||||||
| 	resp, err := http.DefaultClient.Do(req) | 	resp, err := c.Do(req) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return nil, err | 		return nil, err | ||||||
| 	} | 	} | ||||||
|  | @ -892,7 +929,7 @@ func (c *Client) getActionsServiceAdminConnection(ctx context.Context, rt *regis | ||||||
| 
 | 
 | ||||||
| 	c.logger.Info("getting Actions tenant URL and JWT", "registrationURL", registrationURL.String()) | 	c.logger.Info("getting Actions tenant URL and JWT", "registrationURL", registrationURL.String()) | ||||||
| 
 | 
 | ||||||
| 	resp, err := http.DefaultClient.Do(req) | 	resp, err := c.Do(req) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return nil, err | 		return nil, err | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | @ -0,0 +1,149 @@ | ||||||
|  | package actions_test | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"context" | ||||||
|  | 	"crypto/tls" | ||||||
|  | 	"crypto/x509" | ||||||
|  | 	"errors" | ||||||
|  | 	"net/http" | ||||||
|  | 	"net/http/httptest" | ||||||
|  | 	"os" | ||||||
|  | 	"path/filepath" | ||||||
|  | 	"runtime" | ||||||
|  | 	"strings" | ||||||
|  | 	"testing" | ||||||
|  | 	"time" | ||||||
|  | 
 | ||||||
|  | 	"github.com/actions/actions-runner-controller/github/actions" | ||||||
|  | 	"github.com/golang-jwt/jwt/v4" | ||||||
|  | 	"github.com/stretchr/testify/assert" | ||||||
|  | 	"github.com/stretchr/testify/require" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | func TestServerWithSelfSignedCertificates(t *testing.T) { | ||||||
|  | 	ctx := context.Background() | ||||||
|  | 
 | ||||||
|  | 	// this handler is a very very barebones replica of actions api
 | ||||||
|  | 	// used during the creation of a a new client
 | ||||||
|  | 	h := func(w http.ResponseWriter, r *http.Request) { | ||||||
|  | 		// handle get registration token
 | ||||||
|  | 		if strings.HasSuffix(r.URL.Path, "/runners/registration-token") { | ||||||
|  | 			w.WriteHeader(http.StatusCreated) | ||||||
|  | 			w.Write([]byte(`{"token":"token"}`)) | ||||||
|  | 			return | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		// handle getActionsServiceAdminConnection
 | ||||||
|  | 		if strings.HasSuffix(r.URL.Path, "/actions/runner-registration") { | ||||||
|  | 			claims := &jwt.RegisteredClaims{ | ||||||
|  | 				IssuedAt:  jwt.NewNumericDate(time.Now().Add(-1 * time.Minute)), | ||||||
|  | 				ExpiresAt: jwt.NewNumericDate(time.Now().Add(1 * time.Minute)), | ||||||
|  | 				Issuer:    "123", | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			token := jwt.NewWithClaims(jwt.SigningMethodRS256, claims) | ||||||
|  | 			privateKey, err := jwt.ParseRSAPrivateKeyFromPEM([]byte(samplePrivateKey)) | ||||||
|  | 			require.NoError(t, err) | ||||||
|  | 			tokenString, err := token.SignedString(privateKey) | ||||||
|  | 			require.NoError(t, err) | ||||||
|  | 			w.Write([]byte(`{"url":"TODO","token":"` + tokenString + `"}`)) | ||||||
|  | 			return | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	certPath := filepath.Join("testdata", "server.crt") | ||||||
|  | 	keyPath := filepath.Join("testdata", "server.key") | ||||||
|  | 
 | ||||||
|  | 	t.Run("client without ca certs", func(t *testing.T) { | ||||||
|  | 		server := startNewTLSTestServer(t, certPath, keyPath, http.HandlerFunc(h)) | ||||||
|  | 		configURL := server.URL + "/my-org" | ||||||
|  | 
 | ||||||
|  | 		auth := &actions.ActionsAuth{ | ||||||
|  | 			Token: "token", | ||||||
|  | 		} | ||||||
|  | 		client, err := actions.NewClient(ctx, configURL, auth) | ||||||
|  | 		assert.Nil(t, client) | ||||||
|  | 		require.NotNil(t, err) | ||||||
|  | 
 | ||||||
|  | 		if runtime.GOOS == "linux" { | ||||||
|  | 			assert.True(t, errors.As(err, &x509.UnknownAuthorityError{})) | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		// on macOS we only get an untyped error from the system verifying the
 | ||||||
|  | 		// certificate
 | ||||||
|  | 		if runtime.GOOS == "darwin" { | ||||||
|  | 			assert.True(t, strings.HasSuffix(err.Error(), "certificate is not trusted")) | ||||||
|  | 		} | ||||||
|  | 	}) | ||||||
|  | 
 | ||||||
|  | 	t.Run("client with ca certs", func(t *testing.T) { | ||||||
|  | 		server := startNewTLSTestServer(t, certPath, keyPath, http.HandlerFunc(h)) | ||||||
|  | 		configURL := server.URL + "/my-org" | ||||||
|  | 
 | ||||||
|  | 		auth := &actions.ActionsAuth{ | ||||||
|  | 			Token: "token", | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		cert, err := os.ReadFile(filepath.Join("testdata", "rootCA.crt")) | ||||||
|  | 		require.NoError(t, err) | ||||||
|  | 
 | ||||||
|  | 		pool, err := actions.RootCAsFromConfigMap(map[string][]byte{"cert": cert}) | ||||||
|  | 		require.NoError(t, err) | ||||||
|  | 
 | ||||||
|  | 		client, err := actions.NewClient(ctx, configURL, auth, actions.WithRootCAs(pool)) | ||||||
|  | 		require.NoError(t, err) | ||||||
|  | 		assert.NotNil(t, client) | ||||||
|  | 	}) | ||||||
|  | 
 | ||||||
|  | 	t.Run("client with ca chain certs", func(t *testing.T) { | ||||||
|  | 		server := startNewTLSTestServer( | ||||||
|  | 			t, | ||||||
|  | 			filepath.Join("testdata", "leaf.pem"), | ||||||
|  | 			filepath.Join("testdata", "leaf.key"), | ||||||
|  | 			http.HandlerFunc(h), | ||||||
|  | 		) | ||||||
|  | 		configURL := server.URL + "/my-org" | ||||||
|  | 
 | ||||||
|  | 		auth := &actions.ActionsAuth{ | ||||||
|  | 			Token: "token", | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		cert, err := os.ReadFile(filepath.Join("testdata", "intermediate.pem")) | ||||||
|  | 		require.NoError(t, err) | ||||||
|  | 
 | ||||||
|  | 		pool, err := actions.RootCAsFromConfigMap(map[string][]byte{"cert": cert}) | ||||||
|  | 		require.NoError(t, err) | ||||||
|  | 
 | ||||||
|  | 		client, err := actions.NewClient(ctx, configURL, auth, actions.WithRootCAs(pool), actions.WithRetryMax(0)) | ||||||
|  | 		require.NoError(t, err) | ||||||
|  | 		assert.NotNil(t, client) | ||||||
|  | 	}) | ||||||
|  | 
 | ||||||
|  | 	t.Run("client skipping tls verification", func(t *testing.T) { | ||||||
|  | 		server := startNewTLSTestServer(t, certPath, keyPath, http.HandlerFunc(h)) | ||||||
|  | 		configURL := server.URL + "/my-org" | ||||||
|  | 
 | ||||||
|  | 		auth := &actions.ActionsAuth{ | ||||||
|  | 			Token: "token", | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		client, err := actions.NewClient(ctx, configURL, auth, actions.WithoutTLSVerify()) | ||||||
|  | 		require.NoError(t, err) | ||||||
|  | 		assert.NotNil(t, client) | ||||||
|  | 	}) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func startNewTLSTestServer(t *testing.T, certPath, keyPath string, handler http.Handler) *httptest.Server { | ||||||
|  | 	server := httptest.NewUnstartedServer(handler) | ||||||
|  | 	t.Cleanup(func() { | ||||||
|  | 		server.Close() | ||||||
|  | 	}) | ||||||
|  | 
 | ||||||
|  | 	cert, err := tls.LoadX509KeyPair(certPath, keyPath) | ||||||
|  | 	require.NoError(t, err) | ||||||
|  | 
 | ||||||
|  | 	server.TLS = &tls.Config{Certificates: []tls.Certificate{cert}} | ||||||
|  | 	server.StartTLS() | ||||||
|  | 
 | ||||||
|  | 	return server | ||||||
|  | } | ||||||
|  | @ -2,6 +2,7 @@ package actions | ||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
| 	"context" | 	"context" | ||||||
|  | 	"crypto/x509" | ||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"net/url" | 	"net/url" | ||||||
| 	"strconv" | 	"strconv" | ||||||
|  | @ -168,3 +169,19 @@ func (m *multiClient) GetClientFromSecret(ctx context.Context, githubConfigURL, | ||||||
| 	auth.AppCreds = &GitHubAppAuth{AppID: parsedAppID, AppInstallationID: parsedAppInstallationID, AppPrivateKey: appPrivateKey} | 	auth.AppCreds = &GitHubAppAuth{AppID: parsedAppID, AppInstallationID: parsedAppInstallationID, AppPrivateKey: appPrivateKey} | ||||||
| 	return m.GetClientFor(ctx, githubConfigURL, auth, namespace) | 	return m.GetClientFor(ctx, githubConfigURL, auth, namespace) | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | func RootCAsFromConfigMap(configMapData map[string][]byte) (*x509.CertPool, error) { | ||||||
|  | 	caCertPool, err := x509.SystemCertPool() | ||||||
|  | 	if err != nil { | ||||||
|  | 		caCertPool = x509.NewCertPool() | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	for key, certData := range configMapData { | ||||||
|  | 		ok := caCertPool.AppendCertsFromPEM(certData) | ||||||
|  | 		if !ok { | ||||||
|  | 			return nil, fmt.Errorf("no certificates successfully parsed from key %s", key) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return caCertPool, nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @ -0,0 +1,73 @@ | ||||||
|  | Certificate: | ||||||
|  |     Data: | ||||||
|  |         Version: 3 (0x2) | ||||||
|  |         Serial Number: 8 (0x8) | ||||||
|  |     Signature Algorithm: sha256WithRSAEncryption | ||||||
|  |         Issuer: C=US, O=arc-test, CN=localhost | ||||||
|  |         Validity | ||||||
|  |             Not Before: Jan 23 17:54:51 2023 GMT | ||||||
|  |             Not After : Jun  9 17:54:51 2050 GMT | ||||||
|  |         Subject: C=US, O=arc-test, CN=localhost | ||||||
|  |         Subject Public Key Info: | ||||||
|  |             Public Key Algorithm: rsaEncryption | ||||||
|  |                 RSA Public-Key: (2048 bit) | ||||||
|  |                 Modulus: | ||||||
|  |                     00:dd:61:59:0a:19:19:1a:d4:e1:f1:c0:8d:bb:c2: | ||||||
|  |                     f8:32:e5:04:55:c5:ea:f6:71:5c:d3:ad:d0:b1:c3: | ||||||
|  |                     86:73:ba:f1:01:7f:5d:45:6c:bf:0d:e6:27:c4:f0: | ||||||
|  |                     a0:f2:be:73:61:04:1f:f5:ca:3b:9d:11:c6:00:ae: | ||||||
|  |                     49:6f:7f:9c:f7:e1:21:e4:53:aa:29:71:58:fe:e8: | ||||||
|  |                     c8:6c:25:2f:0a:ef:8f:be:e8:1c:9d:76:05:4a:28: | ||||||
|  |                     e1:88:20:4b:4a:51:59:48:3c:84:05:ec:10:ae:be: | ||||||
|  |                     76:05:ee:ff:bf:54:67:02:e6:01:e8:02:b4:d0:07: | ||||||
|  |                     79:39:10:71:e6:b1:25:b5:6a:24:7c:22:ef:70:90: | ||||||
|  |                     5b:32:69:81:9d:34:82:a6:3b:fd:b5:8e:6b:8d:12: | ||||||
|  |                     e7:bd:0a:0d:61:1f:ed:16:82:30:f9:2c:93:8d:fe: | ||||||
|  |                     70:b5:4d:c4:53:0b:5e:f1:ba:4a:c5:08:ba:56:8f: | ||||||
|  |                     dd:b7:fc:13:cd:1b:d1:1c:31:00:d1:7d:49:fd:54: | ||||||
|  |                     4d:73:e8:73:1d:69:dd:98:53:fe:77:66:3f:05:a7: | ||||||
|  |                     61:1c:e4:c2:a6:b9:31:df:c5:0b:b5:78:fc:7f:42: | ||||||
|  |                     9f:0e:a6:1a:eb:59:46:be:ac:95:8a:85:ea:05:e4: | ||||||
|  |                     8a:33:00:2e:8e:d9:a4:20:4a:39:77:53:16:7c:8a: | ||||||
|  |                     9c:59 | ||||||
|  |                 Exponent: 65537 (0x10001) | ||||||
|  |         X509v3 extensions: | ||||||
|  |             X509v3 Basic Constraints: critical | ||||||
|  |                 CA:TRUE | ||||||
|  |             X509v3 Key Usage: critical | ||||||
|  |                 Certificate Sign | ||||||
|  |     Signature Algorithm: sha256WithRSAEncryption | ||||||
|  |          a5:5c:2f:be:b7:e4:a8:e7:95:7a:58:93:be:5e:3a:5a:f7:0b: | ||||||
|  |          70:ba:8e:b8:a8:dc:7c:5b:2c:c1:5b:80:f3:8f:8a:c4:2b:d2: | ||||||
|  |          ad:69:21:29:75:3a:5b:7d:bb:4f:2b:f9:27:4a:ab:d7:bd:05: | ||||||
|  |          0a:aa:50:e7:b0:2d:7f:05:2d:42:af:c1:de:aa:a1:69:b1:b4: | ||||||
|  |          78:ce:f2:78:98:97:49:c0:be:1b:5f:23:47:8d:c5:e8:c4:85: | ||||||
|  |          84:31:d0:5c:9b:12:96:43:08:ae:32:dc:9d:d4:ad:c6:6d:15: | ||||||
|  |          ad:0f:6c:ec:50:61:86:3c:b7:75:90:6b:44:d5:dd:56:c1:11: | ||||||
|  |          fe:6e:07:80:85:93:8a:34:da:e9:38:21:ac:ce:73:ce:c1:26: | ||||||
|  |          4e:94:2f:9b:82:b5:06:7a:ef:21:3a:80:79:89:c2:fd:e5:04: | ||||||
|  |          25:1c:a8:b2:28:91:1f:a1:91:b6:82:ea:ce:64:21:ef:da:0c: | ||||||
|  |          af:bf:09:5a:e2:9f:5b:f6:0f:bf:cf:91:d3:97:7f:f1:25:9b: | ||||||
|  |          8b:5f:10:16:fb:a8:92:11:13:38:cb:32:02:03:69:6f:9e:fe: | ||||||
|  |          2a:b0:56:c7:49:f3:2a:9b:c6:ee:a2:98:25:d2:a0:c0:f3:c4: | ||||||
|  |          03:99:e1:94:e3:f5:95:28:07:ec:db:31:3a:25:79:c1:45:c8: | ||||||
|  |          8a:1e:75:39 | ||||||
|  | -----BEGIN CERTIFICATE----- | ||||||
|  | MIIDCDCCAfCgAwIBAgIBCDANBgkqhkiG9w0BAQsFADA0MQswCQYDVQQGEwJVUzER | ||||||
|  | MA8GA1UECgwIYXJjLXRlc3QxEjAQBgNVBAMMCWxvY2FsaG9zdDAgFw0yMzAxMjMx | ||||||
|  | NzU0NTFaGA8yMDUwMDYwOTE3NTQ1MVowNDELMAkGA1UEBhMCVVMxETAPBgNVBAoM | ||||||
|  | CGFyYy10ZXN0MRIwEAYDVQQDDAlsb2NhbGhvc3QwggEiMA0GCSqGSIb3DQEBAQUA | ||||||
|  | A4IBDwAwggEKAoIBAQDdYVkKGRka1OHxwI27wvgy5QRVxer2cVzTrdCxw4ZzuvEB | ||||||
|  | f11FbL8N5ifE8KDyvnNhBB/1yjudEcYArklvf5z34SHkU6opcVj+6MhsJS8K74++ | ||||||
|  | 6ByddgVKKOGIIEtKUVlIPIQF7BCuvnYF7v+/VGcC5gHoArTQB3k5EHHmsSW1aiR8 | ||||||
|  | Iu9wkFsyaYGdNIKmO/21jmuNEue9Cg1hH+0WgjD5LJON/nC1TcRTC17xukrFCLpW | ||||||
|  | j923/BPNG9EcMQDRfUn9VE1z6HMdad2YU/53Zj8Fp2Ec5MKmuTHfxQu1ePx/Qp8O | ||||||
|  | phrrWUa+rJWKheoF5IozAC6O2aQgSjl3UxZ8ipxZAgMBAAGjIzAhMA8GA1UdEwEB | ||||||
|  | /wQFMAMBAf8wDgYDVR0PAQH/BAQDAgIEMA0GCSqGSIb3DQEBCwUAA4IBAQClXC++ | ||||||
|  | t+So55V6WJO+Xjpa9wtwuo64qNx8WyzBW4Dzj4rEK9KtaSEpdTpbfbtPK/knSqvX | ||||||
|  | vQUKqlDnsC1/BS1Cr8HeqqFpsbR4zvJ4mJdJwL4bXyNHjcXoxIWEMdBcmxKWQwiu | ||||||
|  | Mtyd1K3GbRWtD2zsUGGGPLd1kGtE1d1WwRH+bgeAhZOKNNrpOCGsznPOwSZOlC+b | ||||||
|  | grUGeu8hOoB5icL95QQlHKiyKJEfoZG2gurOZCHv2gyvvwla4p9b9g+/z5HTl3/x | ||||||
|  | JZuLXxAW+6iSERM4yzICA2lvnv4qsFbHSfMqm8buopgl0qDA88QDmeGU4/WVKAfs | ||||||
|  | 2zE6JXnBRciKHnU5 | ||||||
|  | -----END CERTIFICATE----- | ||||||
|  | @ -0,0 +1,27 @@ | ||||||
|  | -----BEGIN RSA PRIVATE KEY----- | ||||||
|  | MIIEowIBAAKCAQEApgzbb+dY2DKM+Ysrk+l7guhvtgY9q5ws7pqF0duYkI2zmyMW | ||||||
|  | EDSkXKPoODiimYhol4Cr7c6hgtOzZS0+W4kVdhDLpk/mg9a4ZTLJqn2DIHj9Q0G+ | ||||||
|  | ENJrENjxPHfykXcXs2LAgRLffle4g4bfnJVQCyzZNiCblpqTnSSyEFa1AEtrxq6r | ||||||
|  | 2E/bYjBm18G4WxBOWHukuYsZ5FKlgzT/ZNeLoME9WDp4+wxKAEGSnEhlPv/Sr6ns | ||||||
|  | GxPz5i9NPBFqg373oDW17Nxere7M6l6oMqNtFbsQafI7Jmy4rrgHBrDf0s1SlaY3 | ||||||
|  | ceDPwXpT9ttHXZe9Dqb6MSEEQvL4IWG0TEGMJwIDAQABAoIBADfl8CEVslTlf4uq | ||||||
|  | C/t5B/kjoieWpkAVDRMttYrV7+AJs8Kv5weBkSsWimASwLoKr5sA19/wRXKzLZsL | ||||||
|  | xggud6kNMmFEWIddSynWFQltwyy1ThzMDt2+2AgN3/fJMUFC5BmhTsikv9PaV+T/ | ||||||
|  | DFu77/wzFtQf2gCy/KpT5hWV+sykDBriswFoVycUbC2kAcxcaTJioB5TKmNQoxxe | ||||||
|  | pUxiQSaEgVYTAuKt5da1UqBmiqoqNUQNIC+Q7T6cGw6F6WPd6sF13VXHF3EU/Q+6 | ||||||
|  | 6bW1p+9iuDxAa6sWI5gLCYFq4vcgTvqa5tGSsrxw7CNmuZFc/HtjMqAcBGDAKwFI | ||||||
|  | zrTW8sECgYEA2XxoucFX81P+AW6C2ymHCH+4BUdLYANkAE5VLkiTvGN9NCqYmdQD | ||||||
|  | 5jb1yE3dp0YmDvZ/ZGJpwrJHwU7r1FNt1psRpPhIyErzk7MxgF0Efa4dRl3c2rno | ||||||
|  | aTWgWSTXB1UU3+ev157P3vGNJEewCCgMwdp4qv9dVu+mGaJTZWAKNnECgYEAw3Sj | ||||||
|  | 9bV1c5uaoPvMNAIBVFeSL3W9A6A90uPcPyu55NAsEHtZgAd8JFSYnT2rwbND1CC8 | ||||||
|  | YqynWfvAEyXshVeBEurRC13XCXhB6U3rfEFnLA5+HZsCgpFNfKHiNvxfVGsGGTRn | ||||||
|  | YKGYAPOHz1jN8TVT3ZwzKNc5olzVB4KP97ylKBcCgYEApqqHWurG6qsQOaqlzyw4 | ||||||
|  | 1hOCQ1FKew6+INnmvyxRQwp/FW4bOa9XOaIeolzBowHIAql2IMimQdT71jET2sgA | ||||||
|  | oXh+ggzfQdbmaObm5XbjDSlUN+uQZ3IWoCG/evEXdAAImjnj8Ho81J4JyqbBSM7g | ||||||
|  | T+KLnIdL0WafxH84J7T8vpECgYBYJZ5cDX3uqVpPB7/MJKtc0jGHXd3kaLv5A/Is | ||||||
|  | OxgW7RsyQ67VYorGB7DcGRgAv0vzut+60IqYtkSlXhERAamgUm38ZlG4X5e6E/4D | ||||||
|  | h6tz3wVZbLLxF36OmqNekOqdM7cIXu3QUpAuvaWeCTq3cYllBDC+VnITmzIntOYg | ||||||
|  | n98L+QKBgF4AQDN4Mcet9RSFVdgK2Ue11ngr39SUUQapsK7uFvRZhv86voeDR3zv | ||||||
|  | 4zaj5JIemaRAOMnJS0pdHBHoz4tcqeDcqqHAdliZ/DYmiFhm8Q6Jufzc0KBkus6p | ||||||
|  | w8/pSBRpjZQZrgQZxYoU1g9Smy94ysY4DHt5BZIWGbBiwaREARYO | ||||||
|  | -----END RSA PRIVATE KEY----- | ||||||
|  | @ -0,0 +1,81 @@ | ||||||
|  | Certificate: | ||||||
|  |     Data: | ||||||
|  |         Version: 3 (0x2) | ||||||
|  |         Serial Number: 11 (0xb) | ||||||
|  |     Signature Algorithm: sha256WithRSAEncryption | ||||||
|  |         Issuer: C=US, O=arc-test, CN=localhost | ||||||
|  |         Validity | ||||||
|  |             Not Before: Jan 23 17:54:52 2023 GMT | ||||||
|  |             Not After : Jun  9 17:54:52 2050 GMT | ||||||
|  |         Subject: C=US, O=actions-runner-controller, OU=actions-runner-controller test | ||||||
|  |         Subject Public Key Info: | ||||||
|  |             Public Key Algorithm: rsaEncryption | ||||||
|  |                 RSA Public-Key: (2048 bit) | ||||||
|  |                 Modulus: | ||||||
|  |                     00:a6:0c:db:6f:e7:58:d8:32:8c:f9:8b:2b:93:e9: | ||||||
|  |                     7b:82:e8:6f:b6:06:3d:ab:9c:2c:ee:9a:85:d1:db: | ||||||
|  |                     98:90:8d:b3:9b:23:16:10:34:a4:5c:a3:e8:38:38: | ||||||
|  |                     a2:99:88:68:97:80:ab:ed:ce:a1:82:d3:b3:65:2d: | ||||||
|  |                     3e:5b:89:15:76:10:cb:a6:4f:e6:83:d6:b8:65:32: | ||||||
|  |                     c9:aa:7d:83:20:78:fd:43:41:be:10:d2:6b:10:d8: | ||||||
|  |                     f1:3c:77:f2:91:77:17:b3:62:c0:81:12:df:7e:57: | ||||||
|  |                     b8:83:86:df:9c:95:50:0b:2c:d9:36:20:9b:96:9a: | ||||||
|  |                     93:9d:24:b2:10:56:b5:00:4b:6b:c6:ae:ab:d8:4f: | ||||||
|  |                     db:62:30:66:d7:c1:b8:5b:10:4e:58:7b:a4:b9:8b: | ||||||
|  |                     19:e4:52:a5:83:34:ff:64:d7:8b:a0:c1:3d:58:3a: | ||||||
|  |                     78:fb:0c:4a:00:41:92:9c:48:65:3e:ff:d2:af:a9: | ||||||
|  |                     ec:1b:13:f3:e6:2f:4d:3c:11:6a:83:7e:f7:a0:35: | ||||||
|  |                     b5:ec:dc:5e:ad:ee:cc:ea:5e:a8:32:a3:6d:15:bb: | ||||||
|  |                     10:69:f2:3b:26:6c:b8:ae:b8:07:06:b0:df:d2:cd: | ||||||
|  |                     52:95:a6:37:71:e0:cf:c1:7a:53:f6:db:47:5d:97: | ||||||
|  |                     bd:0e:a6:fa:31:21:04:42:f2:f8:21:61:b4:4c:41: | ||||||
|  |                     8c:27 | ||||||
|  |                 Exponent: 65537 (0x10001) | ||||||
|  |         X509v3 extensions: | ||||||
|  |             X509v3 Authority Key Identifier:  | ||||||
|  |                 DirName:/C=US/O=arc-test/CN=localhost | ||||||
|  |                 serial:08 | ||||||
|  | 
 | ||||||
|  |             X509v3 Basic Constraints:  | ||||||
|  |                 CA:FALSE | ||||||
|  |             X509v3 Key Usage:  | ||||||
|  |                 Digital Signature, Non Repudiation, Key Encipherment, Data Encipherment | ||||||
|  |             X509v3 Subject Alternative Name:  | ||||||
|  |                 IP Address:127.0.0.1, DNS:localhost | ||||||
|  |     Signature Algorithm: sha256WithRSAEncryption | ||||||
|  |          73:70:5c:40:cf:48:a9:c0:8b:50:c8:10:b5:3c:57:18:fd:ac: | ||||||
|  |          05:6b:7c:8f:ad:b2:cc:2a:92:b8:70:57:19:88:40:b6:b1:d9: | ||||||
|  |          e7:44:7b:44:69:4b:dc:10:20:08:a8:5a:b3:29:3c:ce:42:f8: | ||||||
|  |          57:04:e4:9b:b6:d8:22:0f:d4:4a:51:76:b8:32:4b:b6:bd:b9: | ||||||
|  |          10:4a:69:b6:20:f3:77:2b:eb:7b:11:b3:c9:1d:96:a6:0d:9a: | ||||||
|  |          29:ae:e6:89:91:95:26:29:7a:a9:e9:8f:6e:9c:aa:17:96:e7: | ||||||
|  |          87:04:84:bb:61:38:a8:d3:f7:2e:ef:ce:49:38:e7:d9:2c:86: | ||||||
|  |          be:a8:63:98:6a:f2:62:4f:48:1a:ee:d0:3f:9c:33:1e:d2:b3: | ||||||
|  |          3d:3c:bd:ab:4d:a9:c0:02:d2:ae:01:f4:fb:dd:1d:10:82:08: | ||||||
|  |          26:d2:06:2c:c1:5a:3c:76:c6:85:b8:c4:22:63:7d:c1:40:c5: | ||||||
|  |          44:bf:ac:b9:6e:58:ac:5b:5e:5f:34:08:a7:08:88:14:10:3f: | ||||||
|  |          3d:5d:6e:9c:38:d6:9c:2d:45:88:3f:46:10:15:bd:2f:d5:75: | ||||||
|  |          5f:cc:cb:f3:e7:56:c2:d9:99:7b:a9:ea:a8:b5:ff:60:35:28: | ||||||
|  |          b9:0c:6b:13:0b:d9:e0:d1:89:11:9b:4b:26:ad:2e:5a:93:ea: | ||||||
|  |          56:00:da:a0 | ||||||
|  | -----BEGIN CERTIFICATE----- | ||||||
|  | MIIDiTCCAnGgAwIBAgIBCzANBgkqhkiG9w0BAQsFADA0MQswCQYDVQQGEwJVUzER | ||||||
|  | MA8GA1UECgwIYXJjLXRlc3QxEjAQBgNVBAMMCWxvY2FsaG9zdDAgFw0yMzAxMjMx | ||||||
|  | NzU0NTJaGA8yMDUwMDYwOTE3NTQ1MlowWjELMAkGA1UEBhMCVVMxIjAgBgNVBAoM | ||||||
|  | GWFjdGlvbnMtcnVubmVyLWNvbnRyb2xsZXIxJzAlBgNVBAsMHmFjdGlvbnMtcnVu | ||||||
|  | bmVyLWNvbnRyb2xsZXIgdGVzdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC | ||||||
|  | ggEBAKYM22/nWNgyjPmLK5Ppe4Lob7YGPaucLO6ahdHbmJCNs5sjFhA0pFyj6Dg4 | ||||||
|  | opmIaJeAq+3OoYLTs2UtPluJFXYQy6ZP5oPWuGUyyap9gyB4/UNBvhDSaxDY8Tx3 | ||||||
|  | 8pF3F7NiwIES335XuIOG35yVUAss2TYgm5aak50kshBWtQBLa8auq9hP22IwZtfB | ||||||
|  | uFsQTlh7pLmLGeRSpYM0/2TXi6DBPVg6ePsMSgBBkpxIZT7/0q+p7BsT8+YvTTwR | ||||||
|  | aoN+96A1tezcXq3uzOpeqDKjbRW7EGnyOyZsuK64Bwaw39LNUpWmN3Hgz8F6U/bb | ||||||
|  | R12XvQ6m+jEhBELy+CFhtExBjCcCAwEAAaN+MHwwRgYDVR0jBD8wPaE4pDYwNDEL | ||||||
|  | MAkGA1UEBhMCVVMxETAPBgNVBAoMCGFyYy10ZXN0MRIwEAYDVQQDDAlsb2NhbGhv | ||||||
|  | c3SCAQgwCQYDVR0TBAIwADALBgNVHQ8EBAMCBPAwGgYDVR0RBBMwEYcEfwAAAYIJ | ||||||
|  | bG9jYWxob3N0MA0GCSqGSIb3DQEBCwUAA4IBAQBzcFxAz0ipwItQyBC1PFcY/awF | ||||||
|  | a3yPrbLMKpK4cFcZiEC2sdnnRHtEaUvcECAIqFqzKTzOQvhXBOSbttgiD9RKUXa4 | ||||||
|  | Mku2vbkQSmm2IPN3K+t7EbPJHZamDZopruaJkZUmKXqp6Y9unKoXlueHBIS7YTio | ||||||
|  | 0/cu785JOOfZLIa+qGOYavJiT0ga7tA/nDMe0rM9PL2rTanAAtKuAfT73R0Qgggm | ||||||
|  | 0gYswVo8dsaFuMQiY33BQMVEv6y5blisW15fNAinCIgUED89XW6cONacLUWIP0YQ | ||||||
|  | Fb0v1XVfzMvz51bC2Zl7qeqotf9gNSi5DGsTC9ng0YkRm0smrS5ak+pWANqg | ||||||
|  | -----END CERTIFICATE----- | ||||||
|  | @ -0,0 +1,18 @@ | ||||||
|  | -----BEGIN CERTIFICATE----- | ||||||
|  | MIIC6jCCAdICCQCoZFduxPa/eDANBgkqhkiG9w0BAQsFADA2MQswCQYDVQQGEwJV | ||||||
|  | UzEnMCUGA1UEAwweYWN0aW9ucy1ydW5uZXItY29udHJvbGxlci10ZXN0MCAXDTIz | ||||||
|  | MDExOTE2NTAwMVoYDzIwNTAwNjA1MTY1MDAxWjA2MQswCQYDVQQGEwJVUzEnMCUG | ||||||
|  | A1UEAwweYWN0aW9ucy1ydW5uZXItY29udHJvbGxlci10ZXN0MIIBIjANBgkqhkiG | ||||||
|  | 9w0BAQEFAAOCAQ8AMIIBCgKCAQEAykHCU0I/pdzhnQBwr2N+7so66LPq0cxc8JJL | ||||||
|  | S2mmk7gg+NWhTZzoci6aYXNRKCyH6B2Wmy7Qveku2wqT2+/4JBMYgTWH5bF7yt76 | ||||||
|  | LB+x9YruSgH/pBN2WI4vRU87NOAU8F0o0U/Lp5vAJoRo+ePPvcHu0OY1WF+QnEX+ | ||||||
|  | xtp6gJFGf5DT4U9upwEgQjKgvKFEoB5KNeH1qr2fS2yA2vhm6Uhm+1i/KUQUZ49K | ||||||
|  | GvFK8TQQT4HXft8rPLP5M9OitdqVU8SX0dQoXZ4M41/qydycHOvApj0LlH/XsicZ | ||||||
|  | x0mkF90hD+9VRqeYFe562NI4NHR7FGP7HKPWibNjXKC2w+z+aQIDAQABMA0GCSqG | ||||||
|  | SIb3DQEBCwUAA4IBAQBxaOCnmakd1PPp+pH40OjUktKG1nqM2tGqP0o3Bk7huB2y | ||||||
|  | jXIDi9ETuTeqqHONwwgsKOVY3J+Zt5R+teBSC0qUnypODzu+9v8Xa4Is9G9GyT5S | ||||||
|  | erjpPcJjQnvZyMHLH9DGGWE9UCyqKIqmaEc9bwr2oz1+a0rsaS3ZdIFlQibBHij5 | ||||||
|  | tdJcnzXfN4T4GIbYXKMCOYDy/5CiNJ26l/pQNpO9JCzsEmngw0ooS0Bi8EcTCgB6 | ||||||
|  | dsHl0w8va3l1kvxWWIlNTGwrAEpRbXmL01hAqx2yCiaFPVZ/eRNWmBWO4LpW4ouK | ||||||
|  | YOaA+X7geM6XVFlZE3cP58AxYKWHGAThxkZbD5cu | ||||||
|  | -----END CERTIFICATE----- | ||||||
|  | @ -0,0 +1,22 @@ | ||||||
|  | -----BEGIN CERTIFICATE----- | ||||||
|  | MIIDnTCCAoWgAwIBAgIJAJskDVhiEY6fMA0GCSqGSIb3DQEBCwUAMDYxCzAJBgNV | ||||||
|  | BAYTAlVTMScwJQYDVQQDDB5hY3Rpb25zLXJ1bm5lci1jb250cm9sbGVyLXRlc3Qw | ||||||
|  | HhcNMjMwMTE5MTY1MTE0WhcNMjQwMTE5MTY1MTE0WjBaMQswCQYDVQQGEwJVUzEi | ||||||
|  | MCAGA1UECgwZYWN0aW9ucy1ydW5uZXItY29udHJvbGxlcjEnMCUGA1UECwweYWN0 | ||||||
|  | aW9ucy1ydW5uZXItY29udHJvbGxlciB0ZXN0MIIBIjANBgkqhkiG9w0BAQEFAAOC | ||||||
|  | AQ8AMIIBCgKCAQEAzOTt1/VjuaHzn+b7jLeufW3rxLHFKQV+LiUiT389rbFGY+DN | ||||||
|  | CC+Nzx+DbFBpKcX/scseVhFzlXlrESWWZ4h7LGMXRsTDKs91F1RMuFCd8eIEwbuV | ||||||
|  | civR44IqT5r/0hlMOWemd3Fh/c8KF+9dWQ0q0T3tvlVzEbWNRTVAXTT4JzizqNd1 | ||||||
|  | 1hhnuV/KjhiptPC/8jQ4D9ocZKM8a1pM9O2z3bnmH7VTQJkhjxE7gefQTPQRmvKk | ||||||
|  | C7uqvfk2NHTTnKiLfkE10JhLTa0VND2aofNWCybGTyHNNCNlepakoP3KyFC2LjPR | ||||||
|  | oR5iwSnCRDu1z8tDWW+rIa3pfxdQ8LnH4J4CDwIDAQABo4GJMIGGMFAGA1UdIwRJ | ||||||
|  | MEehOqQ4MDYxCzAJBgNVBAYTAlVTMScwJQYDVQQDDB5hY3Rpb25zLXJ1bm5lci1j | ||||||
|  | b250cm9sbGVyLXRlc3SCCQCoZFduxPa/eDAJBgNVHRMEAjAAMAsGA1UdDwQEAwIE | ||||||
|  | 8DAaBgNVHREEEzARhwR/AAABgglsb2NhbGhvc3QwDQYJKoZIhvcNAQELBQADggEB | ||||||
|  | ALdl0ytjellmhtjbXkUZKAl/R2ZXMAVxIOtb4qiN6OOwOMK4p2Wt26p34bQa2JD0 | ||||||
|  | t0qvesI7spQzQObNMdT6NZJl8Ul0ABuzti/Esvmby+VfsFPasCQVXx+jqGhERqXc | ||||||
|  | SeZFIVWVACyfAc1dkqfGwehSrY62eBlY2PJ1JezagW6aLAnV6Si+96++mkALJDdX | ||||||
|  | MZhhSqjxM+Nnmhpy4My6oHVrdYWHcuVhzlEmNaMtmJCYuihIyD2Usn32xJK1k89d | ||||||
|  | WgEOPCk+ZDAligPlGZS201fsznJk5uIjmxPjjFlJLXotBs8H7j0cQ2JkV5YHsHCk | ||||||
|  | EYf5EJ0ZKtZbwRFeRC1Ajxg= | ||||||
|  | -----END CERTIFICATE----- | ||||||
|  | @ -0,0 +1,27 @@ | ||||||
|  | -----BEGIN RSA PRIVATE KEY----- | ||||||
|  | MIIEowIBAAKCAQEAzOTt1/VjuaHzn+b7jLeufW3rxLHFKQV+LiUiT389rbFGY+DN | ||||||
|  | CC+Nzx+DbFBpKcX/scseVhFzlXlrESWWZ4h7LGMXRsTDKs91F1RMuFCd8eIEwbuV | ||||||
|  | civR44IqT5r/0hlMOWemd3Fh/c8KF+9dWQ0q0T3tvlVzEbWNRTVAXTT4JzizqNd1 | ||||||
|  | 1hhnuV/KjhiptPC/8jQ4D9ocZKM8a1pM9O2z3bnmH7VTQJkhjxE7gefQTPQRmvKk | ||||||
|  | C7uqvfk2NHTTnKiLfkE10JhLTa0VND2aofNWCybGTyHNNCNlepakoP3KyFC2LjPR | ||||||
|  | oR5iwSnCRDu1z8tDWW+rIa3pfxdQ8LnH4J4CDwIDAQABAoIBAC5rr3c+IVntV0Tj | ||||||
|  | EBrRgrboMIJfxEuG8w+BWkSoj1DK2SfHxqwUGgzTFvNzRGAye7vMSRM24Pj8iUVZ | ||||||
|  | Pro2MbHcwWlHKvCID/85GiioGyCyFGHQHgu/4c2pr+xZMZxoHtzintRw28KlJaRG | ||||||
|  | lt+WHB1L6pE0yt04RMlpRyvW1GIODtEh1wya61Aa2xZMJxgbNWv89znLI2f3ForY | ||||||
|  | QR/he8hQtfJQeH+mv2SvJ1bopkJ58ZObKapuJAWCSxzVRj/yol1MqfUDBy4NrJfY | ||||||
|  | F5UP0BSmnED1EdIXeC0duo5RyiSfHqqJlcKR+zlepOb4pr4I1H8P6AIJ9iiunxUJ | ||||||
|  | h9i+YAECgYEA7JgrH5sjStcHdwUgEPN4E1MI3WRwDnnuVpzeSUH7tRqK4lsdIKmF | ||||||
|  | u/ss3TMwTgC8XR4JJbVp+6ea54zpVjtBGwShMSvn2+e7OHHg1YoVqBIgRpL+/C4m | ||||||
|  | wfon2EglQ0IjscUtKuAR/UyhU6vZtkYRUKeXRKisW4yoobdob0Y4lakCgYEA3bMl | ||||||
|  | BfszC5c0RXI5vsBUBvr9gXMY/8tacM7H8i3vT7JqoYJG6GGST0/HeK+La3w2zryx | ||||||
|  | Q8IL6uLy/HZvTHZ+BSp4KzwwgDUIk0jm/JcvzD2ZhJHoAo4aQTc6QI2ZNgjGVwCb | ||||||
|  | nJ0Niaxc4CdSUEAUHH1bCXk/e2stcnieFuiiPPcCgYAIxrA60OdjPEyzloYU+uMG | ||||||
|  | XHskszgQ4Wb84X7BWug6VIy4Tsbq0j76tRt57Q8qpY5XKekO9AbFZfcyBaEWKMaG | ||||||
|  | eQp9p3JHTvY75sV/Rkr9XAbEd2lr805OvbfCpxJyxz5JttWxFHS2X6RQVTyTLVAx | ||||||
|  | HLZYvqT+FF6g+QuvrPwmWQKBgAQspVvReQqU1EUie3feAzcGbtOLKUNXvuI04orq | ||||||
|  | 1oC3qU5VN6SUgb7Aj87z7zoc4qNN5kCSXMsVbuHWEQ5thL3wKMcXoQoo9Xpgewjy | ||||||
|  | h9Herw9R9/5kUpY7xfsFL4dW7vUga82tH14iQrVtyBz+t+I5cgdhoxJd2EM5hjCE | ||||||
|  | PNnNAoGBALPjmvEZ1HJdCOxY/AisziVtOFc6Glk/KhpSIT7WE1me4qLQFmrsHIDQ | ||||||
|  | kZ8Sb1f3PQ4T4vHGrtl8qh144MJPI1Nb8klzdlD1xeypGpgXoQb5fsC17g1fgczp | ||||||
|  | TGzq3pvnlGnrgVmnfrWQCHXDLzXtLqM/Pu84guPFftJQ+++yy0np | ||||||
|  | -----END RSA PRIVATE KEY----- | ||||||
		Loading…
	
		Reference in New Issue