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  }