1// Copyright 2018 Istio Authors 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 15// Package vault provides adapter to connect to vault server. 16package vault 17 18import ( 19 "fmt" 20 "time" 21 22 "istio.io/istio/security/pkg/pki/util" 23) 24 25/* 26// Config for prototyping purpose 27const ( 28 istioCaMountPoint = "istio_ca" 29 istioCaDescription = "Istio CA" 30 configCaKeyCertPath = "istio_ca/config/ca" 31 workloadRolePath = "istio_ca/roles/workload_role" 32 signCsrPath = "istio_ca/sign-verbatim" 33) 34 35// Config for prototyping purpose 36// TODO (lei-tang): move the these config to ca_test.go 37const ( 38 vaultAddrForTesting = "http://127.0.0.1:8200" 39 tokenForTesting = "myroot" 40 testCAKeyCertFile = "testdata/istio_ca.pem" 41 testCsrFile = "testdata/workload-1.csr" 42) 43*/ 44 45// CA connects to Vault to sign certificates. 46type CA struct { 47} 48 49// Sign takes a PEM-encoded CSR and returns a signed certificate. If the CA is a multicluster CA, 50// the signed certificate is a CA certificate (CA:TRUE in X509v3 Basic Constraints), otherwise, it is a workload 51// certificate. 52func (v *CA) Sign(csrPEM []byte, ttl time.Duration) ([]byte, error) { 53 return nil, fmt.Errorf("not implemented") 54} 55 56// SignCAServerCert signs the certificate for the Istio CA server (to serve the CSR, etc). 57func (v *CA) SignCAServerCert(csrPEM []byte, ttl time.Duration) ([]byte, error) { 58 return nil, fmt.Errorf("not implemented") 59} 60 61// GetKeyCertBundle returns the KeyCertBundle for the CA. 62func (v *CA) GetKeyCertBundle() util.KeyCertBundle { 63 return nil 64} 65 66/* 67// Get the connection to a Vault server and set the token for the connection. 68// vaultAddr: the address of the Vault server (e.g., "http://127.0.0.1:8200"). 69// token: used for authentication. 70func getVaultConnection(vaultAddr string, token string) (*api.Client, error) { 71 config := api.DefaultConfig() 72 config.Address = vaultAddr 73 74 client, err := api.NewClient(config) 75 if err != nil { 76 log.Errorf("NewClient() failed (error %v)", err) 77 return nil, err 78 } 79 80 //Simply sets the token for future requests without actual authentication 81 client.SetToken(token) 82 return client, nil 83} 84 85// Mount the Vault PKI. 86// caMountPoint: the mount point for CA (e.g., "istio_ca") 87// caDescription: a description for CA (e.g., "Istio CA") 88func mountVaultPki(client *api.Client, caMountPoint string, caDescription string) error { 89 var mountInput api.MountInput 90 mountInput.Description = caDescription 91 mountInput.Type = "pki" 92 err := client.Sys().Mount(caMountPoint, &mountInput) 93 if err != nil { 94 log.Errorf("Mount() failed (error %v)", err) 95 return err 96 } 97 return nil 98} 99 100// Set the workload role that issues certs with the given max-TTL and number of key bits. 101// rolePath: the path to the workload role (e.g., "istio_ca/roles/workload_role") 102// maxTtl: the max life time of a workload cert (e.g., "1h") 103// keyBits: the number of bits for the key of a workload cert (e.g., 2048) 104func setWorkloadRole(client *api.Client, rolePath string, maxTTL string, keyBits int) error { 105 m := map[string]interface{}{ 106 "max_ttl": maxTTL, 107 "key_bits": keyBits, 108 "enforce_hostnames": false, 109 "allow_any_name": true, 110 } 111 112 _, err := client.Logical().Write(rolePath, m) 113 if err != nil { 114 log.Errorf("Write() failed (error %v)", err) 115 return err 116 } 117 return nil 118} 119 120// Set the certificate and the private key of the CA. 121// caConfigPath: the path for configuring the CA (e.g., "istio_ca/config/ca") 122// keyCert: the private key and the public certificate of the CA 123func setCaKeyCert(client *api.Client, caConfigPath string, keyCert string) (*api.Secret, error) { 124 m := map[string]interface{}{ 125 "pem_bundle": keyCert, 126 } 127 128 res, err := client.Logical().Write(caConfigPath, m) 129 if err != nil { 130 log.Errorf("Write() failed (error %v)", err) 131 return nil, err 132 } 133 return res, nil 134} 135 136// Sign a CSR and return the signed certificate. 137// csrPath: the path for signing a CSR (e.g., "istio_ca/sign-verbatim") 138// csr: the CSR to be signed 139func signCsr(client *api.Client, csrPath string, csr string) (*api.Secret, error) { 140 m := map[string]interface{}{ 141 "name": "workload_role", 142 "format": "pem", 143 "use_csr_common_name": true, 144 "csr": csr, 145 } 146 147 res, err := client.Logical().Write(csrPath, m) 148 if err != nil { 149 log.Errorf("Write() failed (error %v)", err) 150 return nil, err 151 } 152 return res, nil 153} 154 155//RunProtoTypeSignCsrFlow runs a prototyping signCsr flow, includes: 156//- Create a connection to Vault 157//- Mount Vault PKI 158//- Set CA signing key and cert 159//- Set workload role for issuing certificates 160//- Sign CSR and print the certificate signed 161func RunProtoTypeSignCsrFlow() error { 162 client, err := getVaultConnection(vaultAddrForTesting, tokenForTesting) 163 if err != nil { 164 log.Errorf("getVaultConnection() failed (error %v)", err) 165 return err 166 } 167 168 err = mountVaultPki(client, istioCaMountPoint, istioCaDescription) 169 if err != nil { 170 log.Errorf("mountVaultPki() failed (error %v)", err) 171 return err 172 } 173 174 keyCert, err := ioutil.ReadFile(testCAKeyCertFile) 175 if err != nil { 176 log.Errorf("ReadFile() failed (error %v)", err) 177 return err 178 } 179 _, err = setCaKeyCert(client, configCaKeyCertPath, string(keyCert)) 180 if err != nil { 181 log.Errorf("setCaKeyCert() failed (error %v)", err) 182 return err 183 } 184 185 err = setWorkloadRole(client, workloadRolePath, "1h", 2048) 186 if err != nil { 187 log.Errorf("setWorkloadRole() failed (error %v)", err) 188 return err 189 } 190 191 testCsr, err := ioutil.ReadFile(testCsrFile) 192 if err != nil { 193 log.Errorf("ReadFile() failed (error %v)", err) 194 return err 195 } 196 res, err := signCsr(client, signCsrPath, string(testCsr)) 197 if err != nil { 198 log.Errorf("signCsr() failed (error %v)", err) 199 return err 200 } 201 log.Info("The certificate generated from CSR is :") 202 //Print the certificate 203 log.Infof("%v", res.Data["certificate"]) 204 return nil 205} 206*/ 207