github.com/kyma-incubator/compass/components/director@v0.0.0-20230623144113-d764f56ff805/internal/tenantfetchersvc/resync/client_test.go (about)

     1  package resync_test
     2  
     3  import (
     4  	"context"
     5  	"crypto/tls"
     6  	"fmt"
     7  	"io"
     8  	"net/http"
     9  	"net/http/httptest"
    10  	"testing"
    11  	"time"
    12  
    13  	"github.com/kyma-incubator/compass/components/director/internal/tenantfetchersvc/resync"
    14  	"golang.org/x/oauth2"
    15  	"golang.org/x/oauth2/clientcredentials"
    16  
    17  	"github.com/kyma-incubator/compass/components/director/pkg/oauth"
    18  
    19  	"github.com/kyma-incubator/compass/components/director/pkg/apperrors"
    20  
    21  	"github.com/stretchr/testify/assert"
    22  	"github.com/stretchr/testify/require"
    23  )
    24  
    25  func TestClient_FetchTenantEventsPage(t *testing.T) {
    26  	// GIVEN
    27  	ctx := context.TODO()
    28  	mockClient, mockServerCloseFn, endpoint := fixHTTPClient(t)
    29  	defer mockServerCloseFn()
    30  
    31  	queryParams := resync.QueryParams{
    32  		"pageSize":  "1",
    33  		"pageNum":   "1",
    34  		"timestamp": "1",
    35  	}
    36  
    37  	subaccountQueryParams := resync.QueryParams{
    38  		"pageSize":  "1",
    39  		"pageNum":   "1",
    40  		"timestamp": "1",
    41  		"region":    "test-region",
    42  	}
    43  
    44  	clientCfg := resync.ClientConfig{
    45  		TenantProvider: "",
    46  		APIConfig: resync.APIEndpointsConfig{
    47  			EndpointTenantCreated:     endpoint + "/ga-created",
    48  			EndpointTenantDeleted:     endpoint + "/ga-deleted",
    49  			EndpointTenantUpdated:     endpoint + "/ga-updated",
    50  			EndpointSubaccountCreated: endpoint + "/sub-created",
    51  			EndpointSubaccountDeleted: endpoint + "/sub-deleted",
    52  			EndpointSubaccountUpdated: endpoint + "/sub-updated",
    53  			EndpointSubaccountMoved:   endpoint + "/sub-moved",
    54  		},
    55  		FieldMapping:        resync.TenantFieldMapping{},
    56  		MovedSAFieldMapping: resync.MovedSubaccountsFieldMapping{},
    57  	}
    58  
    59  	client, err := resync.NewClient(resync.OAuth2Config{}, oauth.Standard, clientCfg, time.Second)
    60  	require.NoError(t, err)
    61  
    62  	client.SetHTTPClient(mockClient)
    63  
    64  	t.Run("Success fetching account creation events", func(t *testing.T) {
    65  		// WHEN
    66  		res, err := client.FetchTenantEventsPage(ctx, resync.CreatedAccountType, queryParams)
    67  		// THEN
    68  		require.NoError(t, err)
    69  		assert.NotEmpty(t, res)
    70  	})
    71  
    72  	t.Run("Success fetching account update events", func(t *testing.T) {
    73  		// WHEN
    74  		res, err := client.FetchTenantEventsPage(ctx, resync.UpdatedAccountType, queryParams)
    75  		// THEN
    76  		require.NoError(t, err)
    77  		assert.NotEmpty(t, res)
    78  	})
    79  
    80  	t.Run("Success fetching account deletion events", func(t *testing.T) {
    81  		// WHEN
    82  		res, err := client.FetchTenantEventsPage(ctx, resync.DeletedAccountType, queryParams)
    83  		// THEN
    84  		require.NoError(t, err)
    85  		assert.NotEmpty(t, res)
    86  	})
    87  
    88  	t.Run("Success fetching subaccount creation events", func(t *testing.T) {
    89  		// WHEN
    90  		res, err := client.FetchTenantEventsPage(ctx, resync.CreatedSubaccountType, subaccountQueryParams)
    91  		// THEN
    92  		require.NoError(t, err)
    93  		assert.NotEmpty(t, res)
    94  	})
    95  
    96  	t.Run("Success fetching subaccount update events", func(t *testing.T) {
    97  		// WHEN
    98  		res, err := client.FetchTenantEventsPage(ctx, resync.UpdatedSubaccountType, subaccountQueryParams)
    99  		// THEN
   100  		require.NoError(t, err)
   101  		assert.NotEmpty(t, res)
   102  	})
   103  
   104  	t.Run("Success fetching subaccount deletion events", func(t *testing.T) {
   105  		// WHEN
   106  		res, err := client.FetchTenantEventsPage(ctx, resync.DeletedSubaccountType, subaccountQueryParams)
   107  		// THEN
   108  		require.NoError(t, err)
   109  		assert.NotEmpty(t, res)
   110  	})
   111  
   112  	t.Run("Success fetching moved subaccount events", func(t *testing.T) {
   113  		// WHEN
   114  		res, err := client.FetchTenantEventsPage(ctx, resync.MovedSubaccountType, subaccountQueryParams)
   115  		// THEN
   116  		require.NoError(t, err)
   117  		assert.NotEmpty(t, res)
   118  	})
   119  
   120  	t.Run("Error when unknown events type", func(t *testing.T) {
   121  		// WHEN
   122  		res, err := client.FetchTenantEventsPage(ctx, -1, queryParams)
   123  		// THEN
   124  		require.EqualError(t, err, apperrors.NewInternalError("unknown events type").Error())
   125  		assert.Empty(t, res)
   126  	})
   127  
   128  	// GIVEN
   129  	clientCfg = resync.ClientConfig{
   130  		TenantProvider: "",
   131  		APIConfig: resync.APIEndpointsConfig{
   132  			EndpointTenantCreated: "___ :// ___ ",
   133  			EndpointTenantDeleted: "http://127.0.0.1:8111/badpath",
   134  			EndpointTenantUpdated: endpoint + "/empty",
   135  		},
   136  		FieldMapping:        resync.TenantFieldMapping{},
   137  		MovedSAFieldMapping: resync.MovedSubaccountsFieldMapping{},
   138  	}
   139  
   140  	client, err = resync.NewClient(resync.OAuth2Config{}, oauth.Standard, clientCfg, time.Second)
   141  	require.NoError(t, err)
   142  
   143  	client.SetHTTPClient(mockClient)
   144  
   145  	t.Run("Success when no content", func(t *testing.T) {
   146  		// WHEN
   147  		res, err := client.FetchTenantEventsPage(ctx, resync.UpdatedAccountType, queryParams)
   148  		// THEN
   149  		require.NoError(t, err)
   150  		require.Empty(t, res)
   151  	})
   152  
   153  	t.Run("Error when endpoint not parsable", func(t *testing.T) {
   154  		// WHEN
   155  		res, err := client.FetchTenantEventsPage(ctx, resync.CreatedAccountType, queryParams)
   156  		// THEN
   157  		require.EqualError(t, err, "parse \"___ :// ___ \": first path segment in URL cannot contain colon")
   158  		assert.Empty(t, res)
   159  	})
   160  
   161  	t.Run("Error when bad path", func(t *testing.T) {
   162  		// WHEN
   163  		res, err := client.FetchTenantEventsPage(ctx, resync.DeletedAccountType, queryParams)
   164  		// THEN
   165  		require.EqualError(t, err, "while sending get request: Get \"http://127.0.0.1:8111/badpath?pageNum=1&pageSize=1&timestamp=1\": dial tcp 127.0.0.1:8111: connect: connection refused")
   166  		assert.Empty(t, res)
   167  	})
   168  
   169  	// GIVEN
   170  	clientCfg = resync.ClientConfig{
   171  		TenantProvider: "",
   172  		APIConfig: resync.APIEndpointsConfig{
   173  			EndpointTenantCreated: endpoint + "/created",
   174  			EndpointTenantDeleted: endpoint + "/deleted",
   175  			EndpointTenantUpdated: endpoint + "/badRequest",
   176  		},
   177  		FieldMapping:        resync.TenantFieldMapping{},
   178  		MovedSAFieldMapping: resync.MovedSubaccountsFieldMapping{},
   179  	}
   180  	client, err = resync.NewClient(resync.OAuth2Config{}, oauth.Standard, clientCfg, time.Second)
   181  	require.NoError(t, err)
   182  
   183  	client.SetHTTPClient(mockClient)
   184  
   185  	t.Run("Error when status code not equal to 200 OK and 204 No Content is returned", func(t *testing.T) {
   186  		// WHEN
   187  		res, err := client.FetchTenantEventsPage(ctx, resync.UpdatedAccountType, queryParams)
   188  		// THEN
   189  		require.EqualError(t, err, fmt.Sprintf("request to \"%s/badRequest?pageNum=1&pageSize=1&timestamp=1\" returned status code 400 and body \"\"", endpoint))
   190  		assert.Empty(t, res)
   191  	})
   192  
   193  	// GIVEN
   194  	clientCfg = resync.ClientConfig{
   195  		APIConfig: resync.APIEndpointsConfig{EndpointSubaccountMoved: ""},
   196  	}
   197  	client, err = resync.NewClient(resync.OAuth2Config{}, oauth.Standard, clientCfg, time.Second)
   198  	require.NoError(t, err)
   199  
   200  	client.SetHTTPClient(mockClient)
   201  
   202  	t.Run("Skip fetching moved subaccount events when endpoint is not provided", func(t *testing.T) {
   203  		// WHEN
   204  		res, err := client.FetchTenantEventsPage(ctx, resync.MovedSubaccountType, queryParams)
   205  		// THEN
   206  		require.NoError(t, err)
   207  		require.Nil(t, res)
   208  	})
   209  }
   210  
   211  func fixHTTPClient(t *testing.T) (*http.Client, func(), string) {
   212  	mux := http.NewServeMux()
   213  
   214  	mux.HandleFunc("/ga-created", func(w http.ResponseWriter, r *http.Request) {
   215  		w.Header().Set("Content-Type", "application/json")
   216  		w.WriteHeader(http.StatusOK)
   217  		_, err := io.WriteString(w, fixCreatedTenantsJSON())
   218  		require.NoError(t, err)
   219  	})
   220  	mux.HandleFunc("/ga-deleted", func(w http.ResponseWriter, r *http.Request) {
   221  		w.Header().Set("Content-Type", "application/json")
   222  		w.WriteHeader(http.StatusOK)
   223  		_, err := io.WriteString(w, fixDeletedAccountsJSON())
   224  		require.NoError(t, err)
   225  	})
   226  	mux.HandleFunc("/ga-updated", func(w http.ResponseWriter, r *http.Request) {
   227  		w.Header().Set("Content-Type", "application/json")
   228  		w.WriteHeader(http.StatusOK)
   229  		_, err := io.WriteString(w, fixUpdatedAccountsJSON())
   230  		require.NoError(t, err)
   231  	})
   232  
   233  	mux.HandleFunc("/sub-created", func(w http.ResponseWriter, r *http.Request) {
   234  		w.Header().Set("Content-Type", "application/json")
   235  		w.WriteHeader(http.StatusOK)
   236  		_, err := io.WriteString(w, fixCreatedSubaccountsJSON())
   237  		require.NoError(t, err)
   238  	})
   239  	mux.HandleFunc("/sub-deleted", func(w http.ResponseWriter, r *http.Request) {
   240  		w.Header().Set("Content-Type", "application/json")
   241  		w.WriteHeader(http.StatusOK)
   242  		_, err := io.WriteString(w, fixDeletedSubaccountsJSON())
   243  		require.NoError(t, err)
   244  	})
   245  	mux.HandleFunc("/sub-updated", func(w http.ResponseWriter, r *http.Request) {
   246  		w.Header().Set("Content-Type", "application/json")
   247  		w.WriteHeader(http.StatusOK)
   248  		_, err := io.WriteString(w, fixUpdatedSubaccountsJSON())
   249  		require.NoError(t, err)
   250  	})
   251  	mux.HandleFunc("/sub-moved", func(w http.ResponseWriter, r *http.Request) {
   252  		w.Header().Set("Content-Type", "application/json")
   253  		w.WriteHeader(http.StatusOK)
   254  		_, err := io.WriteString(w, fixMovedSubaccountsJSON())
   255  		require.NoError(t, err)
   256  	})
   257  
   258  	mux.HandleFunc("/empty", func(w http.ResponseWriter, r *http.Request) {
   259  		w.WriteHeader(http.StatusNoContent)
   260  	})
   261  	mux.HandleFunc("/badRequest", func(w http.ResponseWriter, r *http.Request) {
   262  		w.WriteHeader(http.StatusBadRequest)
   263  	})
   264  
   265  	ts := httptest.NewServer(mux)
   266  
   267  	return ts.Client(), ts.Close, ts.URL
   268  }
   269  
   270  func fixCreatedTenantsJSON() string {
   271  	return `{
   272  "events": [
   273    {
   274      "id": 5,
   275      "type": "GLOBALACCOUNT_CREATION",
   276      "timestamp": "1579771215736",
   277      "eventData": "{\"id\":\"55\",\"displayName\":\"TEN5\",\"model\":\"default\"}"
   278    },
   279    {
   280      "id": 4,
   281      "type": "GLOBALACCOUNT_CREATION",
   282      "timestamp": "1579771215636",
   283      "eventData": "{\"id\":\"44\",\"displayName\":\"TEN4\",\"model\":\"default\"}"
   284    },
   285  	{
   286      "id": 3,
   287      "type": "GLOBALACCOUNT_CREATION",
   288      "timestamp": "1579771215536",
   289      "eventData": "{\"id\":\"33\",\"displayName\":\"TEN3\",\"model\":\"default\"}"
   290    },
   291  	{
   292      "id": 2,
   293      "type": "GLOBALACCOUNT_CREATION",
   294      "timestamp": "1579771215436",
   295      "eventData": "{\"id\":\"22\",\"displayName\":\"TEN2\",\"model\":\"default\"}"
   296    },
   297  	{
   298      "id": 1,
   299      "type": "GLOBALACCOUNT_CREATION",
   300      "timestamp": "1579771215336",
   301      "eventData": "{\"id\":\"11\",\"displayName\":\"TEN1\",\"model\":\"default\"}"
   302    }
   303  ],
   304  "totalResults": 5,
   305  "totalPages": 1
   306  }`
   307  }
   308  
   309  func fixUpdatedAccountsJSON() string {
   310  	return `{
   311  "events": [
   312  	{
   313      "id": 2,
   314      "type": "GLOBALACCOUNT_UPDATE",
   315      "timestamp": "1579771215436",
   316      "eventData": "{\"id\":\"22\",\"displayName\":\"TEN2\",\"model\":\"default\"}"
   317    },
   318  	{
   319      "id": 1,
   320      "type": "GLOBALACCOUNT_UPDATE",
   321      "timestamp": "1579771215336",
   322      "eventData": "{\"id\":\"11\",\"displayName\":\"TEN1\",\"model\":\"default\"}"
   323    }
   324  ],
   325  "totalResults": 2,
   326  "totalPages": 1
   327  }`
   328  }
   329  
   330  func fixDeletedAccountsJSON() string {
   331  	return `{
   332  "events": [
   333  	{
   334      "id": 2,
   335      "type": "GLOBALACCOUNT_DELETION",
   336      "timestamp": "1579771215436",
   337      "eventData": "{\"id\":\"22\",\"displayName\":\"TEN2\",\"model\":\"default\"}"
   338    },
   339  	{
   340      "id": 1,
   341      "type": "GLOBALACCOUNT_DELETION",
   342      "timestamp": "1579771215336",
   343      "eventData": "{\"id\":\"11\",\"displayName\":\"TEN1\",\"model\":\"default\"}"
   344    }
   345  ],
   346  "totalResults": 2,
   347  "totalPages": 1
   348  }`
   349  }
   350  
   351  func fixCreatedSubaccountsJSON() string {
   352  	return `{
   353  "events": [
   354    {
   355      "id": 5,
   356      "type": "SUBACCOUNT_CREATION",
   357  	 "region": "test-region",
   358      "timestamp": "1579771215736",
   359      "eventData": "{\"id\":\"55\",\"displayName\":\"TEN5\",\"model\":\"default\"}"
   360    },
   361    {
   362      "id": 4,
   363      "type": "SUBACCOUNT_CREATION",
   364  	 "region": "test-region",
   365      "timestamp": "1579771215636",
   366      "eventData": "{\"id\":\"44\",\"displayName\":\"TEN4\",\"model\":\"default\"}"
   367    },
   368  	{
   369      "id": 3,
   370      "type": "SUBACCOUNT_CREATION",
   371  	 "region": "test-region",
   372      "timestamp": "1579771215536",
   373      "eventData": "{\"id\":\"33\",\"displayName\":\"TEN3\",\"model\":\"default\"}"
   374    },
   375  	{
   376      "id": 2,
   377      "type": "SUBACCOUNT_CREATION",
   378  	 "region": "test-region",
   379      "timestamp": "1579771215436",
   380      "eventData": "{\"id\":\"22\",\"displayName\":\"TEN2\",\"model\":\"default\"}"
   381    },
   382  	{
   383      "id": 1,
   384      "type": "SUBACCOUNT_CREATION",
   385  	 "region": "test-region",
   386      "timestamp": "1579771215336",
   387      "eventData": "{\"id\":\"11\",\"displayName\":\"TEN1\",\"model\":\"default\"}"
   388    }
   389  ],
   390  "totalResults": 5,
   391  "totalPages": 1
   392  }`
   393  }
   394  
   395  func fixUpdatedSubaccountsJSON() string {
   396  	return `{
   397  "events": [
   398  	{
   399      "id": 2,
   400      "type": "SUBACCOUNT_UPDATE",
   401  	 "region": "test-region",
   402      "timestamp": "1579771215436",
   403      "eventData": "{\"id\":\"22\",\"displayName\":\"TEN2\",\"model\":\"default\"}"
   404    },
   405  	{
   406      "id": 1,
   407      "type": "SUBACCOUNT_UPDATE",
   408  	 "region": "test-region",
   409      "timestamp": "1579771215336",
   410      "eventData": "{\"id\":\"11\",\"displayName\":\"TEN1\",\"model\":\"default\"}"
   411    }
   412  ],
   413  "totalResults": 2,
   414  "totalPages": 1
   415  }`
   416  }
   417  
   418  func fixDeletedSubaccountsJSON() string {
   419  	return `{
   420  "events": [
   421  	{
   422      "id": 2,
   423      "type": "SUBACCOUNT_DELETION",
   424  	 "region": "test-region",
   425      "timestamp": "1579771215436",
   426      "eventData": "{\"id\":\"22\",\"displayName\":\"TEN2\",\"model\":\"default\"}"
   427    },
   428  	{
   429      "id": 1,
   430      "type": "SUBACCOUNT_DELETION",
   431  	 "region": "test-region",
   432      "timestamp": "1579771215336",
   433      "eventData": "{\"id\":\"11\",\"displayName\":\"TEN1\",\"model\":\"default\"}"
   434    }
   435  ],
   436  "totalResults": 2,
   437  "totalPages": 1
   438  }`
   439  }
   440  
   441  func fixMovedSubaccountsJSON() string {
   442  	return `{
   443  "events": [
   444  	{
   445      "id": 2,
   446      "type": "SUBACCOUNT_MOVED",
   447  	 "region": "test-region",
   448      "timestamp": "1579771215436",
   449      "eventData": "{\"id\":\"22\",\"source\":\"TEN1\",\"target\":\"TEN2\"}"
   450    },
   451  	{
   452      "id": 1,
   453      "type": "SUBACCOUNT_MOVED",
   454  	 "region": "test-region",
   455      "timestamp": "1579771215336",
   456      "eventData": "{\"id\":\"11\",\"source\":\"TEN3\",\"target\":\"TEN4\"}"
   457    }
   458  ],
   459  "totalResults": 2,
   460  "totalPages": 1
   461  }`
   462  }
   463  
   464  func TestNewClient(t *testing.T) {
   465  	const clientID = "client"
   466  	const clientSecret = "secret"
   467  
   468  	t.Run("expect error on invalid auth mode", func(t *testing.T) {
   469  		_, err := resync.NewClient(resync.OAuth2Config{}, "invalid-auth-mode", resync.ClientConfig{}, 1)
   470  		require.Error(t, err)
   471  	})
   472  
   473  	t.Run("standard client-credentials mode", func(t *testing.T) {
   474  		client, err := resync.NewClient(resync.OAuth2Config{
   475  			ClientID:     clientID,
   476  			ClientSecret: clientSecret,
   477  		}, oauth.Standard, resync.ClientConfig{}, 1)
   478  		require.NoError(t, err)
   479  
   480  		httpClient := client.GetHTTPClient()
   481  		tr, ok := httpClient.Transport.(*oauth2.Transport)
   482  		require.True(t, ok, "expected *oauth2.Transport")
   483  		require.Equal(t, http.DefaultClient.Transport, tr.Base)
   484  
   485  		cfg := clientcredentials.Config{
   486  			ClientID:     clientID,
   487  			ClientSecret: clientSecret,
   488  		}
   489  		expectedTokenSrc := cfg.TokenSource(context.Background())
   490  		require.Equal(t, expectedTokenSrc, tr.Source)
   491  	})
   492  
   493  	t.Run("mtls+client-secret mode", func(t *testing.T) {
   494  		const certificate = "-----BEGIN CERTIFICATE-----\nMIIDbjCCAlYCCQDg7pmtw8dIVTANBgkqhkiG9w0BAQsFADB5MQswCQYDVQQGEwJC\nRzENMAsGA1UECAwEVGVzdDENMAsGA1UEBwwEVGVzdDENMAsGA1UECgwEVGVzdDEN\nMAsGA1UECwwEVGVzdDENMAsGA1UEAwwEVGVzdDEfMB0GCSqGSIb3DQEJARYQdGVz\ndEBleGFtcGxlLmNvbTAeFw0yMjAxMjQxMTM4MDFaFw0zMjAxMjIxMTM4MDFaMHkx\nCzAJBgNVBAYTAkJHMQ0wCwYDVQQIDARUZXN0MQ0wCwYDVQQHDARUZXN0MQ0wCwYD\nVQQKDARUZXN0MQ0wCwYDVQQLDARUZXN0MQ0wCwYDVQQDDARUZXN0MR8wHQYJKoZI\nhvcNAQkBFhB0ZXN0QGV4YW1wbGUuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A\nMIIBCgKCAQEAuiFt98GUVTDSCHsOlBcblvUB/02uEmsalsG+DKEufzIVrp4DCxsA\nEsIN85Ywkd1Fsl0vwg9+3ibQlf1XtyXqJ6/jwm2zFdJPM3u2JfGGiiQpscHYp5hS\nlVscBjxZh1CQMKeBXltDsD64EV+XgHGN1aaw9mWKb6iSKsHLhBz594jYMFCnP3wH\nw9/hm6zBAhoF4Xr6UMOp4ZzzY8nzLCGPQuQ9UGp4lyAethrBpsqI6zAxjPKlqhmx\nL3591wkQgTzuL9th54yLEmyEvPTE26ONJBKylH2BqbAFiZPrwet0+PRJSflAfMU8\nYHqqo2AkaY1lmMAZiKDhj1RxMe/jt3HmVQIDAQABMA0GCSqGSIb3DQEBCwUAA4IB\nAQBx8BRhJ59UA3JDL+FHNKwIpxFewxjJwIGWqJTsOh4+rjPK3QeSnF0vt4cnLrCY\n+FLuhhUdFxjeFqJtWN7tHDK3ywSn/yZQTD5Nwcy/F1RmLjl91hjudxO/VewznOlq\nHJlDoM7kW9kOG6xS2HbbSaC1CzU33E90QOwcyCoeVXJ8aMDe6v/kWC65RoI9evg5\n2OxoARA8fpjyUphMTXuVNVI1kd2Uskpo8PePbc1h3OJVzYPIQ4+qMGsu7n3ZdwzI\nqDs2kdBD77k6cBQS+n7g5ETwv5OAgl5q1O17ye/YFNA/T3FhL9to6Nmrkqt7rlnF\nL8uAkeTGuHEATjmosQWUmbYi\n-----END CERTIFICATE-----\n"
   495  		const key = "-----BEGIN RSA PRIVATE KEY-----\nMIIEowIBAAKCAQEAuiFt98GUVTDSCHsOlBcblvUB/02uEmsalsG+DKEufzIVrp4D\nCxsAEsIN85Ywkd1Fsl0vwg9+3ibQlf1XtyXqJ6/jwm2zFdJPM3u2JfGGiiQpscHY\np5hSlVscBjxZh1CQMKeBXltDsD64EV+XgHGN1aaw9mWKb6iSKsHLhBz594jYMFCn\nP3wHw9/hm6zBAhoF4Xr6UMOp4ZzzY8nzLCGPQuQ9UGp4lyAethrBpsqI6zAxjPKl\nqhmxL3591wkQgTzuL9th54yLEmyEvPTE26ONJBKylH2BqbAFiZPrwet0+PRJSflA\nfMU8YHqqo2AkaY1lmMAZiKDhj1RxMe/jt3HmVQIDAQABAoIBAH+9xa0N6/FzqhIr\n8ltsaID38cD33QnC++KPYRFl5XViOEM5KrmKdEhragvM/dR92gGJtucmn1lzph/q\nWTLXEJbgPh4ID6pgRf79Xos38bAJFZxrf3e2MKdUei1FaeRWRD9AFqddV100DjvO\nMTnztPX2iujv00zCkl5J1pT7FgrtcYgDPxXQK7dIcHrc9bV9fdTQUnpbVIs/9U7a\n7Qk/eJnEkezbjQCk7+Pgt3ymR29s4vJvyPen3jek0FKhQCxAg6iA5ZOtY+J5AS9e\n3ozZLUEa3b0eOABMw8QnKMtGTmIhLbf9JhISK2Ltsisc/yHHH3KfFE2nayqjvLZf\n5GR62hkCgYEA612EgoRHg4+BSfPfLNG3xsSnM+a98nZOmyxgZ3eNFWpSvi+7MemL\nCJHpwwje412OU1wCc2MtWYvGFY+heL62FxT8+JJLntykZcTQzQoHX3wvaMwopWRi\nJdrv3tEDtSJo9za54kfrNqnVyaxu82r7zgxVbcNiAVR+n7cRXuov288CgYEAynLm\nVI7cIKBOM6U44unkKyIS99Bh57FPjE1QAIsEOiNCWZay4qmzdEboOXjtC95Qyyxn\nTb+MONybwXKkGiLZQZQ2SlgjtEMBDQ+ofk2fK+yHWf4VeLtYWJdBESaAz85xGCCY\nYqlqbFEQd8cl86gTne+emLXp8KrDMuXhbbPvMJsCgYEAgBISAacS9t6GfoQqA0xW\nkNz/EnnTD/UaTst15bci2O1S+tQkK0OmeNJU/eB80AFfabKeTsU/rwMklSTjuz0i\n/ipYgLWyWk47UnknGPsFCgscDQ1SbLTTxz972KWpO83uid6IhT2XGtaNU0D12pRz\nUipZ7fEsCgc9I5FM7XXG9vcCgYBp6xN2ygeBSl2fx6GrlpM5veoOnYeboLjtvsVM\ng28Cu8/K731H+WFaRH7bEtlyjC3ZHrItiznhxgn3e/M/eVwRY2nEG7kSZrv2CWsu\nKY5NfMKT4st5Dwt5zijMwEhEcM3awbL4a4qygPcMs7S3dghNaUCgxQxQTgcyafM3\nYhySYQKBgF7pqQW7ESo1Mp9by+HzJBJsSju5zPBrCZrx8rFAMLCk1uDAIRcUuQtq\n+YwKU8ViemkOHWfN6bePap3/kdVHUxj2xJ6xTAUYHpVOQVMhTw1UmOikiV4FwUo+\nGb5Nk5evWBGhsl2LFqoOqhvFpjftv8+qgRHxmWtj4EoJYWng+hRz\n-----END RSA PRIVATE KEY-----\n"
   496  
   497  		certCfg := resync.X509Config{
   498  			Cert: certificate,
   499  			Key:  key,
   500  		}
   501  
   502  		tlsCert, err := certCfg.ParseCertificate()
   503  		require.NoError(t, err)
   504  
   505  		oauthCfg := resync.OAuth2Config{
   506  			X509Config: certCfg,
   507  			ClientID:   clientID,
   508  		}
   509  		client, err := resync.NewClient(oauthCfg, oauth.Mtls, resync.ClientConfig{}, 1)
   510  		require.NoError(t, err)
   511  
   512  		httpClient := client.GetHTTPClient()
   513  		tr, ok := httpClient.Transport.(*oauth2.Transport)
   514  		require.True(t, ok, "expected *oauth2.Transport")
   515  
   516  		expectedTransport := &http.Transport{
   517  			TLSClientConfig: &tls.Config{
   518  				Certificates:       []tls.Certificate{*tlsCert},
   519  				InsecureSkipVerify: oauthCfg.SkipSSLValidation,
   520  			},
   521  		}
   522  		require.Equal(t, tr.Base, expectedTransport)
   523  	})
   524  }