github.com/pf-qiu/concourse/v6@v6.7.3-0.20201207032516-1f455d73275f/atc/creds/vault/manager_test.go (about) 1 package vault_test 2 3 import ( 4 "crypto/tls" 5 "encoding/json" 6 "net" 7 "net/http" 8 "net/http/httptest" 9 "time" 10 11 "code.cloudfoundry.org/lager/lagertest" 12 "github.com/pf-qiu/concourse/v6/atc/creds/vault" 13 "github.com/hashicorp/vault/api" 14 "github.com/jessevdk/go-flags" 15 "github.com/square/certstrap/pkix" 16 17 . "github.com/onsi/ginkgo" 18 . "github.com/onsi/ginkgo/extensions/table" 19 . "github.com/onsi/gomega" 20 ) 21 22 var _ = Describe("VaultManager", func() { 23 var manager vault.VaultManager 24 25 Describe("IsConfigured()", func() { 26 JustBeforeEach(func() { 27 _, err := flags.ParseArgs(&manager, []string{}) 28 Expect(err).To(BeNil()) 29 }) 30 31 It("fails on empty Manager", func() { 32 Expect(manager.IsConfigured()).To(BeFalse()) 33 }) 34 35 It("passes if URL is set", func() { 36 manager.URL = "http://vault" 37 Expect(manager.IsConfigured()).To(BeTrue()) 38 }) 39 }) 40 41 Describe("Validate()", func() { 42 JustBeforeEach(func() { 43 manager = vault.VaultManager{URL: "http://vault", Auth: vault.AuthConfig{ClientToken: "xxx"}} 44 _, err := flags.ParseArgs(&manager, []string{}) 45 Expect(err).To(BeNil()) 46 Expect(manager.SharedPath).To(Equal("")) 47 Expect(manager.PathPrefix).To(Equal("/concourse")) 48 Expect(manager.LookupTemplates).To(Equal([]string{ 49 "/{{.Team}}/{{.Pipeline}}/{{.Secret}}", 50 "/{{.Team}}/{{.Secret}}", 51 })) 52 Expect(manager.Namespace).To(Equal("")) 53 }) 54 55 It("passes on default parameters", func() { 56 Expect(manager.Validate()).To(BeNil()) 57 }) 58 59 DescribeTable("passes if all vault credentials are specified", 60 func(backend, clientToken string) { 61 manager.Auth.Backend = backend 62 manager.Auth.ClientToken = clientToken 63 Expect(manager.Validate()).To(BeNil()) 64 }, 65 Entry("all values", "backend", "clientToken"), 66 Entry("only clientToken", "", "clientToken"), 67 ) 68 69 It("fails on missing vault auth credentials", func() { 70 manager.Auth = vault.AuthConfig{} 71 Expect(manager.Validate()).ToNot(BeNil()) 72 }) 73 }) 74 75 Describe("Config", func() { 76 var config map[string]interface{} 77 var fakeVault *httptest.Server 78 79 var configErr error 80 81 BeforeEach(func() { 82 key, err := pkix.CreateRSAKey(1024) 83 Expect(err).ToNot(HaveOccurred()) 84 85 ca, err := pkix.CreateCertificateAuthority(key, "", time.Now().Add(time.Hour), "", "", "", "", "vault-ca") 86 Expect(err).ToNot(HaveOccurred()) 87 88 serverKey, err := pkix.CreateRSAKey(1024) 89 Expect(err).ToNot(HaveOccurred()) 90 91 serverKeyBytes, err := serverKey.ExportPrivate() 92 Expect(err).ToNot(HaveOccurred()) 93 94 serverName := "vault" 95 96 serverCSR, err := pkix.CreateCertificateSigningRequest(serverKey, "", []net.IP{net.ParseIP("127.0.0.1")}, []string{serverName}, "", "", "", "", "") 97 Expect(err).ToNot(HaveOccurred()) 98 99 serverCert, err := pkix.CreateCertificateHost(ca, key, serverCSR, time.Now().Add(time.Hour)) 100 Expect(err).ToNot(HaveOccurred()) 101 102 clientKey, err := pkix.CreateRSAKey(1024) 103 Expect(err).ToNot(HaveOccurred()) 104 105 clientKeyBytes, err := clientKey.ExportPrivate() 106 Expect(err).ToNot(HaveOccurred()) 107 108 clientCSR, err := pkix.CreateCertificateSigningRequest(clientKey, "", nil, nil, "", "", "", "", "concourse") 109 Expect(err).ToNot(HaveOccurred()) 110 111 clientCert, err := pkix.CreateCertificateHost(ca, key, clientCSR, time.Now().Add(time.Hour)) 112 Expect(err).ToNot(HaveOccurred()) 113 114 serverCertBytes, err := serverCert.Export() 115 Expect(err).ToNot(HaveOccurred()) 116 117 clientCertBytes, err := clientCert.Export() 118 Expect(err).ToNot(HaveOccurred()) 119 120 caBytes, err := ca.Export() 121 Expect(err).ToNot(HaveOccurred()) 122 123 fakeVault = httptest.NewUnstartedServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 124 err := json.NewEncoder(w).Encode(api.Secret{ 125 Data: map[string]interface{}{"value": "foo"}, 126 }) 127 Expect(err).ToNot(HaveOccurred()) 128 })) 129 130 tlsCert, err := tls.X509KeyPair(serverCertBytes, serverKeyBytes) 131 Expect(err).ToNot(HaveOccurred()) 132 133 fakeVault.TLS = &tls.Config{ 134 Certificates: []tls.Certificate{tlsCert}, 135 } 136 137 fakeVault.StartTLS() 138 139 config = map[string]interface{}{ 140 "url": fakeVault.URL, 141 "path_prefix": "/path-prefix", 142 "lookup_templates": []string{ 143 "/what/{{.Team}}/blah/{{.Pipeline}}/{{.Secret}}", 144 "/thing/{{.Team}}/{{.Secret}}", 145 }, 146 "shared_path": "/shared-path", 147 "namespace": "some-namespace", 148 "ca_cert": string(caBytes), 149 "client_cert": string(clientCertBytes), 150 "client_key": string(clientKeyBytes), 151 "server_name": serverName, 152 "insecure_skip_verify": true, 153 "client_token": "some-client-token", 154 "auth_backend_max_ttl": "5m", 155 "auth_retry_max": "15m", 156 "auth_retry_initial": "10s", 157 "auth_backend": "approle", 158 "auth_params": map[string]string{ 159 "role_id": "some-role-id", 160 "secret_id": "some-secret-id", 161 }, 162 } 163 164 manager = vault.VaultManager{} 165 }) 166 167 JustBeforeEach(func() { 168 configErr = manager.Config(config) 169 }) 170 171 It("configures TLS appropriately", func() { 172 Expect(configErr).ToNot(HaveOccurred()) 173 174 err := manager.Init(lagertest.NewTestLogger("test")) 175 Expect(err).ToNot(HaveOccurred()) 176 177 secret, err := manager.Client.Read("some/path") 178 Expect(err).ToNot(HaveOccurred()) 179 Expect(secret).ToNot(BeNil()) 180 Expect(secret.Data).To(Equal(map[string]interface{}{"value": "foo"})) 181 }) 182 183 It("configures all attributes appropriately", func() { 184 Expect(configErr).ToNot(HaveOccurred()) 185 186 Expect(manager.URL).To(Equal(fakeVault.URL)) 187 Expect(manager.PathPrefix).To(Equal("/path-prefix")) 188 Expect(manager.LookupTemplates).To(Equal([]string{ 189 "/what/{{.Team}}/blah/{{.Pipeline}}/{{.Secret}}", 190 "/thing/{{.Team}}/{{.Secret}}", 191 })) 192 Expect(manager.SharedPath).To(Equal("/shared-path")) 193 Expect(manager.Namespace).To(Equal("some-namespace")) 194 195 Expect(manager.TLS.Insecure).To(BeTrue()) 196 197 Expect(manager.Auth.ClientToken).To(Equal("some-client-token")) 198 Expect(manager.Auth.BackendMaxTTL).To(Equal(5 * time.Minute)) 199 Expect(manager.Auth.RetryMax).To(Equal(15 * time.Minute)) 200 Expect(manager.Auth.RetryInitial).To(Equal(10 * time.Second)) 201 Expect(manager.Auth.Backend).To(Equal("approle")) 202 Expect(manager.Auth.Params).To(Equal(map[string]string{ 203 "role_id": "some-role-id", 204 "secret_id": "some-secret-id", 205 })) 206 }) 207 208 Context("with optional configs omitted", func() { 209 BeforeEach(func() { 210 delete(config, "path_prefix") 211 delete(config, "auth_retry_max") 212 delete(config, "auth_retry_initial") 213 delete(config, "lookup_templates") 214 }) 215 216 It("has sane defaults", func() { 217 Expect(configErr).ToNot(HaveOccurred()) 218 219 Expect(manager.PathPrefix).To(Equal("/concourse")) 220 Expect(manager.Auth.RetryMax).To(Equal(5 * time.Minute)) 221 Expect(manager.Auth.RetryInitial).To(Equal(time.Second)) 222 Expect(manager.LookupTemplates).To(Equal([]string{ 223 "/{{.Team}}/{{.Pipeline}}/{{.Secret}}", 224 "/{{.Team}}/{{.Secret}}", 225 })) 226 }) 227 }) 228 229 Context("with extra keys in the config", func() { 230 BeforeEach(func() { 231 config["unknown_key"] = "whambam" 232 }) 233 234 It("returns an error", func() { 235 Expect(configErr).To(HaveOccurred()) 236 Expect(configErr.Error()).To(ContainSubstring("unknown_key")) 237 }) 238 }) 239 }) 240 })