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