1/*
2Copyright (c) 2016 VMware, Inc. All Rights Reserved.
3
4Licensed under the Apache License, Version 2.0 (the "License");
5you may not use this file except in compliance with the License.
6You may obtain a copy of the License at
7
8    http://www.apache.org/licenses/LICENSE-2.0
9
10Unless required by applicable law or agreed to in writing, software
11distributed under the License is distributed on an "AS IS" BASIS,
12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13See the License for the specific language governing permissions and
14limitations under the License.
15*/
16
17package object
18
19import (
20	"context"
21
22	"github.com/vmware/govmomi/property"
23	"github.com/vmware/govmomi/vim25"
24	"github.com/vmware/govmomi/vim25/methods"
25	"github.com/vmware/govmomi/vim25/mo"
26	"github.com/vmware/govmomi/vim25/types"
27)
28
29// HostCertificateManager provides helper methods around the HostSystem.ConfigManager.CertificateManager
30type HostCertificateManager struct {
31	Common
32	Host *HostSystem
33}
34
35// NewHostCertificateManager creates a new HostCertificateManager helper
36func NewHostCertificateManager(c *vim25.Client, ref types.ManagedObjectReference, host types.ManagedObjectReference) *HostCertificateManager {
37	return &HostCertificateManager{
38		Common: NewCommon(c, ref),
39		Host:   NewHostSystem(c, host),
40	}
41}
42
43// CertificateInfo wraps the host CertificateManager certificateInfo property with the HostCertificateInfo helper.
44// The ThumbprintSHA1 field is set to HostSystem.Summary.Config.SslThumbprint if the host system is managed by a vCenter.
45func (m HostCertificateManager) CertificateInfo(ctx context.Context) (*HostCertificateInfo, error) {
46	var hs mo.HostSystem
47	var cm mo.HostCertificateManager
48
49	pc := property.DefaultCollector(m.Client())
50
51	err := pc.RetrieveOne(ctx, m.Reference(), []string{"certificateInfo"}, &cm)
52	if err != nil {
53		return nil, err
54	}
55
56	_ = pc.RetrieveOne(ctx, m.Host.Reference(), []string{"summary.config.sslThumbprint"}, &hs)
57
58	return &HostCertificateInfo{
59		HostCertificateManagerCertificateInfo: cm.CertificateInfo,
60		ThumbprintSHA1:                        hs.Summary.Config.SslThumbprint,
61	}, nil
62}
63
64// GenerateCertificateSigningRequest requests the host system to generate a certificate-signing request (CSR) for itself.
65// The CSR is then typically provided to a Certificate Authority to sign and issue the SSL certificate for the host system.
66// Use InstallServerCertificate to import this certificate.
67func (m HostCertificateManager) GenerateCertificateSigningRequest(ctx context.Context, useIPAddressAsCommonName bool) (string, error) {
68	req := types.GenerateCertificateSigningRequest{
69		This: m.Reference(),
70		UseIpAddressAsCommonName: useIPAddressAsCommonName,
71	}
72
73	res, err := methods.GenerateCertificateSigningRequest(ctx, m.Client(), &req)
74	if err != nil {
75		return "", err
76	}
77
78	return res.Returnval, nil
79}
80
81// GenerateCertificateSigningRequestByDn requests the host system to generate a certificate-signing request (CSR) for itself.
82// Alternative version similar to GenerateCertificateSigningRequest but takes a Distinguished Name (DN) as a parameter.
83func (m HostCertificateManager) GenerateCertificateSigningRequestByDn(ctx context.Context, distinguishedName string) (string, error) {
84	req := types.GenerateCertificateSigningRequestByDn{
85		This:              m.Reference(),
86		DistinguishedName: distinguishedName,
87	}
88
89	res, err := methods.GenerateCertificateSigningRequestByDn(ctx, m.Client(), &req)
90	if err != nil {
91		return "", err
92	}
93
94	return res.Returnval, nil
95}
96
97// InstallServerCertificate imports the given SSL certificate to the host system.
98func (m HostCertificateManager) InstallServerCertificate(ctx context.Context, cert string) error {
99	req := types.InstallServerCertificate{
100		This: m.Reference(),
101		Cert: cert,
102	}
103
104	_, err := methods.InstallServerCertificate(ctx, m.Client(), &req)
105	if err != nil {
106		return err
107	}
108
109	// NotifyAffectedService is internal, not exposing as we don't have a use case other than with InstallServerCertificate
110	// Without this call, hostd needs to be restarted to use the updated certificate
111	// Note: using Refresh as it has the same struct/signature, we just need to use different xml name tags
112	body := struct {
113		Req *types.Refresh         `xml:"urn:vim25 NotifyAffectedServices,omitempty"`
114		Res *types.RefreshResponse `xml:"urn:vim25 NotifyAffectedServicesResponse,omitempty"`
115		methods.RefreshBody
116	}{
117		Req: &types.Refresh{This: m.Reference()},
118	}
119
120	return m.Client().RoundTrip(ctx, &body, &body)
121}
122
123// ListCACertificateRevocationLists returns the SSL CRLs of Certificate Authorities that are trusted by the host system.
124func (m HostCertificateManager) ListCACertificateRevocationLists(ctx context.Context) ([]string, error) {
125	req := types.ListCACertificateRevocationLists{
126		This: m.Reference(),
127	}
128
129	res, err := methods.ListCACertificateRevocationLists(ctx, m.Client(), &req)
130	if err != nil {
131		return nil, err
132	}
133
134	return res.Returnval, nil
135}
136
137// ListCACertificates returns the SSL certificates of Certificate Authorities that are trusted by the host system.
138func (m HostCertificateManager) ListCACertificates(ctx context.Context) ([]string, error) {
139	req := types.ListCACertificates{
140		This: m.Reference(),
141	}
142
143	res, err := methods.ListCACertificates(ctx, m.Client(), &req)
144	if err != nil {
145		return nil, err
146	}
147
148	return res.Returnval, nil
149}
150
151// ReplaceCACertificatesAndCRLs replaces the trusted CA certificates and CRL used by the host system.
152// These determine whether the server can verify the identity of an external entity.
153func (m HostCertificateManager) ReplaceCACertificatesAndCRLs(ctx context.Context, caCert []string, caCrl []string) error {
154	req := types.ReplaceCACertificatesAndCRLs{
155		This:   m.Reference(),
156		CaCert: caCert,
157		CaCrl:  caCrl,
158	}
159
160	_, err := methods.ReplaceCACertificatesAndCRLs(ctx, m.Client(), &req)
161	return err
162}
163