agones.dev/agones@v1.54.0/cmd/allocator/main_test.go (about)

     1  // Copyright 2019 Google LLC All Rights Reserved.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //	http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  package main
    15  
    16  import (
    17  	"context"
    18  	"crypto/tls"
    19  	"crypto/x509"
    20  	"encoding/pem"
    21  	"net/http"
    22  	"os"
    23  	"testing"
    24  
    25  	pb "agones.dev/agones/pkg/allocation/go"
    26  	allocationv1 "agones.dev/agones/pkg/apis/allocation/v1"
    27  	"github.com/stretchr/testify/assert"
    28  	"google.golang.org/grpc/codes"
    29  	"google.golang.org/grpc/status"
    30  	corev1 "k8s.io/api/core/v1"
    31  	k8serror "k8s.io/apimachinery/pkg/api/errors"
    32  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    33  	k8sruntime "k8s.io/apimachinery/pkg/runtime"
    34  )
    35  
    36  func TestAllocateHandler(t *testing.T) {
    37  	t.Parallel()
    38  
    39  	h := serviceHandler{
    40  		allocationCallback: func(_ *allocationv1.GameServerAllocation) (k8sruntime.Object, error) {
    41  			return &allocationv1.GameServerAllocation{
    42  				ObjectMeta: metav1.ObjectMeta{
    43  					Namespace: "default",
    44  				},
    45  				Status: allocationv1.GameServerAllocationStatus{
    46  					State: allocationv1.GameServerAllocationContention,
    47  				},
    48  			}, nil
    49  		},
    50  	}
    51  
    52  	request := &pb.AllocationRequest{
    53  		Namespace: "ns",
    54  		MultiClusterSetting: &pb.MultiClusterSetting{
    55  			Enabled: true,
    56  		},
    57  	}
    58  
    59  	response, err := h.Allocate(context.Background(), request)
    60  	if !assert.Nil(t, response) {
    61  		return
    62  	}
    63  	st, ok := status.FromError(err)
    64  	if !assert.True(t, ok) {
    65  		return
    66  	}
    67  	assert.Equal(t, st.Code(), codes.Aborted)
    68  }
    69  
    70  func TestAllocateHandlerReturnsError(t *testing.T) {
    71  	t.Parallel()
    72  
    73  	h := serviceHandler{
    74  		allocationCallback: func(_ *allocationv1.GameServerAllocation) (k8sruntime.Object, error) {
    75  			return nil, k8serror.NewBadRequest("error")
    76  		},
    77  	}
    78  
    79  	request := &pb.AllocationRequest{}
    80  	_, err := h.Allocate(context.Background(), request)
    81  	if assert.Error(t, err) {
    82  		assert.Equal(t, "error", err.Error())
    83  	}
    84  }
    85  
    86  func TestGetTlsCert(t *testing.T) {
    87  	t.Parallel()
    88  	cert1, err := tls.X509KeyPair(serverCert1, serverKey1)
    89  	assert.Nil(t, err, "expected (serverCert1, serverKey1) to create a cert")
    90  
    91  	cert2, err := tls.X509KeyPair(serverCert2, serverKey2)
    92  	assert.Nil(t, err, "expected (serverCert2, serverKey2) to create a cert")
    93  
    94  	h := serviceHandler{
    95  		tlsCert: &cert1,
    96  	}
    97  
    98  	retrievedCert1, err := h.getTLSCert(nil)
    99  	assert.Nil(t, err, "expected getTlsCert() to not fail")
   100  	assert.Equal(t, cert1.Certificate, retrievedCert1.Certificate, "expected the retrieved cert to be equal to the original one")
   101  
   102  	h.tlsCert = &cert2
   103  	retrievedCert2, err := h.getTLSCert(nil)
   104  	assert.Nil(t, err, "expected getTlsCert() to not fail")
   105  	assert.Equal(t, cert2.Certificate, retrievedCert2.Certificate, "expected the retrieved cert to be equal to the original one")
   106  }
   107  
   108  func TestHandlingStatus(t *testing.T) {
   109  	t.Parallel()
   110  
   111  	errorMessage := "GameServerAllocation is invalid"
   112  	h := serviceHandler{
   113  		allocationCallback: func(_ *allocationv1.GameServerAllocation) (k8sruntime.Object, error) {
   114  			return &metav1.Status{
   115  				Status:  metav1.StatusFailure,
   116  				Message: errorMessage,
   117  				Reason:  metav1.StatusReasonInvalid,
   118  				Details: &metav1.StatusDetails{
   119  					Kind:  "GameServerAllocation",
   120  					Group: allocationv1.SchemeGroupVersion.Group,
   121  				},
   122  				Code: http.StatusUnprocessableEntity,
   123  			}, nil
   124  		},
   125  	}
   126  
   127  	request := &pb.AllocationRequest{}
   128  	_, err := h.Allocate(context.Background(), request)
   129  	if !assert.Error(t, err, "expecting failure") {
   130  		return
   131  	}
   132  
   133  	st, ok := status.FromError(err)
   134  	if !ok {
   135  		t.Errorf("expecting status error: %v", err)
   136  	}
   137  	assert.Equal(t, 422, int(st.Code()))
   138  	assert.Contains(t, st.Message(), errorMessage)
   139  }
   140  
   141  func TestBadReturnType(t *testing.T) {
   142  	t.Parallel()
   143  
   144  	h := serviceHandler{
   145  		allocationCallback: func(_ *allocationv1.GameServerAllocation) (k8sruntime.Object, error) {
   146  			return &corev1.Secret{}, nil
   147  		},
   148  	}
   149  
   150  	request := &pb.AllocationRequest{}
   151  	_, err := h.Allocate(context.Background(), request)
   152  	if !assert.Error(t, err, "expecting failure") {
   153  		return
   154  	}
   155  
   156  	st, ok := status.FromError(err)
   157  	if !ok {
   158  		t.Errorf("expecting status error: %v", err)
   159  	}
   160  	assert.Equal(t, codes.Internal, st.Code())
   161  	assert.Contains(t, st.Message(), "internal server error")
   162  }
   163  
   164  func TestVerifyClientCertificateSucceeds(t *testing.T) {
   165  	t.Parallel()
   166  
   167  	crt := []byte(clientCert)
   168  	certPool := x509.NewCertPool()
   169  	assert.True(t, certPool.AppendCertsFromPEM(crt))
   170  
   171  	h := serviceHandler{
   172  		caCertPool: certPool,
   173  	}
   174  
   175  	block, _ := pem.Decode(crt)
   176  	input := [][]byte{block.Bytes}
   177  	assert.Nil(t, h.verifyClientCertificate(input, nil),
   178  		"verifyClientCertificate failed.")
   179  }
   180  
   181  func TestVerifyClientCertificateFails(t *testing.T) {
   182  	t.Parallel()
   183  
   184  	crt := []byte(clientCert)
   185  	certPool := x509.NewCertPool()
   186  	h := serviceHandler{
   187  		caCertPool: certPool,
   188  	}
   189  
   190  	block, _ := pem.Decode(crt)
   191  	input := [][]byte{block.Bytes}
   192  	assert.Error(t, h.verifyClientCertificate(input, nil),
   193  		"verifyClientCertificate() succeeded, expected error.")
   194  }
   195  
   196  func TestGettingCaCert(t *testing.T) {
   197  	t.Parallel()
   198  
   199  	file, err := os.CreateTemp(".", "*.crt")
   200  	if assert.Nil(t, err) {
   201  		defer os.Remove(file.Name()) // nolint: errcheck
   202  		_, err = file.WriteString(clientCert)
   203  		if assert.Nil(t, err) {
   204  			certPool, err := getCACertPool("./")
   205  			if assert.Nil(t, err) {
   206  				// linting complaints certPool.Subjects() has been deprecated since Go 1.18.
   207  				// But since this cert doesn't come from SystemCertPool, it doesn't seem behavior
   208  				// should be impacted. So marking the lint as ignored.
   209  				assert.Len(t, certPool.Subjects(), 1) // nolint
   210  			}
   211  		}
   212  	}
   213  }
   214  
   215  var clientCert = `-----BEGIN CERTIFICATE-----
   216  MIIDuzCCAqOgAwIBAgIUduDWtqpUsp3rZhCEfUrzI05laVIwDQYJKoZIhvcNAQEL
   217  BQAwbTELMAkGA1UEBhMCR0IxDzANBgNVBAgMBkxvbmRvbjEPMA0GA1UEBwwGTG9u
   218  ZG9uMRgwFgYDVQQKDA9HbG9iYWwgU2VjdXJpdHkxFjAUBgNVBAsMDUlUIERlcGFy
   219  dG1lbnQxCjAIBgNVBAMMASowHhcNMTkwNTAyMjIzMDQ3WhcNMjkwNDI5MjIzMDQ3
   220  WjBtMQswCQYDVQQGEwJHQjEPMA0GA1UECAwGTG9uZG9uMQ8wDQYDVQQHDAZMb25k
   221  b24xGDAWBgNVBAoMD0dsb2JhbCBTZWN1cml0eTEWMBQGA1UECwwNSVQgRGVwYXJ0
   222  bWVudDEKMAgGA1UEAwwBKjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
   223  AKGDasjadVwe0bXUEQfZCkMEAkzn0qTud3RYytympmaS0c01SWFNZwPRO0rpdIOZ
   224  fyXVXVOAhgmgCR6QuXySmyQIoYl/D6tVhc5r9FyWPIBtzQKCJTX0mZOZwMn22qvo
   225  bfnDnVsZ1Ny3RLZIF3um3xovvePXyg1z7D/NvCogNuYpyUUEITPZX6ss5ods/U78
   226  BxLhKrT8iyu61ZC+ZegbHQqFRngbeb348gE1JwKTslDfe4oH7tZ+bNDZxnGcvh9j
   227  eyagpM0zys4gFfQf/vfD2aEsUJ+GesUQC6uGVoGnTFshFhBsAK6vpIQ4ZQujaJ0r
   228  NKgJ/ccBJFiJXMCR44yWFY0CAwEAAaNTMFEwHQYDVR0OBBYEFEe1gDd8JpzgnvOo
   229  1AEloAXxmxHCMB8GA1UdIwQYMBaAFEe1gDd8JpzgnvOo1AEloAXxmxHCMA8GA1Ud
   230  EwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAI5GyuakVgunerCGCSN7Ghsr
   231  ys9vJytbyT+BLmxNBPSXWQwcm3g9yCDdgf0Y3q3Eef7IEZu4I428318iLzhfKln1
   232  ua4fxvmTFKJ65lQKNkc6Y4e3w1t+C2HOl6fOIVT231qsCoM5SAwQQpqAzEUj6kZl
   233  x+3avw9KSlXqR/mCAkePyoKvprxeb6RVDdq92Ug0qzoAHLpvIkuHdlF0dNp6/kO0
   234  1pVL0BqW+6UTimSSvH8F/cMeYKbkhpE1u2c/NtNwsR2jN4M9kl3KHqkynk67PfZv
   235  pwlCqZx4M8FpdfCbOZeRLzClUBdD5qzev0L3RNUx7UJzEIN+4LCBv37DIojNOyA=
   236  -----END CERTIFICATE-----
   237  `
   238  
   239  var serverCert1 = []byte(`-----BEGIN CERTIFICATE-----
   240  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
   269  -----END CERTIFICATE-----`)
   270  var serverCert2 = []byte(`-----BEGIN CERTIFICATE-----
   271  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
   300  -----END CERTIFICATE-----`)
   301  
   302  var serverKey1 = []byte(`-----BEGIN PRIVATE KEY-----
   303  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
   352  kEIJI+7KY0lG3Ig3y5XPRM6kzYKGjA==
   353  -----END PRIVATE KEY-----`)
   354  var serverKey2 = []byte(`-----BEGIN PRIVATE KEY-----
   355  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
   404  xA2QN+Zomk0SRjSeYzZO/DT3LTykJXE=
   405  -----END PRIVATE KEY-----`)