1use std::process::ExitCode;
4
5use nethsm::{KeyId, NetHsm};
6use nethsm_config::UserMapping;
7use signstar_config::{CredentialsLoading, Error as ConfigError};
8use signstar_request_signature::{Request, Response, Sha512};
9
10#[derive(Debug, thiserror::Error)]
12enum Error {
13 #[error("No key ID set for the operator user")]
15 NoKeyId,
16
17 #[error("Loading credentials encountered errors")]
19 HasUserIdErrors,
20
21 #[error("No credentials for the system user")]
23 NoCredentials,
24
25 #[error("Unsupported signing request parameters")]
27 UnsupportedParameters,
28
29 #[error("Config error")]
31 Config(#[from] ConfigError),
32
33 #[error("NetHsm error")]
35 NetHsm(#[from] nethsm::Error),
36
37 #[error("Signing request error")]
39 SigningRequest(#[from] signstar_request_signature::Error),
40}
41
42fn load_nethsm_keyid() -> Result<(NetHsm, KeyId), Error> {
53 let credentials_loading = CredentialsLoading::from_system_user()?;
54
55 if credentials_loading.has_userid_errors() {
56 return Err(Error::HasUserIdErrors);
57 }
58
59 if !credentials_loading.has_signing_user() {
60 return Err(Error::NoCredentials);
61 }
62
63 let key_id = if let UserMapping::SystemNetHsmOperatorSigning {
64 nethsm_key_setup, ..
65 } = credentials_loading.get_mapping().get_user_mapping()
66 {
67 nethsm_key_setup.get_key_id().clone()
68 } else {
69 return Err(Error::NoKeyId);
70 };
71
72 let connection = if let Some(connection) = credentials_loading
76 .get_mapping()
77 .get_connections()
78 .iter()
79 .next()
80 {
81 connection.clone()
82 } else {
83 return Err(Error::NoCredentials);
84 };
85
86 let credentials = credentials_loading.credentials_for_signing_user()?;
87
88 Ok((
89 NetHsm::new(connection, Some(credentials.into()), None, None)?,
90 key_id,
91 ))
92}
93
94fn sign_request(reader: impl std::io::Read, writer: impl std::io::Write) -> Result<(), Error> {
108 let req = Request::from_reader(reader)?;
109
110 if !req.required.output.is_openpgp_v4() {
111 Err(Error::UnsupportedParameters)?;
112 }
113
114 if req.version.major != 1 {
115 Err(Error::UnsupportedParameters)?;
116 }
117
118 let hasher: Sha512 = req.required.input.try_into()?;
119
120 let (nethsm, key_id) = load_nethsm_keyid()?;
121
122 let signature = nethsm.openpgp_sign_state(&key_id, hasher)?;
123
124 Response::v1(signature).to_writer(writer)?;
125
126 Ok(())
127}
128
129fn main() -> ExitCode {
131 let result = sign_request(std::io::stdin(), std::io::stdout());
132
133 if let Err(error) = result {
134 eprintln!("{error}");
135 ExitCode::FAILURE
136 } else {
137 ExitCode::SUCCESS
138 }
139}