github.com/hugh712/snapd@v0.0.0-20200910133618-1a99902bd583/overlord/configstate/configcore/certs_test.go (about)

     1  // -*- Mode: Go; indent-tabs-mode: t -*-
     2  
     3  /*
     4   * Copyright (C) 2020 Canonical Ltd
     5   *
     6   * This program is free software: you can redistribute it and/or modify
     7   * it under the terms of the GNU General Public License version 3 as
     8   * published by the Free Software Foundation.
     9   *
    10   * This program is distributed in the hope that it will be useful,
    11   * but WITHOUT ANY WARRANTY; without even the implied warranty of
    12   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    13   * GNU General Public License for more details.
    14   *
    15   * You should have received a copy of the GNU General Public License
    16   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
    17   *
    18   */
    19  
    20  package configcore_test
    21  
    22  import (
    23  	"path/filepath"
    24  
    25  	. "gopkg.in/check.v1"
    26  
    27  	"github.com/snapcore/snapd/dirs"
    28  	"github.com/snapcore/snapd/overlord/configstate/configcore"
    29  	"github.com/snapcore/snapd/testutil"
    30  )
    31  
    32  type certsSuite struct {
    33  	configcoreSuite
    34  }
    35  
    36  var _ = Suite(&certsSuite{})
    37  
    38  func (s *certsSuite) TestConfigureCertsUnhappyName(c *C) {
    39  	err := configcore.Run(&mockConf{
    40  		state: s.state,
    41  		changes: map[string]interface{}{
    42  			"store-certs.cert-illegal-!": "xxx",
    43  		},
    44  	})
    45  	c.Assert(err, ErrorMatches, `cannot set store ssl certificate under name "core.store-certs.cert-illegal-!": name must only contain word characters or a dash`)
    46  }
    47  
    48  var mockCert = `-----BEGIN CERTIFICATE-----
    49  MIIEIDCCAwigAwIBAgIQNE7VVyDV7exJ9C/ON9srbTANBgkqhkiG9w0BAQUFADCB
    50  qTELMAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjEoMCYGA1UECxMf
    51  Q2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMvKGMpIDIw
    52  MDYgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxHzAdBgNV
    53  BAMTFnRoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EwHhcNMDYxMTE3MDAwMDAwWhcNMzYw
    54  NzE2MjM1OTU5WjCBqTELMAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5j
    55  LjEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjE4MDYG
    56  A1UECxMvKGMpIDIwMDYgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNl
    57  IG9ubHkxHzAdBgNVBAMTFnRoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EwggEiMA0GCSqG
    58  SIb3DQEBAQUAA4IBDwAwggEKAoIBAQCsoPD7gFnUnMekz52hWXMJEEUMDSxuaPFs
    59  W0hoSVk3/AszGcJ3f8wQLZU0HObrTQmnHNK4yZc2AreJ1CRfBsDMRJSUjQJib+ta
    60  3RGNKJpchJAQeg29dGYvajig4tVUROsdB58Hum/u6f1OCyn1PoSgAfGcq/gcfomk
    61  6KHYcWUNo1F77rzSImANuVud37r8UVsLr5iy6S7pBOhih94ryNdOwUxkHt3Ph1i6
    62  Sk/KaAcdHJ1KxtUvkcx8cXIcxcBn6zL9yZJclNqFwJu/U30rCfSMnZEfl2pSy94J
    63  NqR32HuHUETVPm4pafs5SSYeCaWAe0At6+gnhcn+Yf1+5nyXHdWdAgMBAAGjQjBA
    64  MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBR7W0XP
    65  r87Lev0xkhpqtvNG61dIUDANBgkqhkiG9w0BAQUFAAOCAQEAeRHAS7ORtvzw6WfU
    66  DW5FvlXok9LOAz/t2iWwHVfLHjp2oEzsUHboZHIMpKnxuIvW1oeEuzLlQRHAd9mz
    67  YJ3rG9XRbkREqaYB7FViHXe4XI5ISXycO1cRrK1zN44veFyQaEfZYGDm/Ac9IiAX
    68  xPcW6cTYcvnIc3zfFi8VqT79aie2oetaupgf1eNNZAqdE8hhuvU5HIe6uL17In/2
    69  /qxAeeWsEG89jxt5dovEN7MhGITlNgDrYyCZuen+MwS7QcjBAvlEYyCegc5C09Y/
    70  LHbTY5xZ3Y+m4Q6gLkH3LpVHz7z9M/P2C2F+fpErgUfCJzDupxBdN49cOSvkBPB7
    71  jVaMaA==
    72  -----END CERTIFICATE-----
    73  `
    74  
    75  func (s *certsSuite) TestConfigureCertsHappy(c *C) {
    76  	err := configcore.Run(&mockConf{
    77  		state: s.state,
    78  		changes: map[string]interface{}{
    79  			"store-certs.cert1": mockCert,
    80  		},
    81  	})
    82  	c.Assert(err, IsNil)
    83  	c.Assert(filepath.Join(dirs.SnapdStoreSSLCertsDir, "cert1.pem"), testutil.FileEquals, mockCert)
    84  }
    85  
    86  func (s *certsSuite) TestConfigureCertsSimulteRevert(c *C) {
    87  	// do a normal "snap set"
    88  	err := configcore.Run(&mockConf{
    89  		state: s.state,
    90  		changes: map[string]interface{}{
    91  			"store-certs.cert1": mockCert,
    92  		},
    93  	})
    94  	c.Assert(err, IsNil)
    95  	c.Assert(filepath.Join(dirs.SnapdStoreSSLCertsDir, "cert1.pem"), testutil.FilePresent)
    96  	// and one more with a new cert that will be reverted
    97  	err = configcore.Run(&mockConf{
    98  		state: s.state,
    99  		conf: map[string]interface{}{
   100  			"store-certs.cert1": mockCert,
   101  		},
   102  		changes: map[string]interface{}{
   103  			"store-certs.certthatwillbereverted": mockCert,
   104  		},
   105  	})
   106  	c.Assert(err, IsNil)
   107  	c.Assert(filepath.Join(dirs.SnapdStoreSSLCertsDir, "cert1.pem"), testutil.FilePresent)
   108  	c.Assert(filepath.Join(dirs.SnapdStoreSSLCertsDir, "certthatwillbereverted.pem"), testutil.FilePresent)
   109  
   110  	// now simulate a "snap revert core" where "cert1" will stay in
   111  	// the state but "cert-that-will-be-reverted" is part of the config
   112  	// of the reverted core
   113  	err = configcore.Run(&mockConf{
   114  		state: s.state,
   115  		conf: map[string]interface{}{
   116  			"store-certs.cert1": mockCert,
   117  		},
   118  	})
   119  	c.Assert(err, IsNil)
   120  	c.Assert(filepath.Join(dirs.SnapdStoreSSLCertsDir, "cert1.pem"), testutil.FilePresent)
   121  	c.Assert(filepath.Join(dirs.SnapdStoreSSLCertsDir, "certthatwillbereverted.pem"), testutil.FileAbsent)
   122  }
   123  
   124  var certThatFailsToParse = `-----BEGIN CERTIFICATE-----
   125  jVaMaA==
   126  -----END CERTIFICATE-----
   127  `
   128  
   129  func (s *certsSuite) TestConfigureCertsFailsToParse(c *C) {
   130  	err := configcore.Run(&mockConf{
   131  		state: s.state,
   132  		changes: map[string]interface{}{
   133  			"store-certs.cert1": certThatFailsToParse,
   134  		},
   135  	})
   136  	c.Assert(err, ErrorMatches, `cannot decode pem certificate "cert1"`)
   137  }
   138  
   139  func (s *certsSuite) TestConfigureCertsUnhappyContent(c *C) {
   140  	err := configcore.Run(&mockConf{
   141  		state: s.state,
   142  		changes: map[string]interface{}{
   143  			"store-certs.cert-bad": "xxx",
   144  		},
   145  	})
   146  	c.Assert(err, ErrorMatches, `cannot decode pem certificate "cert-bad"`)
   147  }