github.com/docker/compose-on-kubernetes@v0.5.0/cmd/api-server/cli/root_test.go (about) 1 package cli 2 3 import ( 4 "os" 5 "path/filepath" 6 "strings" 7 "testing" 8 9 "github.com/docker/compose-on-kubernetes/internal/keys" 10 11 "github.com/stretchr/testify/assert" 12 genericoptions "k8s.io/apiserver/pkg/server/options" 13 certutil "k8s.io/client-go/util/cert" 14 ) 15 16 // TestGenerateBundleAndMerge simulate 2 consecutive runs of the API server for the same POD (e.g.: simulating node crash) 17 // It checks 2 aspects: 18 // - the generated CA and Cert have correct info encoded in them 19 // - when a new CA is generated for the same POD as another one, the "merge" operation discard the old CA from the bundle (but keeps other CAS valid for other PODs) 20 func TestGenerateBundleAndMerge(t *testing.T) { 21 hostname, err := os.Hostname() 22 assert.NoError(t, err) 23 // simulate the generation of the first CA+Cert bundle 24 oldOpts := &apiServerOptions{ 25 RecommendedOptions: &genericoptions.RecommendedOptions{ 26 SecureServing: &genericoptions.SecureServingOptionsWithLoopback{ 27 SecureServingOptions: &genericoptions.SecureServingOptions{}, 28 }, 29 }, 30 serviceName: "old-service-name", 31 serviceNamespace: "old-namespace", 32 } 33 err = generateCertificateIfRequired(oldOpts) 34 if oldOpts.caBundleFile != "" { 35 defer os.RemoveAll(filepath.Dir(oldOpts.caBundleFile)) 36 } 37 assert.NoError(t, err) 38 39 // load old CA from the generated file, and checks its characteristics 40 oldCA, err := certutil.CertsFromFile(oldOpts.caBundleFile) 41 assert.NoError(t, err) 42 assert.Len(t, oldCA, 1) 43 assert.Equal(t, "compose-api-ca-"+strings.ToLower(hostname), oldCA[0].Subject.CommonName) 44 45 // load old cert from the generated file and checks its characteristics 46 oldCert, err := certutil.CertsFromFile(oldOpts.RecommendedOptions.SecureServing.ServerCert.CertKey.CertFile) 47 assert.NoError(t, err) 48 assert.Len(t, oldCert, 1) 49 assert.Equal(t, "old-service-name.old-namespace.svc", oldCert[0].Subject.CommonName) 50 assert.Contains(t, oldCert[0].DNSNames, "old-service-name.old-namespace.svc") 51 assert.Contains(t, oldCert[0].DNSNames, "localhost") 52 assert.Len(t, oldCert[0].IPAddresses, 1) 53 assert.True(t, oldCert[0].IPAddresses[0].Equal(loopbackIP)) 54 55 // simulate the generation of the new CA for the same POD 56 newOpts := &apiServerOptions{ 57 RecommendedOptions: &genericoptions.RecommendedOptions{ 58 SecureServing: &genericoptions.SecureServingOptionsWithLoopback{ 59 SecureServingOptions: &genericoptions.SecureServingOptions{}, 60 }, 61 }, 62 serviceName: "new-service-name", 63 serviceNamespace: "new-namespace", 64 } 65 err = generateCertificateIfRequired(newOpts) 66 if newOpts.caBundleFile != "" { 67 defer os.RemoveAll(filepath.Dir(newOpts.caBundleFile)) 68 } 69 assert.NoError(t, err) 70 newCA, err := certutil.CertsFromFile(newOpts.caBundleFile) 71 assert.NoError(t, err) 72 73 // create an other CA that should not be touched by the merge 74 otherCa, err := keys.NewSelfSignedCA("other-ca", nil) 75 assert.NoError(t, err) 76 77 // old ca bundle contains both the old CA and the "other" CA 78 oldCABundle := append(keys.EncodeCertPEM(oldCA[0]), keys.EncodeCertPEM(otherCa.Cert())...) 79 80 // after merging, the bundle should contain the new CA and the "other" CA (but not the old CA) 81 expectedNewCABundle := append(keys.EncodeCertPEM(otherCa.Cert()), keys.EncodeCertPEM(newCA[0])...) 82 newBundle, err := mergeCABundle(oldCABundle, keys.EncodeCertPEM(newCA[0])) 83 assert.NoError(t, err) 84 assert.EqualValues(t, newBundle, expectedNewCABundle) 85 }