-
Notifications
You must be signed in to change notification settings - Fork 51
/
client_builder.rs
144 lines (132 loc) · 5.28 KB
/
client_builder.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
//
// Copyright 2022 The Sigstore Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
use rustls_pki_types::CertificateDer;
use tracing::info;
use super::client::Client;
use crate::crypto::SigningScheme;
use crate::crypto::{certificate_pool::CertificatePool, CosignVerificationKey};
use crate::errors::Result;
use crate::registry::ClientConfig;
use crate::tuf::Repository;
/// A builder that generates Client objects.
///
/// ## Rekor integration
///
/// Rekor integration can be enabled by specifying Rekor's public key.
/// This can be provided via the [`ClientBuilder::with_rekor_pub_key`] method.
///
/// > Note well: the [`tuf`](crate::tuf) module provides helper structs and methods
/// > to obtain this data from the official TUF repository of the Sigstore project.
///
/// ## Fulcio integration
///
/// Fulcio integration can be enabled by specifying Fulcio's certificate.
/// This can be provided via the [`ClientBuilder::with_fulcio_certs`] method.
///
/// > Note well: the [`tuf`](crate::tuf) module provides helper structs and methods
/// > to obtain this data from the official TUF repository of the Sigstore project.
///
/// ## Registry caching
///
/// The [`cosign::Client`](crate::cosign::Client) interacts with remote container registries to obtain
/// the data needed to perform Sigstore verification.
///
/// By default, the client will always reach out to the remote registry. However,
/// it's possible to enable an in-memory cache. This behaviour can be enabled via
/// the [`ClientBuilder::enable_registry_caching`] method.
///
/// Each cached entry will automatically expire after 60 seconds.
#[derive(Default)]
pub struct ClientBuilder<'a> {
oci_client_config: ClientConfig,
rekor_pub_key: Option<&'a [u8]>,
fulcio_certs: Vec<CertificateDer<'a>>,
// repo: Repository
#[cfg(feature = "cached-client")]
enable_registry_caching: bool,
}
impl<'a> ClientBuilder<'a> {
/// Enable caching of data returned from remote OCI registries
#[cfg(feature = "cached-client")]
pub fn enable_registry_caching(mut self) -> Self {
self.enable_registry_caching = true;
self
}
/// Optional - Configures the roots of trust.
///
/// Enables Fulcio and Rekor integration with the given trust repository.
/// See [crate::tuf::Repository] for more details on trust repositories.
pub fn with_trust_repository<R: Repository + ?Sized>(mut self, repo: &'a R) -> Result<Self> {
let rekor_keys = repo.rekor_keys()?;
if !rekor_keys.is_empty() {
self.rekor_pub_key = Some(rekor_keys[0]);
}
self.fulcio_certs = repo.fulcio_certs()?;
Ok(self)
}
/// Optional - the configuration to be used by the OCI client.
///
/// This can be used when dealing with registries that are not using
/// TLS termination, or are using self-signed certificates.
pub fn with_oci_client_config(mut self, config: ClientConfig) -> Self {
self.oci_client_config = config;
self
}
pub fn build(self) -> Result<Client<'a>> {
let rekor_pub_key = match self.rekor_pub_key {
None => {
info!("Rekor public key not provided. Rekor integration disabled");
None
}
Some(data) => Some(CosignVerificationKey::from_der(
data,
&SigningScheme::default(),
)?),
};
let fulcio_cert_pool = if self.fulcio_certs.is_empty() {
info!("No Fulcio cert has been provided. Fulcio integration disabled");
None
} else {
let cert_pool = CertificatePool::from_certificates(self.fulcio_certs, [])?;
Some(cert_pool)
};
let oci_client =
oci_distribution::client::Client::new(self.oci_client_config.clone().into());
let registry_client: Box<dyn crate::registry::ClientCapabilities> = {
cfg_if::cfg_if! {
if #[cfg(feature = "cached-client")] {
if self.enable_registry_caching {
Box::new(crate::registry::OciCachingClient {
registry_client: oci_client,
}) as Box<dyn crate::registry::ClientCapabilities>
} else {
Box::new(crate::registry::OciClient {
registry_client: oci_client,
}) as Box<dyn crate::registry::ClientCapabilities>
}
} else {
Box::new(crate::registry::OciClient {
registry_client: oci_client,
}) as Box<dyn crate::registry::ClientCapabilities>
}
}
};
Ok(Client {
registry_client,
rekor_pub_key,
fulcio_cert_pool,
})
}
}