github.com/argoproj/argo-cd/v3@v3.2.1/util/db/certificate_test.go (about)

     1  package db
     2  
     3  import (
     4  	"testing"
     5  
     6  	"github.com/stretchr/testify/assert"
     7  	"github.com/stretchr/testify/require"
     8  	corev1 "k8s.io/api/core/v1"
     9  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    10  	"k8s.io/apimachinery/pkg/runtime"
    11  	"k8s.io/client-go/kubernetes/fake"
    12  
    13  	"github.com/argoproj/argo-cd/v3/pkg/apis/application/v1alpha1"
    14  	"github.com/argoproj/argo-cd/v3/util/settings"
    15  )
    16  
    17  const (
    18  	TestCert1CN = "CN=foo.example.com,OU=SpecOps,O=Capone\\, Inc,L=Chicago,ST=IL,C=US"
    19  	TestCert2CN = "CN=bar.example.com,OU=Testsuite,O=Testing Corp,L=Hanover,ST=Lower Saxony,C=DE"
    20  )
    21  
    22  var TestTLSSubjects = []string{
    23  	"CN=foo.example.com,OU=SpecOps,O=Capone\\, Inc,L=Chicago,ST=IL,C=US",
    24  	"CN=bar.example.com,OU=Testsuite,O=Testing Corp,L=Hanover,ST=Lower Saxony,C=DE",
    25  }
    26  
    27  const TestTLSValidSingleCert = `
    28  -----BEGIN CERTIFICATE-----
    29  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
    60  -----END CERTIFICATE-----
    61  `
    62  
    63  const TestTLSInvalidPEMData = `
    64  MIIF1zCCA7+gAwIBAgIUQdTcSHY2Sxd3Tq/v1eIEZPCNbOowDQYJKoZIhvcNAQEL
    65  BQAwezELMAkGA1UEBhMCREUxFTATBgNVBAgMDExvd2VyIFNheG9ueTEQMA4GA1UE
    66  BwwHSGFub3ZlcjEVMBMGA1UECgwMVGVzdGluZyBDb3JwMRIwEAYDVQQLDAlUZXN0
    67  c3VpdGUxGDAWBgNVBAMMD2Jhci5leGFtcGxlLmNvbTAeFw0xOTA3MDgxMzU2MTda
    68  Fw0yMDA3MDcxMzU2MTdaMHsxCzAJBgNVBAYTAkRFMRUwEwYDVQQIDAxMb3dlciBT
    69  YXhvbnkxEDAOBgNVBAcMB0hhbm92ZXIxFTATBgNVBAoMDFRlc3RpbmcgQ29ycDES
    70  MBAGA1UECwwJVGVzdHN1aXRlMRgwFgYDVQQDDA9iYXIuZXhhbXBsZS5jb20wggIi
    71  MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCv4mHMdVUcafmaSHVpUM0zZWp5
    72  NFXfboxA4inuOkE8kZlbGSe7wiG9WqLirdr39Ts+WSAFA6oANvbzlu3JrEQ2CHPc
    73  CNQm6diPREFwcDPFCe/eMawbwkQAPVSHPts0UoRxnpZox5pn69ghncBR+jtvx+/u
    74  P6HdwW0qqTvfJnfAF1hBJ4oIk2AXiip5kkIznsAh9W6WRy6nTVCeetmIepDOGe0G
    75  ZJIRn/OfSz7NzKylfDCat2z3EAutyeT/5oXZoWOmGg/8T7pn/pR588GoYYKRQnp+
    76  YilqCPFX+az09EqqK/iHXnkdZ/Z2fCuU+9M/Zhrnlwlygl3RuVBI6xhm/ZsXtL2E
    77  Gxa61lNy6pyx5+hSxHEFEJshXLtioRd702VdLKxEOuYSXKeJDs1x9o6cJ75S6hko
    78  `
    79  
    80  const TestTLSInvalidSingleCert = `
    81  -----BEGIN CERTIFICATE-----
    82  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
   113  XWyb96wrUlv+E8I=
   114  -----END CERTIFICATE-----
   115  `
   116  
   117  const TestTLSValidMultiCert = `
   118  -----BEGIN CERTIFICATE-----
   119  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
   150  -----END CERTIFICATE-----
   151  -----BEGIN CERTIFICATE-----
   152  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
   183  XWyb96wrUlv+E8I=
   184  -----END CERTIFICATE-----
   185  `
   186  
   187  // Taken from hack/ssh_known_hosts
   188  const TestValidSSHKnownHostsData = `
   189  # BitBucket
   190  bitbucket.org ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDQeJzhupRu0u0cdegZIa8e86EG2qOCsIsD1Xw0xSeiPDlCr7kq97NLmMbpKTX6Esc30NuoqEEHCuc7yWtwp8dI76EEEB1VqY9QJq6vk+aySyboD5QF61I/1WeTwu+deCbgKMGbUijeXhtfbxSxm6JwGrXrhBdofTsbKRUsrN1WoNgUa8uqN1Vx6WAJw1JHPhglEGGHea6QICwJOAr/6mrui/oB7pkaWKHj3z7d1IC4KWLtY47elvjbaTlkN04Kc/5LFEirorGYVbt15kAUlqGM65pk6ZBxtaO3+30LVlORZkxOh+LKL/BvbZ/iRNhItLqNyieoQj/uh/7Iv4uyH/cV/0b4WDSd3DptigWq84lJubb9t/DnZlrJazxyDCulTmKdOR7vs9gMTo+uoIrPSb8ScTtvw65+odKAlBj59dhnVp9zd7QUojOpXlL62Aw56U4oO+FALuevvMjiWeavKhJqlR7i5n9srYcrNV7ttmDw7kf/97P5zauIhxcjX+xHv4M=
   191  # GitHub
   192  github.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCj7ndNxQowgcQnjshcLrqPEiiphnt+VTTvDP6mHBL9j1aNUkY4Ue1gvwnGLVlOhGeYrnZaMgRK6+PKCUXaDbC7qtbW8gIkhL7aGCsOr/C56SJMy/BCZfxd1nWzAOxSDPgVsmerOBYfNqltV9/hWCqBywINIR+5dIg6JTJ72pcEpEjcYgXkE2YEFXV1JHnsKgbLWNlhScqb2UmyRkQyytRLtL+38TGxkxCflmO+5Z8CSSNY7GidjMIZ7Q4zMjA2n1nGrlTDkzwDCsw+wqFPGQA179cnfGWOWRVruj16z6XyvxvjJwbz0wQZ75XK5tKSb7FNyeIEs4TT4jk+S4dhPeAUC5y+bDYirYgM4GC7uEnztnZyaVWQ7B381AK4Qdrwt51ZqExKbQpTUNn+EjqoTwvqNj4kqx5QUCI0ThS/YkOxJCXmPUWZbhjpCg56i+2aB6CmK2JGhn57K5mj0MNdBXA4/WnwH6XoPWJzK5Nyu2zB3nAZp+S5hpQs+p1vN1/wsjk=
   193  # GitLab
   194  gitlab.com ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBFSMqzJeV9rUzU4kWitGjeR4PWSa29SPqJ1fVkhtj3Hw9xjLVXVYrU9QlYWrOLXBpQ6KWjbjTDTdDkoohFzgbEY=
   195  gitlab.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAfuCHKVTjquxvt6CM6tdG4SLp1Btn/nOeHHE5UOzRdf
   196  gitlab.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCsj2bNKTBSpIYDEGk9KxsGh3mySTRgMtXL583qmBpzeQ+jqCMRgBqB98u3z++J1sKlXHWfM9dyhSevkMwSbhoR8XIq/U0tCNyokEi/ueaBMCvbcTHhO7FcwzY92WK4Yt0aGROY5qX2UKSeOvuP4D6TPqKF1onrSzH9bx9XUf2lEdWT/ia1NEKjunUqu1xOB/StKDHMoX4/OKyIzuS0q/T1zOATthvasJFoPrAjkohTyaDUz2LN5JoH839hViyEG82yB+MjcFV5MU3N1l1QL3cVUCh93xSaua1N85qivl+siMkPGbO5xR/En4iEY6K2XPASUEMaieWVNTRCtJ4S8H+9
   197  # Azure
   198  ssh.dev.azure.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC7Hr1oTWqNqOlzGJOfGJ4NakVyIzf1rXYd4d7wo6jBlkLvCA4odBlL0mDUyZ0/QUfTTqeu+tm22gOsv+VrVTMk6vwRU75gY/y9ut5Mb3bR5BV58dKXyq9A9UeB5Cakehn5Zgm6x1mKoVyf+FFn26iYqXJRgzIZZcZ5V6hrE0Qg39kZm4az48o0AUbf6Sp4SLdvnuMa2sVNwHBboS7EJkm57XQPVU3/QpyNLHbWDdzwtrlS+ez30S3AdYhLKEOxAG8weOnyrtLJAUen9mTkol8oII1edf7mWWbWVf0nBmly21+nZcmCTISQBtdcyPaEno7fFQMDD26/s0lfKob4Kw8H
   199  vs-ssh.visualstudio.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC7Hr1oTWqNqOlzGJOfGJ4NakVyIzf1rXYd4d7wo6jBlkLvCA4odBlL0mDUyZ0/QUfTTqeu+tm22gOsv+VrVTMk6vwRU75gY/y9ut5Mb3bR5BV58dKXyq9A9UeB5Cakehn5Zgm6x1mKoVyf+FFn26iYqXJRgzIZZcZ5V6hrE0Qg39kZm4az48o0AUbf6Sp4SLdvnuMa2sVNwHBboS7EJkm57XQPVU3/QpyNLHbWDdzwtrlS+ez30S3AdYhLKEOxAG8weOnyrtLJAUen9mTkol8oII1edf7mWWbWVf0nBmly21+nZcmCTISQBtdcyPaEno7fFQMDD26/s0lfKob4Kw8H
   200  `
   201  
   202  const TestInvalidSSHKnownHostsData = `
   203  bitbucket.org AAAAB3NzaC1yc2EAAAADAQABAAABgQDQeJzhupRu0u0cdegZIa8e86EG2qOCsIsD1Xw0xSeiPDlCr7kq97NLmMbpKTX6Esc30NuoqEEHCuc7yWtwp8dI76EEEB1VqY9QJq6vk+aySyboD5QF61I/1WeTwu+deCbgKMGbUijeXhtfbxSxm6JwGrXrhBdofTsbKRUsrN1WoNgUa8uqN1Vx6WAJw1JHPhglEGGHea6QICwJOAr/6mrui/oB7pkaWKHj3z7d1IC4KWLtY47elvjbaTlkN04Kc/5LFEirorGYVbt15kAUlqGM65pk6ZBxtaO3+30LVlORZkxOh+LKL/BvbZ/iRNhItLqNyieoQj/uh/7Iv4uyH/cV/0b4WDSd3DptigWq84lJubb9t/DnZlrJazxyDCulTmKdOR7vs9gMTo+uoIrPSb8ScTtvw65+odKAlBj59dhnVp9zd7QUojOpXlL62Aw56U4oO+FALuevvMjiWeavKhJqlR7i5n9srYcrNV7ttmDw7kf/97P5zauIhxcjX+xHv4M=
   204  # GitHub
   205  github.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCj7ndNxQowgcQnjshcLrqPEiiphnt+VTTvDP6mHBL9j1aNUkY4Ue1gvwnGLVlOhGeYrnZaMgRK6+PKCUXaDbC7qtbW8gIkhL7aGCsOr/C56SJMy/BCZfxd1nWzAOxSDPgVsmerOBYfNqltV9/hWCqBywINIR+5dIg6JTJ72pcEpEjcYgXkE2YEFXV1JHnsKgbLWNlhScqb2UmyRkQyytRLtL+38TGxkxCflmO+5Z8CSSNY7GidjMIZ7Q4zMjA2n1nGrlTDkzwDCsw+wqFPGQA179cnfGWOWRVruj16z6XyvxvjJwbz0wQZ75XK5tKSb7FNyeIEs4TT4jk+S4dhPeAUC5y+bDYirYgM4GC7uEnztnZyaVWQ7B381AK4Qdrwt51ZqExKbQpTUNn+EjqoTwvqNj4kqx5QUCI0ThS/YkOxJCXmPUWZbhjpCg56i+2aB6CmK2JGhn57K5mj0MNdBXA4/WnwH6XoPWJzK5Nyu2zB3nAZp+S5hpQs+p1vN1/wsjk=
   206  # GitLab
   207  gitlab.com ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBFSMqzJeV9rUzU4kWitGjeR4PWSa29SPqJ1fVkhtj3Hw9xjLVXVYrU9QlYWrOLXBpQ6KWjbjTDTdDkoohFzgbEY=
   208  gitlab.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAfuCHKVTjquxvt6CM6tdG4SLp1Btn/nOeHHE5UOzRdf
   209  gitlab.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCsj2bNKTBSpIYDEGk9KxsGh3mySTRgMtXL583qmBpzeQ+jqCMRgBqB98u3z++J1sKlXHWfM9dyhSevkMwSbhoR8XIq/U0tCNyokEi/ueaBMCvbcTHhO7FcwzY92WK4Yt0aGROY5qX2UKSeOvuP4D6TPqKF1onrSzH9bx9XUf2lEdWT/ia1NEKjunUqu1xOB/StKDHMoX4/OKyIzuS0q/T1zOATthvasJFoPrAjkohTyaDUz2LN5JoH839hViyEG82yB+MjcFV5MU3N1l1QL3cVUCh93xSaua1N85qivl+siMkPGbO5xR/En4iEY6K2XPASUEMaieWVNTRCtJ4S8H+9
   210  # Azure
   211  ssh.dev.azure.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC7Hr1oTWqNqOlzGJOfGJ4NakVyIzf1rXYd4d7wo6jBlkLvCA4odBlL0mDUyZ0/QUfTTqeu+tm22gOsv+VrVTMk6vwRU75gY/y9ut5Mb3bR5BV58dKXyq9A9UeB5Cakehn5Zgm6x1mKoVyf+FFn26iYqXJRgzIZZcZ5V6hrE0Qg39kZm4az48o0AUbf6Sp4SLdvnuMa2sVNwHBboS7EJkm57XQPVU3/QpyNLHbWDdzwtrlS+ez30S3AdYhLKEOxAG8weOnyrtLJAUen9mTkol8oII1edf7mWWbWVf0nBmly21+nZcmCTISQBtdcyPaEno7fFQMDD26/s0lfKob4Kw8H
   212  vs-ssh.visualstudio.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC7Hr1oTWqNqOlzGJOfGJ4NakVyIzf1rXYd4d7wo6jBlkLvCA4odBlL0mDUyZ0/QUfTTqeu+tm22gOsv+VrVTMk6vwRU75gY/y9ut5Mb3bR5BV58dKXyq9A9UeB5Cakehn5Zgm6x1mKoVyf+FFn26iYqXJRgzIZZcZ5V6hrE0Qg39kZm4az48o0AUbf6Sp4SLdvnuMa2sVNwHBboS7EJkm57XQPVU3/QpyNLHbWDdzwtrlS+ez30S3AdYhLKEOxAG8weOnyrtLJAUen9mTkol8oII1edf7mWWbWVf0nBmly21+nZcmCTISQBtdcyPaEno7fFQMDD26/s0lfKob4Kw8H
   213  `
   214  
   215  var TestSSHHostnameEntries = []string{
   216  	"bitbucket.org",
   217  	"github.com",
   218  	"gitlab.com",
   219  	"gitlab.com",
   220  	"gitlab.com",
   221  	"ssh.dev.azure.com",
   222  	"vs-ssh.visualstudio.com",
   223  }
   224  
   225  var TestSSHSubtypes = []string{
   226  	"ssh-rsa",
   227  	"ssh-rsa",
   228  	"ecdsa-sha2-nistp256",
   229  	"ssh-ed25519",
   230  	"ssh-rsa",
   231  	"ssh-rsa",
   232  	"ssh-rsa",
   233  }
   234  
   235  var TestTLSHostnames = []string{
   236  	"test.example.com",
   237  	"test.example.com",
   238  	"github.com",
   239  }
   240  
   241  const (
   242  	TestNumSSHKnownHostsExpected   = 7
   243  	TestNumTLSCertificatesExpected = 3
   244  )
   245  
   246  func getCertClientset() *fake.Clientset {
   247  	cm := corev1.ConfigMap{
   248  		ObjectMeta: metav1.ObjectMeta{
   249  			Name:      "argocd-cm",
   250  			Namespace: testNamespace,
   251  			Labels: map[string]string{
   252  				"app.kubernetes.io/part-of": "argocd",
   253  			},
   254  		},
   255  		Data: nil,
   256  	}
   257  
   258  	sshCM := corev1.ConfigMap{
   259  		ObjectMeta: metav1.ObjectMeta{
   260  			Name:      "argocd-ssh-known-hosts-cm",
   261  			Namespace: testNamespace,
   262  			Labels: map[string]string{
   263  				"app.kubernetes.io/part-of": "argocd",
   264  			},
   265  		},
   266  		Data: map[string]string{
   267  			"ssh_known_hosts": TestValidSSHKnownHostsData,
   268  		},
   269  	}
   270  
   271  	tlsCM := corev1.ConfigMap{
   272  		ObjectMeta: metav1.ObjectMeta{
   273  			Name:      "argocd-tls-certs-cm",
   274  			Namespace: testNamespace,
   275  			Labels: map[string]string{
   276  				"app.kubernetes.io/part-of": "argocd",
   277  			},
   278  		},
   279  		Data: map[string]string{
   280  			"test.example.com": TestTLSValidMultiCert,
   281  			"gitlab.com":       TestTLSValidSingleCert,
   282  		},
   283  	}
   284  
   285  	return fake.NewClientset([]runtime.Object{&cm, &sshCM, &tlsCM}...)
   286  }
   287  
   288  func TestListCertificate(t *testing.T) {
   289  	clientset := getCertClientset()
   290  	db := NewDB(testNamespace, settings.NewSettingsManager(t.Context(), clientset, testNamespace), clientset)
   291  	assert.NotNil(t, db)
   292  
   293  	// List all SSH known host entries from configuration.
   294  	// Expected: List of 7 entries
   295  	certList, err := db.ListRepoCertificates(t.Context(), &CertificateListSelector{
   296  		HostNamePattern: "*",
   297  		CertType:        "ssh",
   298  	})
   299  	require.NoError(t, err)
   300  	assert.NotNil(t, certList)
   301  	assert.Len(t, certList.Items, TestNumSSHKnownHostsExpected)
   302  	for idx, entry := range certList.Items {
   303  		assert.Equal(t, entry.ServerName, TestSSHHostnameEntries[idx])
   304  		assert.Equal(t, entry.CertSubType, TestSSHSubtypes[idx])
   305  	}
   306  
   307  	// List all TLS certificates from configuration.
   308  	// Expected: List of 3 entries
   309  	certList, err = db.ListRepoCertificates(t.Context(), &CertificateListSelector{
   310  		HostNamePattern: "*",
   311  		CertType:        "https",
   312  	})
   313  	require.NoError(t, err)
   314  	assert.NotNil(t, certList)
   315  	assert.Len(t, certList.Items, TestNumTLSCertificatesExpected)
   316  
   317  	// List all certificates using selector
   318  	// Expected: List of 10 entries
   319  	certList, err = db.ListRepoCertificates(t.Context(), &CertificateListSelector{
   320  		HostNamePattern: "*",
   321  		CertType:        "*",
   322  	})
   323  	require.NoError(t, err)
   324  	assert.NotNil(t, certList)
   325  	assert.Len(t, certList.Items, TestNumTLSCertificatesExpected+TestNumSSHKnownHostsExpected)
   326  
   327  	// List all certificates using nil selector
   328  	// Expected: List of 10 entries
   329  	certList, err = db.ListRepoCertificates(t.Context(), nil)
   330  	require.NoError(t, err)
   331  	assert.NotNil(t, certList)
   332  	assert.Len(t, certList.Items, TestNumTLSCertificatesExpected+TestNumSSHKnownHostsExpected)
   333  
   334  	// List all certificates matching a host name pattern
   335  	// Expected: List of 4 entries, all with servername gitlab.com
   336  	certList, err = db.ListRepoCertificates(t.Context(), &CertificateListSelector{
   337  		HostNamePattern: "gitlab.com",
   338  		CertType:        "*",
   339  	})
   340  	require.NoError(t, err)
   341  	assert.NotNil(t, certList)
   342  	assert.Len(t, certList.Items, 4)
   343  	for _, entry := range certList.Items {
   344  		assert.Equal(t, "gitlab.com", entry.ServerName)
   345  	}
   346  
   347  	// List all TLS certificates matching a host name pattern
   348  	certList, err = db.ListRepoCertificates(t.Context(), &CertificateListSelector{
   349  		HostNamePattern: "gitlab.com",
   350  		CertType:        "https",
   351  	})
   352  	require.NoError(t, err)
   353  	assert.NotNil(t, certList)
   354  	assert.Len(t, certList.Items, 1)
   355  	assert.Equal(t, "gitlab.com", certList.Items[0].ServerName)
   356  	assert.Equal(t, "https", certList.Items[0].CertType)
   357  }
   358  
   359  func TestCreateSSHKnownHostEntries(t *testing.T) {
   360  	clientset := getCertClientset()
   361  	db := NewDB(testNamespace, settings.NewSettingsManager(t.Context(), clientset, testNamespace), clientset)
   362  	assert.NotNil(t, db)
   363  
   364  	// Valid known hosts entry
   365  	certList, err := db.CreateRepoCertificate(t.Context(), &v1alpha1.RepositoryCertificateList{
   366  		Items: []v1alpha1.RepositoryCertificate{
   367  			{
   368  				ServerName: "foo.example.com",
   369  				CertType:   "ssh",
   370  				CertData:   []byte("ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDioSMcGxdVkHaQzRjP71nY4mgVHXjuZiYN9NBiUxNZ0DYGjTIENI3uV45XxrS6PQfoyekUlVlHK2jwpcPrqAg6rlAdMD5WIxzvCnFjCuPA6Ljk8p0ZmYbvriDcgtj+UfGEdyUTgxH2gch6KwTY0eAbLue15IuXtoNzpLxk29iGRi5ZXNAbSBjeB3hm2PKLa6LnDqdkvc+nqoYqn1Fvx7ZJIh0apBCJpOtHPON4rnl7QQvNg9pWulZ5GKcpYMRfTpvHyFTEyrsVT5GH38l9s355GqU7GxQ/i6Tj1D0MKrIB2WmdjOnujM/ELLsrkYspMhn8ZRpCphN/LTcrOWsb0AM69drvYlhc6cnNAtC4UXp0GUy1HsBiJCsUm9/1Gz23VLDRvWop8yE8+PE3Ho5eL7ad9wmOG0mSOYEqVvAstmd8vzbD6oRuY8qV8X3tt9ph2tMAve0Qbo0NN3c51c9OfdXtJaSyckjEjaK7zjnArnYfladZZVlf2Tv8FsV0sJmfSAE="),
   371  			},
   372  		},
   373  	}, false)
   374  	require.NoError(t, err)
   375  	assert.NotNil(t, certList)
   376  	assert.Len(t, certList.Items, 1)
   377  
   378  	// Valid known hosts entry
   379  	certList, err = db.CreateRepoCertificate(t.Context(), &v1alpha1.RepositoryCertificateList{
   380  		Items: []v1alpha1.RepositoryCertificate{
   381  			{
   382  				ServerName: "[foo.example.com]:2222",
   383  				CertType:   "ssh",
   384  				CertData:   []byte("ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDioSMcGxdVkHaQzRjP71nY4mgVHXjuZiYN9NBiUxNZ0DYGjTIENI3uV45XxrS6PQfoyekUlVlHK2jwpcPrqAg6rlAdMD5WIxzvCnFjCuPA6Ljk8p0ZmYbvriDcgtj+UfGEdyUTgxH2gch6KwTY0eAbLue15IuXtoNzpLxk29iGRi5ZXNAbSBjeB3hm2PKLa6LnDqdkvc+nqoYqn1Fvx7ZJIh0apBCJpOtHPON4rnl7QQvNg9pWulZ5GKcpYMRfTpvHyFTEyrsVT5GH38l9s355GqU7GxQ/i6Tj1D0MKrIB2WmdjOnujM/ELLsrkYspMhn8ZRpCphN/LTcrOWsb0AM69drvYlhc6cnNAtC4UXp0GUy1HsBiJCsUm9/1Gz23VLDRvWop8yE8+PE3Ho5eL7ad9wmOG0mSOYEqVvAstmd8vzbD6oRuY8qV8X3tt9ph2tMAve0Qbo0NN3c51c9OfdXtJaSyckjEjaK7zjnArnYfladZZVlf2Tv8FsV0sJmfSAE="),
   385  			},
   386  		},
   387  	}, false)
   388  	require.NoError(t, err)
   389  	assert.NotNil(t, certList)
   390  	assert.Len(t, certList.Items, 1)
   391  
   392  	// Invalid hostname
   393  	// Result: Error
   394  	certList, err = db.CreateRepoCertificate(t.Context(), &v1alpha1.RepositoryCertificateList{
   395  		Items: []v1alpha1.RepositoryCertificate{
   396  			{
   397  				ServerName: "foo..example.com",
   398  				CertType:   "ssh",
   399  				CertData:   []byte("ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDioSMcGxdVkHaQzRjP71nY4mgVHXjuZiYN9NBiUxNZ0DYGjTIENI3uV45XxrS6PQfoyekUlVlHK2jwpcPrqAg6rlAdMD5WIxzvCnFjCuPA6Ljk8p0ZmYbvriDcgtj+UfGEdyUTgxH2gch6KwTY0eAbLue15IuXtoNzpLxk29iGRi5ZXNAbSBjeB3hm2PKLa6LnDqdkvc+nqoYqn1Fvx7ZJIh0apBCJpOtHPON4rnl7QQvNg9pWulZ5GKcpYMRfTpvHyFTEyrsVT5GH38l9s355GqU7GxQ/i6Tj1D0MKrIB2WmdjOnujM/ELLsrkYspMhn8ZRpCphN/LTcrOWsb0AM69drvYlhc6cnNAtC4UXp0GUy1HsBiJCsUm9/1Gz23VLDRvWop8yE8+PE3Ho5eL7ad9wmOG0mSOYEqVvAstmd8vzbD6oRuY8qV8X3tt9ph2tMAve0Qbo0NN3c51c9OfdXtJaSyckjEjaK7zjnArnYfladZZVlf2Tv8FsV0sJmfSAE="),
   400  			},
   401  		},
   402  	}, false)
   403  	require.Error(t, err)
   404  	assert.Nil(t, certList)
   405  
   406  	// Check if it really was added
   407  	// Result: List of 1 entry
   408  	certList, err = db.ListRepoCertificates(t.Context(), &CertificateListSelector{
   409  		HostNamePattern: "foo.example.com",
   410  		CertType:        "ssh",
   411  	})
   412  	require.NoError(t, err)
   413  	assert.NotNil(t, certList)
   414  	assert.Len(t, certList.Items, 1)
   415  
   416  	// Existing cert, same data, no upsert
   417  	// Result: no error, should return 0 added certificates
   418  	certList, err = db.CreateRepoCertificate(t.Context(), &v1alpha1.RepositoryCertificateList{
   419  		Items: []v1alpha1.RepositoryCertificate{
   420  			{
   421  				ServerName: "foo.example.com",
   422  				CertType:   "ssh",
   423  				CertData:   []byte("ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDioSMcGxdVkHaQzRjP71nY4mgVHXjuZiYN9NBiUxNZ0DYGjTIENI3uV45XxrS6PQfoyekUlVlHK2jwpcPrqAg6rlAdMD5WIxzvCnFjCuPA6Ljk8p0ZmYbvriDcgtj+UfGEdyUTgxH2gch6KwTY0eAbLue15IuXtoNzpLxk29iGRi5ZXNAbSBjeB3hm2PKLa6LnDqdkvc+nqoYqn1Fvx7ZJIh0apBCJpOtHPON4rnl7QQvNg9pWulZ5GKcpYMRfTpvHyFTEyrsVT5GH38l9s355GqU7GxQ/i6Tj1D0MKrIB2WmdjOnujM/ELLsrkYspMhn8ZRpCphN/LTcrOWsb0AM69drvYlhc6cnNAtC4UXp0GUy1HsBiJCsUm9/1Gz23VLDRvWop8yE8+PE3Ho5eL7ad9wmOG0mSOYEqVvAstmd8vzbD6oRuY8qV8X3tt9ph2tMAve0Qbo0NN3c51c9OfdXtJaSyckjEjaK7zjnArnYfladZZVlf2Tv8FsV0sJmfSAE="),
   424  			},
   425  		},
   426  	}, false)
   427  	require.NoError(t, err)
   428  	assert.NotNil(t, certList)
   429  	assert.Empty(t, certList.Items)
   430  
   431  	// Existing cert, different data, no upsert
   432  	// Result: Error
   433  	certList, err = db.CreateRepoCertificate(t.Context(), &v1alpha1.RepositoryCertificateList{
   434  		Items: []v1alpha1.RepositoryCertificate{
   435  			{
   436  				ServerName: "foo.example.com",
   437  				CertType:   "ssh",
   438  				CertData:   []byte("ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCj7ndNxQowgcQnjshcLrqPEiiphnt+VTTvDP6mHBL9j1aNUkY4Ue1gvwnGLVlOhGeYrnZaMgRK6+PKCUXaDbC7qtbW8gIkhL7aGCsOr/C56SJMy/BCZfxd1nWzAOxSDPgVsmerOBYfNqltV9/hWCqBywINIR+5dIg6JTJ72pcEpEjcYgXkE2YEFXV1JHnsKgbLWNlhScqb2UmyRkQyytRLtL+38TGxkxCflmO+5Z8CSSNY7GidjMIZ7Q4zMjA2n1nGrlTDkzwDCsw+wqFPGQA179cnfGWOWRVruj16z6XyvxvjJwbz0wQZ75XK5tKSb7FNyeIEs4TT4jk+S4dhPeAUC5y+bDYirYgM4GC7uEnztnZyaVWQ7B381AK4Qdrwt51ZqExKbQpTUNn+EjqoTwvqNj4kqx5QUCI0ThS/YkOxJCXmPUWZbhjpCg56i+2aB6CmK2JGhn57K5mj0MNdBXA4/WnwH6XoPWJzK5Nyu2zB3nAZp+S5hpQs+p1vN1/wsjk="),
   439  			},
   440  		},
   441  	}, false)
   442  	require.Error(t, err)
   443  	assert.Nil(t, certList)
   444  
   445  	// Existing cert, different data, upsert
   446  	certList, err = db.CreateRepoCertificate(t.Context(), &v1alpha1.RepositoryCertificateList{
   447  		Items: []v1alpha1.RepositoryCertificate{
   448  			{
   449  				ServerName: "foo.example.com",
   450  				CertType:   "ssh",
   451  				CertData:   []byte("ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCj7ndNxQowgcQnjshcLrqPEiiphnt+VTTvDP6mHBL9j1aNUkY4Ue1gvwnGLVlOhGeYrnZaMgRK6+PKCUXaDbC7qtbW8gIkhL7aGCsOr/C56SJMy/BCZfxd1nWzAOxSDPgVsmerOBYfNqltV9/hWCqBywINIR+5dIg6JTJ72pcEpEjcYgXkE2YEFXV1JHnsKgbLWNlhScqb2UmyRkQyytRLtL+38TGxkxCflmO+5Z8CSSNY7GidjMIZ7Q4zMjA2n1nGrlTDkzwDCsw+wqFPGQA179cnfGWOWRVruj16z6XyvxvjJwbz0wQZ75XK5tKSb7FNyeIEs4TT4jk+S4dhPeAUC5y+bDYirYgM4GC7uEnztnZyaVWQ7B381AK4Qdrwt51ZqExKbQpTUNn+EjqoTwvqNj4kqx5QUCI0ThS/YkOxJCXmPUWZbhjpCg56i+2aB6CmK2JGhn57K5mj0MNdBXA4/WnwH6XoPWJzK5Nyu2zB3nAZp+S5hpQs+p1vN1/wsjk="),
   452  			},
   453  		},
   454  	}, true)
   455  	require.NoError(t, err)
   456  	assert.NotNil(t, certList)
   457  	assert.Len(t, certList.Items, 1)
   458  
   459  	// Invalid known hosts entry, case 1: key sub type missing
   460  	// Result: Error
   461  	certList, err = db.CreateRepoCertificate(t.Context(), &v1alpha1.RepositoryCertificateList{
   462  		Items: []v1alpha1.RepositoryCertificate{
   463  			{
   464  				ServerName: "bar.example.com",
   465  				CertType:   "ssh",
   466  				CertData:   []byte("AAAAB3NzaC1yc2EAAAADAQABAAABgQDioSMcGxdVkHaQzRjP71nY4mgVHXjuZiYN9NBiUxNZ0DYGjTIENI3uV45XxrS6PQfoyekUlVlHK2jwpcPrqAg6rlAdMD5WIxzvCnFjCuPA6Ljk8p0ZmYbvriDcgtj+UfGEdyUTgxH2gch6KwTY0eAbLue15IuXtoNzpLxk29iGRi5ZXNAbSBjeB3hm2PKLa6LnDqdkvc+nqoYqn1Fvx7ZJIh0apBCJpOtHPON4rnl7QQvNg9pWulZ5GKcpYMRfTpvHyFTEyrsVT5GH38l9s355GqU7GxQ/i6Tj1D0MKrIB2WmdjOnujM/ELLsrkYspMhn8ZRpCphN/LTcrOWsb0AM69drvYlhc6cnNAtC4UXp0GUy1HsBiJCsUm9/1Gz23VLDRvWop8yE8+PE3Ho5eL7ad9wmOG0mSOYEqVvAstmd8vzbD6oRuY8qV8X3tt9ph2tMAve0Qbo0NN3c51c9OfdXtJaSyckjEjaK7zjnArnYfladZZVlf2Tv8FsV0sJmfSAE="),
   467  			},
   468  		},
   469  	}, false)
   470  	require.Error(t, err)
   471  	assert.Nil(t, certList)
   472  
   473  	// Invalid known hosts entry, case 2: invalid base64 data
   474  	// Result: Error
   475  	certList, err = db.CreateRepoCertificate(t.Context(), &v1alpha1.RepositoryCertificateList{
   476  		Items: []v1alpha1.RepositoryCertificate{
   477  			{
   478  				ServerName: "bar.example.com",
   479  				CertType:   "ssh",
   480  				CertData:   []byte("ssh-rsa AAAAB3Nza1yc2EAAAADAQABAAABgQDioSMcGxdVkHaQzRjP71nY4mgVHXjuZiYN9NBiUxNZ0DYGjTIENI3uV45XxrS6PQfoyekUlVlHK2jwpcPrqAg6rlAdMD5WIxzvCnFjCuPA6Ljk8p0ZmYbvriDcgtj+UfGEdyUTgxH2gch6KwTY0eAbLue15IuXtoNzpLxk29iGRi5ZXNAbSBjeB3hm2PKLa6LnDqdkvc+nqoYqn1Fvx7ZJIh0apBCJpOtHPON4rnl7QQvNg9pWulZ5GKcpYMRfTpvHyFTEyrsVT5GH38l9s355GqU7GxQ/i6Tj1D0MKrIB2WmdjOnujM/ELLsrkYspMhn8ZRpCphN/LTcrOWsb0AM69drvYlhc6cnNAtC4UXp0GUy1HsBiJCsUm9/1Gz23VLDRvWop8yE8+PE3Ho5eL7ad9wmOG0mSOYEqVvAstmd8vzbD6oRuY8qV8X3tt9ph2tMAve0Qbo0NN3c51c9OfdXtJaSyckjEjaK7zjnArnYfladZZVlf2Tv8FsV0sJmfSAE="),
   481  			},
   482  		},
   483  	}, false)
   484  	require.Error(t, err)
   485  	assert.Nil(t, certList)
   486  }
   487  
   488  func TestCreateTLSCertificates(t *testing.T) {
   489  	clientset := getCertClientset()
   490  	db := NewDB(testNamespace, settings.NewSettingsManager(t.Context(), clientset, testNamespace), clientset)
   491  	assert.NotNil(t, db)
   492  
   493  	// Valid TLS certificate
   494  	// Expected: List of 1 entry
   495  	certList, err := db.CreateRepoCertificate(t.Context(), &v1alpha1.RepositoryCertificateList{
   496  		Items: []v1alpha1.RepositoryCertificate{
   497  			{
   498  				ServerName: "foo.example.com",
   499  				CertType:   "https",
   500  				CertData:   []byte(TestTLSValidSingleCert),
   501  			},
   502  		},
   503  	}, false)
   504  	require.NoError(t, err)
   505  	assert.NotNil(t, certList)
   506  	assert.Len(t, certList.Items, 1)
   507  
   508  	// Invalid hostname
   509  	// Result: Error
   510  	certList, err = db.CreateRepoCertificate(t.Context(), &v1alpha1.RepositoryCertificateList{
   511  		Items: []v1alpha1.RepositoryCertificate{
   512  			{
   513  				ServerName: "foo..example",
   514  				CertType:   "https",
   515  				CertData:   []byte(TestTLSValidSingleCert),
   516  			},
   517  		},
   518  	}, false)
   519  	require.Error(t, err)
   520  	assert.Nil(t, certList)
   521  
   522  	// Check if it really was added
   523  	// Result: Return new certificate
   524  	certList, err = db.ListRepoCertificates(t.Context(), &CertificateListSelector{
   525  		HostNamePattern: "foo.example.com",
   526  		CertType:        "https",
   527  	})
   528  	require.NoError(t, err)
   529  	assert.NotNil(t, certList)
   530  	assert.Len(t, certList.Items, 1)
   531  
   532  	// Valid TLS certificates, multiple PEMs in data
   533  	// Expected: List of 2 entry
   534  	certList, err = db.CreateRepoCertificate(t.Context(), &v1alpha1.RepositoryCertificateList{
   535  		Items: []v1alpha1.RepositoryCertificate{
   536  			{
   537  				ServerName: "bar.example.com",
   538  				CertType:   "https",
   539  				CertData:   []byte(TestTLSValidMultiCert),
   540  			},
   541  		},
   542  	}, false)
   543  	require.NoError(t, err)
   544  	assert.NotNil(t, certList)
   545  	assert.Len(t, certList.Items, 2)
   546  
   547  	// Check if it really was added
   548  	// Result: Return new certificate
   549  	certList, err = db.ListRepoCertificates(t.Context(), &CertificateListSelector{
   550  		HostNamePattern: "bar.example.com",
   551  		CertType:        "https",
   552  	})
   553  	require.NoError(t, err)
   554  	assert.NotNil(t, certList)
   555  	assert.Len(t, certList.Items, 2)
   556  
   557  	// Valid TLS certificate, existing cert, same data, no upsert
   558  	// Expected: List of 0 entry
   559  	certList, err = db.CreateRepoCertificate(t.Context(), &v1alpha1.RepositoryCertificateList{
   560  		Items: []v1alpha1.RepositoryCertificate{
   561  			{
   562  				ServerName: "foo.example.com",
   563  				CertType:   "https",
   564  				CertData:   []byte(TestTLSValidSingleCert),
   565  			},
   566  		},
   567  	}, false)
   568  	require.NoError(t, err)
   569  	assert.NotNil(t, certList)
   570  	assert.Empty(t, certList.Items)
   571  
   572  	// Valid TLS certificate, existing cert, different data, no upsert
   573  	// Expected: Error
   574  	certList, err = db.CreateRepoCertificate(t.Context(), &v1alpha1.RepositoryCertificateList{
   575  		Items: []v1alpha1.RepositoryCertificate{
   576  			{
   577  				ServerName: "foo.example.com",
   578  				CertType:   "https",
   579  				CertData:   []byte(TestTLSValidMultiCert),
   580  			},
   581  		},
   582  	}, false)
   583  	require.Error(t, err)
   584  	assert.Nil(t, certList)
   585  
   586  	// Valid TLS certificate, existing cert, different data, upsert
   587  	// Expected: List of 2 entries
   588  	certList, err = db.CreateRepoCertificate(t.Context(), &v1alpha1.RepositoryCertificateList{
   589  		Items: []v1alpha1.RepositoryCertificate{
   590  			{
   591  				ServerName: "foo.example.com",
   592  				CertType:   "https",
   593  				CertData:   []byte(TestTLSValidMultiCert),
   594  			},
   595  		},
   596  	}, true)
   597  	require.NoError(t, err)
   598  	assert.NotNil(t, certList)
   599  	assert.Len(t, certList.Items, 2)
   600  
   601  	// Check if upsert was successful
   602  	// Expected: List of 2 entries, matching hostnames & cert types
   603  	certList, err = db.ListRepoCertificates(t.Context(), &CertificateListSelector{
   604  		HostNamePattern: "foo.example.com",
   605  		CertType:        "https",
   606  	})
   607  	require.NoError(t, err)
   608  	assert.NotNil(t, certList)
   609  	assert.Len(t, certList.Items, 2)
   610  	for _, entry := range certList.Items {
   611  		assert.Equal(t, "foo.example.com", entry.ServerName)
   612  		assert.Equal(t, "https", entry.CertType)
   613  	}
   614  
   615  	// Invalid PEM data, new cert
   616  	// Expected: Error
   617  	certList, err = db.CreateRepoCertificate(t.Context(), &v1alpha1.RepositoryCertificateList{
   618  		Items: []v1alpha1.RepositoryCertificate{
   619  			{
   620  				ServerName: "baz.example.com",
   621  				CertType:   "https",
   622  				CertData:   []byte(TestTLSInvalidPEMData),
   623  			},
   624  		},
   625  	}, false)
   626  	require.Error(t, err)
   627  	assert.Nil(t, certList)
   628  
   629  	// Valid PEM data, new cert, but invalid certificate
   630  	// Expected: Error
   631  	certList, err = db.CreateRepoCertificate(t.Context(), &v1alpha1.RepositoryCertificateList{
   632  		Items: []v1alpha1.RepositoryCertificate{
   633  			{
   634  				ServerName: "baz.example.com",
   635  				CertType:   "https",
   636  				CertData:   []byte(TestTLSInvalidSingleCert),
   637  			},
   638  		},
   639  	}, false)
   640  	require.Error(t, err)
   641  	assert.Nil(t, certList)
   642  
   643  	// Invalid PEM data, existing cert, upsert
   644  	// Expected: Error
   645  	certList, err = db.CreateRepoCertificate(t.Context(), &v1alpha1.RepositoryCertificateList{
   646  		Items: []v1alpha1.RepositoryCertificate{
   647  			{
   648  				ServerName: "baz.example.com",
   649  				CertType:   "https",
   650  				CertData:   []byte(TestTLSInvalidPEMData),
   651  			},
   652  		},
   653  	}, true)
   654  	require.Error(t, err)
   655  	assert.Nil(t, certList)
   656  
   657  	// Valid PEM data, existing cert, but invalid certificate, upsert
   658  	// Expected: Error
   659  	certList, err = db.CreateRepoCertificate(t.Context(), &v1alpha1.RepositoryCertificateList{
   660  		Items: []v1alpha1.RepositoryCertificate{
   661  			{
   662  				ServerName: "baz.example.com",
   663  				CertType:   "https",
   664  				CertData:   []byte(TestTLSInvalidSingleCert),
   665  			},
   666  		},
   667  	}, true)
   668  	require.Error(t, err)
   669  	assert.Nil(t, certList)
   670  }
   671  
   672  func TestRemoveSSHKnownHosts(t *testing.T) {
   673  	clientset := getCertClientset()
   674  	db := NewDB(testNamespace, settings.NewSettingsManager(t.Context(), clientset, testNamespace), clientset)
   675  	assert.NotNil(t, db)
   676  
   677  	// Remove single SSH known hosts entry by hostname
   678  	// Expected: List of 1 entry
   679  	certList, err := db.RemoveRepoCertificates(t.Context(), &CertificateListSelector{
   680  		HostNamePattern: "github.com",
   681  		CertType:        "ssh",
   682  	})
   683  	require.NoError(t, err)
   684  	assert.NotNil(t, certList)
   685  	assert.Len(t, certList.Items, 1)
   686  
   687  	// Check whether entry was really removed
   688  	// Expected: List of 0 entries
   689  	certList, err = db.ListRepoCertificates(t.Context(), &CertificateListSelector{
   690  		HostNamePattern: "github.com",
   691  		CertType:        "ssh",
   692  	})
   693  	require.NoError(t, err)
   694  	assert.NotNil(t, certList)
   695  	assert.Empty(t, certList.Items)
   696  
   697  	// Remove single SSH known hosts entry by sub type
   698  	// Expected: List of 1 entry
   699  	certList, err = db.RemoveRepoCertificates(t.Context(), &CertificateListSelector{
   700  		CertType:    "ssh",
   701  		CertSubType: "ssh-ed25519",
   702  	})
   703  	require.NoError(t, err)
   704  	assert.NotNil(t, certList)
   705  	assert.Len(t, certList.Items, 1)
   706  
   707  	// Check whether entry was really removed
   708  	// Expected: List of 0 entries
   709  	certList, err = db.ListRepoCertificates(t.Context(), &CertificateListSelector{
   710  		CertType:    "ssh",
   711  		CertSubType: "ssh-ed25519",
   712  	})
   713  	require.NoError(t, err)
   714  	assert.NotNil(t, certList)
   715  	assert.Empty(t, certList.Items)
   716  
   717  	// Remove all remaining SSH known hosts entries
   718  	// Expected: List of 5 entry
   719  	certList, err = db.RemoveRepoCertificates(t.Context(), &CertificateListSelector{
   720  		CertType: "ssh",
   721  	})
   722  	require.NoError(t, err)
   723  	assert.NotNil(t, certList)
   724  	assert.Len(t, certList.Items, 5)
   725  
   726  	// Check whether the entries were really removed
   727  	// Expected: List of 0 entries
   728  	certList, err = db.ListRepoCertificates(t.Context(), &CertificateListSelector{
   729  		CertType: "ssh",
   730  	})
   731  	require.NoError(t, err)
   732  	assert.NotNil(t, certList)
   733  	assert.Empty(t, certList.Items)
   734  }
   735  
   736  func TestRemoveTLSCertificates(t *testing.T) {
   737  	clientset := getCertClientset()
   738  	db := NewDB(testNamespace, settings.NewSettingsManager(t.Context(), clientset, testNamespace), clientset)
   739  	assert.NotNil(t, db)
   740  
   741  	// Remove single TLS certificate entry by hostname
   742  	// Expected: List of 1 entry
   743  	certList, err := db.RemoveRepoCertificates(t.Context(), &CertificateListSelector{
   744  		HostNamePattern: "gitlab.com",
   745  		CertType:        "https",
   746  	})
   747  	require.NoError(t, err)
   748  	assert.NotNil(t, certList)
   749  	assert.Len(t, certList.Items, 1)
   750  
   751  	// Check whether entry was really removed
   752  	// Expected: List of 0 entries
   753  	certList, err = db.ListRepoCertificates(t.Context(), &CertificateListSelector{
   754  		HostNamePattern: "gitlab.com",
   755  		CertType:        "https",
   756  	})
   757  	require.NoError(t, err)
   758  	assert.NotNil(t, certList)
   759  	assert.Empty(t, certList.Items)
   760  
   761  	// Remove all TLS certificate entry for hostname
   762  	// Expected: List of 2 entry
   763  	certList, err = db.RemoveRepoCertificates(t.Context(), &CertificateListSelector{
   764  		HostNamePattern: "test.example.com",
   765  		CertType:        "https",
   766  	})
   767  	require.NoError(t, err)
   768  	assert.NotNil(t, certList)
   769  	assert.Len(t, certList.Items, 2)
   770  
   771  	// Check whether entries were really removed
   772  	// Expected: List of 0 entries
   773  	certList, err = db.ListRepoCertificates(t.Context(), &CertificateListSelector{
   774  		HostNamePattern: "test.example.com",
   775  		CertType:        "https",
   776  	})
   777  	require.NoError(t, err)
   778  	assert.NotNil(t, certList)
   779  	assert.Empty(t, certList.Items)
   780  }