1
0
Fork 0
mirror of https://codeberg.org/icewind/haze.git synced 2026-08-02 12:14:46 +02:00

add sftp with key authentication service

This commit is contained in:
Robin Appelman 2026-05-26 20:45:29 +02:00
commit 204fb676d6
19 changed files with 348 additions and 135 deletions

View file

@ -633,12 +633,7 @@ async fn setup(docker: &Docker, options: CloudOptions, config: &HazeConfig) -> R
for service in cloud.services() {
for cmd in service.post_setup(docker, &cloud.id, config).await? {
cloud
.exec(
docker,
shell_words::split(&cmd).into_diagnostic()?,
false,
Vec::<String>::default(),
)
.exec(docker, cmd, false, Vec::<String>::default())
.await?;
}
}

View file

@ -30,7 +30,7 @@ pub use crate::service::office::Office;
pub use crate::service::onlyoffice::OnlyOffice;
pub use crate::service::push::NotifyPush;
use crate::service::redis::Redis;
use crate::service::sftp::Sftp;
use crate::service::sftp::{Sftp, SftpKey};
use crate::service::sharded::{Sharding, ShardingMigrate, ShardingMigrateUnset, SingleShard};
use crate::service::smb::Smb;
use crate::service::webhook::Webhook;
@ -116,7 +116,7 @@ pub trait ServiceTrait {
_docker: &Docker,
_cloud_id: &str,
_config: &HazeConfig,
) -> Result<Vec<String>> {
) -> Result<Vec<Vec<String>>> {
Ok(Vec::new())
}
@ -267,6 +267,8 @@ pub enum ServiceType {
Dav,
/// Sftp external storage
Sftp,
/// Sftp external storage with public key authentication
SftpKey,
/// ownCloud instance for migration
Oc,
/// Imaginary for preview generation
@ -318,6 +320,7 @@ pub enum Service {
ShardingMigrate(ShardingMigrate),
ShardingMigrateUnset(ShardingMigrateUnset),
Sftp(Sftp),
SftpKey(SftpKey),
Kaspersky(Kaspersky),
KasperskyIcap(KasperskyIcap),
Clam(Clam),
@ -361,6 +364,7 @@ impl Service {
}
ServiceType::Dav => Some(vec![Service::Dav(Dav)]),
ServiceType::Sftp => Some(vec![Service::Sftp(Sftp)]),
ServiceType::SftpKey => Some(vec![Service::SftpKey(SftpKey)]),
ServiceType::Oc => Some(vec![Service::Oc(Oc)]),
ServiceType::Imaginary => Some(vec![Service::Imaginary(Imaginary)]),
ServiceType::Kaspersky => Some(vec![Service::Kaspersky(Kaspersky)]),
@ -437,15 +441,29 @@ impl ServiceTrait for PresetService {
_docker: &Docker,
_cloud_id: &str,
config: &HazeConfig,
) -> Result<Vec<String>> {
) -> Result<Vec<Vec<String>>> {
let preset =
get_preset(&config.preset, &self.0).ok_or_else(|| Report::msg("invalid preset"))?;
let mut commands: Vec<_> = preset
.apps
.iter()
.map(|app| format!("occ app:enable {app} --force"))
.map(|app| {
vec![
"occ".into(),
"app:enable".into(),
app.clone(),
"--force".into(),
]
})
.collect();
commands.extend_from_slice(&preset.commands);
for cmnd in &preset.commands {
commands.push(shell_words::split(cmnd).into_diagnostic()?);
}
Ok(commands)
}
}
fn split_cmnd(s: &str) -> Vec<String> {
s.split(' ').map(String::from).collect()
}

View file

@ -2,7 +2,7 @@ use crate::cloud::CloudOptions;
use crate::config::HazeConfig;
use crate::exec::exec;
use crate::image::pull_image;
use crate::service::ServiceTrait;
use crate::service::{split_cmnd, ServiceTrait};
use crate::Result;
use bollard::models::{ContainerCreateBody, EndpointSettings, HostConfig, NetworkingConfig};
use bollard::query_parameters::CreateContainerOptions;
@ -85,14 +85,13 @@ impl ServiceTrait for ClamIcap {
_docker: &Docker,
_cloud_id: &str,
_config: &HazeConfig,
) -> Result<Vec<String>> {
) -> Result<Vec<Vec<String>>> {
Ok(vec![
"occ config:app:set files_antivirus av_mode --value=icap".into(),
"occ config:app:set files_antivirus av_host --value=clamav-icap".into(),
"occ config:app:set files_antivirus av_port --value=1344".into(),
"occ config:app:set files_antivirus av_icap_request_service --value=avscan".into(),
"occ config:app:set files_antivirus av_icap_response_header --value=X-Infection-Found"
.into(),
split_cmnd("occ config:app:set files_antivirus av_mode --value=icap"),
split_cmnd("occ config:app:set files_antivirus av_host --value=clamav-icap"),
split_cmnd("occ config:app:set files_antivirus av_port --value=1344"),
split_cmnd("occ config:app:set files_antivirus av_icap_request_service --value=avscan"),
split_cmnd("occ config:app:set files_antivirus av_icap_response_header --value=X-Infection-Found"),
])
}
}
@ -171,7 +170,7 @@ impl ServiceTrait for ClamIcapTls {
docker: &Docker,
cloud_id: &str,
config: &HazeConfig,
) -> Result<Vec<String>> {
) -> Result<Vec<Vec<String>>> {
let mut cert = Vec::new();
exec(
docker,
@ -191,14 +190,13 @@ impl ServiceTrait for ClamIcapTls {
.wrap_err("Failed to write icap certificate")?;
Ok(vec![
"occ config:app:set files_antivirus av_mode --value=icap".into(),
"occ config:app:set files_antivirus av_icap_tls --value=1".into(),
"occ config:app:set files_antivirus av_host --value=clamav-icap-tls".into(),
"occ config:app:set files_antivirus av_port --value=1345".into(),
"occ config:app:set files_antivirus av_icap_request_service --value=avscan".into(),
"occ config:app:set files_antivirus av_icap_response_header --value=X-Infection-Found"
.into(),
"occ security:certificates:import data/icap-cert.pem".into(),
split_cmnd("occ config:app:set files_antivirus av_mode --value=icap"),
split_cmnd("occ config:app:set files_antivirus av_icap_tls --value=1"),
split_cmnd("occ config:app:set files_antivirus av_host --value=clamav-icap-tls"),
split_cmnd("occ config:app:set files_antivirus av_port --value=1345"),
split_cmnd("occ config:app:set files_antivirus av_icap_request_service --value=avscan"),
split_cmnd("occ config:app:set files_antivirus av_icap_response_header --value=X-Infection-Found"),
split_cmnd("occ security:certificates:import data/icap-cert.pem"),
])
}
}
@ -221,10 +219,10 @@ impl ServiceTrait for Clam {
_docker: &Docker,
_cloud_id: &str,
_config: &HazeConfig,
) -> Result<Vec<String>> {
) -> Result<Vec<Vec<String>>> {
Ok(vec![
"occ config:app:set files_antivirus av_mode --value=executable".into(),
"occ config:app:set files_antivirus av_path --value=/bin/clamscan".into(),
split_cmnd("occ config:app:set files_antivirus av_mode --value=executable"),
split_cmnd("occ config:app:set files_antivirus av_path --value=/bin/clamscan"),
])
}
}
@ -294,10 +292,12 @@ impl ServiceTrait for ClamSocket {
_docker: &Docker,
_cloud_id: &str,
_config: &HazeConfig,
) -> Result<Vec<String>> {
) -> Result<Vec<Vec<String>>> {
Ok(vec![
"occ config:app:set files_antivirus av_mode --value=socket".into(),
"occ config:app:set files_antivirus av_socket --value=tcp://clamav-socket:3310".into(),
split_cmnd("occ config:app:set files_antivirus av_mode --value=socket"),
split_cmnd(
"occ config:app:set files_antivirus av_socket --value=tcp://clamav-socket:3310",
),
])
}
}

View file

@ -1,7 +1,7 @@
use crate::cloud::CloudOptions;
use crate::config::HazeConfig;
use crate::image::pull_image;
use crate::service::ServiceTrait;
use crate::service::{split_cmnd, ServiceTrait};
use crate::Result;
use bollard::config::ContainerCreateBody;
use bollard::models::{EndpointSettings, HostConfig, NetworkingConfig};
@ -76,12 +76,12 @@ impl ServiceTrait for Dav {
_docker: &Docker,
_cloud_id: &str,
_config: &HazeConfig,
) -> Result<Vec<String>> {
) -> Result<Vec<Vec<String>>> {
Ok(vec![
"occ files_external:create dav dav password::password".into(),
"occ files_external:config 1 host dav".into(),
"occ files_external:config 1 user test".into(),
"occ files_external:config 1 password test".into(),
split_cmnd("occ files_external:create dav dav password::password"),
split_cmnd("occ files_external:config 1 host dav"),
split_cmnd("occ files_external:config 1 user test"),
split_cmnd("occ files_external:config 1 password test"),
])
}
}

View file

@ -1,7 +1,7 @@
use crate::cloud::CloudOptions;
use crate::config::HazeConfig;
use crate::image::pull_image;
use crate::service::ServiceTrait;
use crate::service::{split_cmnd, ServiceTrait};
use crate::Result;
use bollard::config::NetworkingConfig;
use bollard::models::{ContainerCreateBody, EndpointSettings, HostConfig};
@ -71,11 +71,14 @@ impl ServiceTrait for Imaginary {
_docker: &Docker,
_cloud_id: &str,
_config: &HazeConfig,
) -> Result<Vec<String>> {
) -> Result<Vec<Vec<String>>> {
Ok(vec![
"occ config:system:set enabledPreviewProviders 0 --value='OC\\Preview\\Imaginary'"
.into(),
"occ config:system:set preview_imaginary_url --value='http://imaginary:9000'".into(),
split_cmnd(
"occ config:system:set enabledPreviewProviders 0 --value='OC\\Preview\\Imaginary'",
),
split_cmnd(
"occ config:system:set preview_imaginary_url --value='http://imaginary:9000'",
),
])
}
}

View file

@ -2,7 +2,7 @@ use crate::cloud::CloudOptions;
use crate::config::HazeConfig;
use crate::exec::exec;
use crate::image::{image_exists, pull_image};
use crate::service::ServiceTrait;
use crate::service::{split_cmnd, ServiceTrait};
use crate::Result;
use bollard::models::{ContainerCreateBody, EndpointSettings, HostConfig, NetworkingConfig};
use bollard::query_parameters::CreateContainerOptions;
@ -101,11 +101,11 @@ impl ServiceTrait for Kaspersky {
_docker: &Docker,
_cloud_id: &str,
_config: &HazeConfig,
) -> Result<Vec<String>> {
) -> Result<Vec<Vec<String>>> {
Ok(vec![
"occ config:app:set files_antivirus av_mode --value=kaspersky".into(),
"occ config:app:set files_antivirus av_host --value=kaspersky".into(),
"occ config:app:set files_antivirus av_port --value=80".into(),
split_cmnd("occ config:app:set files_antivirus av_mode --value=kaspersky"),
split_cmnd("occ config:app:set files_antivirus av_host --value=kaspersky"),
split_cmnd("occ config:app:set files_antivirus av_port --value=80"),
])
}
}
@ -187,13 +187,15 @@ impl ServiceTrait for KasperskyIcap {
_docker: &Docker,
_cloud_id: &str,
_config: &HazeConfig,
) -> Result<Vec<String>> {
) -> Result<Vec<Vec<String>>> {
Ok(vec![
"occ config:app:set files_antivirus av_mode --value=icap".into(),
"occ config:app:set files_antivirus av_host --value=kaspersky-icap".into(),
"occ config:app:set files_antivirus av_port --value=1344".into(),
"occ config:app:set files_antivirus av_icap_request_service --value=req".into(),
"occ config:app:set files_antivirus av_icap_response_header --value=X-Virus-ID".into(),
split_cmnd("occ config:app:set files_antivirus av_mode --value=icap"),
split_cmnd("occ config:app:set files_antivirus av_host --value=kaspersky-icap"),
split_cmnd("occ config:app:set files_antivirus av_port --value=1344"),
split_cmnd("occ config:app:set files_antivirus av_icap_request_service --value=req"),
split_cmnd(
"occ config:app:set files_antivirus av_icap_response_header --value=X-Virus-ID",
),
])
}
}

View file

@ -1,7 +1,7 @@
use crate::cloud::CloudOptions;
use crate::config::{HazeConfig, ProxyConfig};
use crate::image::pull_image;
use crate::service::ServiceTrait;
use crate::service::{split_cmnd, ServiceTrait};
use crate::Result;
use bollard::config::NetworkingConfig;
use bollard::models::{ContainerCreateBody, ContainerState, EndpointSettings, HostConfig};
@ -92,30 +92,29 @@ impl ServiceTrait for Ldap {
_docker: &Docker,
_cloud_id: &str,
_config: &HazeConfig,
) -> Result<Vec<String>> {
) -> Result<Vec<Vec<String>>> {
Ok(vec![
"occ ldap:create-empty-config".into(),
"occ ldap:set-config s01 ldapHost 'ldap://ldap'".into(),
"occ ldap:set-config s01 ldapPort '389'".into(),
"occ ldap:set-config s01 ldapAgentName 'cn=admin,dc=example,dc=org'".into(),
"occ ldap:set-config s01 ldapAgentPassword 'haze'".into(),
"occ ldap:set-config s01 ldapBase 'dc=example,dc=org'".into(),
"occ ldap:set-config s01 ldapBaseUsers 'dc=example,dc=org'".into(),
"occ ldap:set-config s01 ldapBaseGroups 'dc=example,dc=org'".into(),
"occ ldap:set-config s01 ldapLoginFilter '(&(&(objectclass=inetOrgPerson))(uid=%uid))'"
.into(),
"occ ldap:set-config s01 ldapUserFilter '((objectclass=inetOrgPerson))'".into(),
"occ ldap:set-config s01 ldapUserFilterMode '0'".into(),
"occ ldap:set-config s01 ldapUserDisplayName 'sn'".into(),
"occ ldap:set-config s01 ldapUserFilterObjectclass 'inetOrgPerson'".into(),
"occ ldap:set-config s01 ldapGroupFilter '(&(|(objectclass=posixGroup)))'".into(),
"occ ldap:set-config s01 ldapGroupFilterObjectclass 'posixGroup'".into(),
"occ ldap:set-config s01 ldapEmailAttribute 'email'".into(),
"occ ldap:set-config s01 ldapUuidUserAttribute 'email'".into(),
"occ ldap:set-config s01 ldapUuidUserAttribute 'auto'".into(),
"occ ldap:set-config s01 ldapUuidGroupAttribute 'auto'".into(),
"occ ldap:set-config s01 ldapLoginFilterUsername '1'".into(),
"occ ldap:set-config s01 ldapConfigurationActive '1'".into(),
split_cmnd("occ ldap:create-empty-config"),
split_cmnd("occ ldap:set-config s01 ldapHost 'ldap://ldap'"),
split_cmnd("occ ldap:set-config s01 ldapPort '389'"),
split_cmnd("occ ldap:set-config s01 ldapAgentName 'cn=admin,dc=example,dc=org'"),
split_cmnd("occ ldap:set-config s01 ldapAgentPassword 'haze'"),
split_cmnd("occ ldap:set-config s01 ldapBase 'dc=example,dc=org'"),
split_cmnd("occ ldap:set-config s01 ldapBaseUsers 'dc=example,dc=org'"),
split_cmnd("occ ldap:set-config s01 ldapBaseGroups 'dc=example,dc=org'"),
split_cmnd("occ ldap:set-config s01 ldapLoginFilter '(&(&(objectclass=inetOrgPerson))(uid=%uid))'"),
split_cmnd("occ ldap:set-config s01 ldapUserFilter '((objectclass=inetOrgPerson))'"),
split_cmnd("occ ldap:set-config s01 ldapUserFilterMode '0'"),
split_cmnd("occ ldap:set-config s01 ldapUserDisplayName 'sn'"),
split_cmnd("occ ldap:set-config s01 ldapUserFilterObjectclass 'inetOrgPerson'"),
split_cmnd("occ ldap:set-config s01 ldapGroupFilter '(&(|(objectclass=posixGroup)))'"),
split_cmnd("occ ldap:set-config s01 ldapGroupFilterObjectclass 'posixGroup'"),
split_cmnd("occ ldap:set-config s01 ldapEmailAttribute 'email'"),
split_cmnd("occ ldap:set-config s01 ldapUuidUserAttribute 'email'"),
split_cmnd("occ ldap:set-config s01 ldapUuidUserAttribute 'auto'"),
split_cmnd("occ ldap:set-config s01 ldapUuidGroupAttribute 'auto'"),
split_cmnd("occ ldap:set-config s01 ldapLoginFilterUsername '1'"),
split_cmnd("occ ldap:set-config s01 ldapConfigurationActive '1'"),
])
}

View file

@ -1,7 +1,7 @@
use crate::cloud::CloudOptions;
use crate::config::HazeConfig;
use crate::image::pull_image;
use crate::service::ServiceTrait;
use crate::service::{split_cmnd, ServiceTrait};
use crate::Result;
use bollard::models::{ContainerCreateBody, EndpointSettings, HostConfig, NetworkingConfig};
use bollard::query_parameters::CreateContainerOptions;
@ -70,14 +70,14 @@ impl ServiceTrait for Mail {
_docker: &Docker,
_cloud_id: &str,
_config: &HazeConfig,
) -> Result<Vec<String>> {
) -> Result<Vec<Vec<String>>> {
Ok(vec![
"occ config:system:set mail_smtpmode --value smtp".into(),
"occ config:system:set mail_sendmailmode --value smtp".into(),
"occ config:system:set mail_domain --value haze".into(),
"occ config:system:set mail_smtphost --value mail".into(),
"occ config:system:set mail_smtpport --value 25".into(),
"occ user:setting admin settings email admin@haze".into(),
split_cmnd("occ config:system:set mail_smtpmode --value smtp"),
split_cmnd("occ config:system:set mail_sendmailmode --value smtp"),
split_cmnd("occ config:system:set mail_domain --value haze"),
split_cmnd("occ config:system:set mail_smtphost --value mail"),
split_cmnd("occ config:system:set mail_smtpport --value 25"),
split_cmnd("occ user:setting admin settings email admin@haze"),
])
}
}

View file

@ -2,7 +2,7 @@ use crate::cloud::CloudOptions;
use crate::config::HazeConfig;
use crate::exec::exec;
use crate::image::pull_image;
use crate::service::ServiceTrait;
use crate::service::{split_cmnd, ServiceTrait};
use crate::Result;
use bollard::models::{
ContainerCreateBody, ContainerState, EndpointSettings, HostConfig, NetworkingConfig,
@ -247,18 +247,18 @@ impl ServiceTrait for ObjectStore {
_docker: &Docker,
_cloud_id: &str,
_config: &HazeConfig,
) -> Result<Vec<String>> {
) -> Result<Vec<Vec<String>>> {
match self {
ObjectStore::S3 => Ok(vec![
"occ files_external:create s3 amazons3 amazons3::accesskey".into(),
"occ files_external:config 1 bucket ext".into(),
"occ files_external:config 1 hostname s3".into(),
"occ files_external:config 1 port 9000".into(),
"occ files_external:config 1 use_ssl false".into(),
"occ files_external:config 1 use_path_style true".into(),
"occ files_external:config 1 key minio".into(),
"occ files_external:config 1 secret minio123".into(),
"mc alias set s3 http://s3:9000 minio minio123".into(),
split_cmnd("occ files_external:create s3 amazons3 amazons3::accesskey"),
split_cmnd("occ files_external:config 1 bucket ext"),
split_cmnd("occ files_external:config 1 hostname s3"),
split_cmnd("occ files_external:config 1 port 9000"),
split_cmnd("occ files_external:config 1 use_ssl false"),
split_cmnd("occ files_external:config 1 use_path_style true"),
split_cmnd("occ files_external:config 1 key minio"),
split_cmnd("occ files_external:config 1 secret minio123"),
split_cmnd("mc alias set s3 http://s3:9000 minio minio123"),
]),
// ObjectStore::S3s => Ok(vec![
// "occ files_external:create s3 amazons3 amazons3::accesskey".into(),

View file

@ -83,7 +83,7 @@ impl ServiceTrait for Oc {
docker: &Docker,
cloud_id: &str,
config: &HazeConfig,
) -> Result<Vec<String>> {
) -> Result<Vec<Vec<String>>> {
if let Some(ip) = self.get_ips(docker, cloud_id).await?.next() {
let container = self.container_name(cloud_id).unwrap();
let addr = config.proxy.addr(&container, ip);

View file

@ -119,7 +119,7 @@ impl ServiceTrait for Office {
docker: &Docker,
cloud_id: &str,
config: &HazeConfig,
) -> Result<Vec<String>> {
) -> Result<Vec<Vec<String>>> {
let container = &self.container_name(cloud_id).unwrap();
let info = docker
.inspect_container(container, None)
@ -152,8 +152,22 @@ impl ServiceTrait for Office {
.addr_with_port(container, ip, self.proxy_port());
Ok(vec![
format!(r#"occ config:app:set richdocuments public_wopi_url --value="{public}""#),
r#"occ richdocuments:setup --wopi-url "http://office:9980" --callback-url "http://cloud""#.into(),
vec![
"occ".into(),
"config:app:set".into(),
"richdocuments".into(),
"public_wopi_url".into(),
"--value".into(),
public,
],
vec![
"occ".into(),
"richdocuments:setup".into(),
"--wopi-url".into(),
"http://office:9980".into(),
"--callback-url".into(),
"http://cloud".into(),
],
])
}

View file

@ -2,7 +2,7 @@ use crate::cloud::CloudOptions;
use crate::config::HazeConfig;
use crate::exec::exec;
use crate::image::pull_image;
use crate::service::ServiceTrait;
use crate::service::{split_cmnd, ServiceTrait};
use crate::Result;
use bollard::models::{
ContainerCreateBody, ContainerState, EndpointSettings, HostConfig, NetworkingConfig,
@ -82,7 +82,7 @@ impl ServiceTrait for OnlyOffice {
docker: &Docker,
cloud_id: &str,
config: &HazeConfig,
) -> Result<Vec<String>> {
) -> Result<Vec<Vec<String>>> {
let info = docker
.inspect_container(&self.container_name(cloud_id).unwrap(), None)
.await
@ -137,16 +137,44 @@ impl ServiceTrait for OnlyOffice {
);
Ok(vec![
format!("occ config:app:set onlyoffice DocumentServerUrl --value {addr}/"),
format!("occ config:app:set onlyoffice jwt_secret --value {secret}"),
"occ onlyoffice:documentserver --check".into(),
vec![
"occ".into(),
"config:app:set".into(),
"onlyoffice".into(),
"DocumentServerUrl".into(),
"--value".into(),
addr,
],
vec![
"occ".into(),
"config:app:set".into(),
"onlyoffice".into(),
"jwt_secret".into(),
"--value".into(),
secret.into(),
],
split_cmnd("occ onlyoffice:documentserver --check"),
])
} else {
Ok(vec![
format!("occ config:app:set onlyoffice DocumentServerUrl --value https://{ip}/"),
"occ config:app:set onlyoffice verify_peer_off --value true".into(),
format!("occ config:app:set onlyoffice jwt_secret --value {secret}"),
"occ onlyoffice:documentserver --check".into(),
vec![
"occ".into(),
"config:app:set".into(),
"onlyoffice".into(),
"DocumentServerUrl".into(),
"--value".into(),
format!("https://{ip}/"),
],
split_cmnd("occ config:app:set onlyoffice verify_peer_off --value true"),
vec![
"occ".into(),
"config:app:set".into(),
"onlyoffice".into(),
"jwt_secret".into(),
"--value".into(),
secret.into(),
],
split_cmnd("occ onlyoffice:documentserver --check"),
])
}
}

View file

@ -87,7 +87,7 @@ impl ServiceTrait for NotifyPush {
docker: &Docker,
cloud_id: &str,
config: &HazeConfig,
) -> Result<Vec<String>> {
) -> Result<Vec<Vec<String>>> {
let mut ips: Vec<_> = self.get_ips(docker, cloud_id).await?.collect();
if let Ok(local_interfaces) = list_afinet_netifas() {
ips.extend(local_interfaces.into_iter().map(|(_, ip)| ip));
@ -97,10 +97,14 @@ impl ServiceTrait for NotifyPush {
.iter()
.enumerate()
.map(|(i, ip)| {
format!(
"occ config:system:set trusted_proxies {} --value {ip}",
i + 1
)
vec![
"occ".into(),
"config:system:set".into(),
"trusted_proxies".into(),
(i + 1).to_string(),
"--value".into(),
ip.to_string(),
]
})
.collect();
@ -108,7 +112,7 @@ impl ServiceTrait for NotifyPush {
config
.proxy
.addr_with_port(&self.container_name(cloud_id).unwrap(), ips[0], 7867);
commands.push(format!("occ notify_push:setup {}", addr));
commands.push(vec!["occ".into(), "notify_push:setup".into(), addr]);
Ok(commands)
}

View file

@ -1,7 +1,7 @@
use crate::cloud::CloudOptions;
use crate::config::HazeConfig;
use crate::image::pull_image;
use crate::service::ServiceTrait;
use crate::service::{split_cmnd, ServiceTrait};
use crate::Result;
use bollard::models::{ContainerCreateBody, EndpointSettings, HostConfig, NetworkingConfig};
use bollard::query_parameters::CreateContainerOptions;
@ -70,7 +70,9 @@ impl ServiceTrait for Redis {
_docker: &Docker,
_cloud_id: &str,
_config: &HazeConfig,
) -> Result<Vec<String>> {
Ok(vec!["occ config:system:set redis host --value redis".into()])
) -> Result<Vec<Vec<String>>> {
Ok(vec![split_cmnd(
"occ config:system:set redis host --value redis",
)])
}
}

View file

@ -1,13 +1,14 @@
use crate::cloud::CloudOptions;
use crate::config::HazeConfig;
use crate::image::pull_image;
use crate::service::ServiceTrait;
use crate::service::{split_cmnd, ServiceTrait};
use crate::Result;
use bollard::models::{ContainerCreateBody, EndpointSettings, HostConfig, NetworkingConfig};
use bollard::query_parameters::CreateContainerOptions;
use bollard::Docker;
use maplit::hashmap;
use miette::IntoDiagnostic;
use miette::{Context, IntoDiagnostic};
use std::fs::{create_dir_all, write};
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct Sftp;
@ -75,13 +76,119 @@ impl ServiceTrait for Sftp {
_docker: &Docker,
_cloud_id: &str,
_config: &HazeConfig,
) -> Result<Vec<String>> {
) -> Result<Vec<Vec<String>>> {
Ok(vec![
"occ files_external:create sftp sftp password::password".into(),
"occ files_external:config 1 host sftp".into(),
"occ files_external:config 1 user test".into(),
"occ files_external:config 1 root data".into(),
"occ files_external:config 1 password test".into(),
split_cmnd("occ files_external:create sftp sftp password::password"),
split_cmnd("occ files_external:config 1 host sftp"),
split_cmnd("occ files_external:config 1 user test"),
split_cmnd("occ files_external:config 1 root data"),
split_cmnd("occ files_external:config 1 password test"),
])
}
}
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct SftpKey;
#[async_trait::async_trait]
impl ServiceTrait for SftpKey {
fn name(&self) -> &str {
"sftp-key"
}
async fn spawn(
&self,
docker: &Docker,
cloud_id: &str,
network: &str,
config: &HazeConfig,
_options: &CloudOptions,
) -> Result<Vec<String>> {
let image = "atmoz/sftp:alpine";
pull_image(docker, image).await?;
let options = Some(CreateContainerOptions {
name: self.container_name(cloud_id),
..CreateContainerOptions::default()
});
let key_dir = config.work_dir.join("certificates/sftp");
create_dir_all(&key_dir)
.into_diagnostic()
.wrap_err("Failed to create sftp certificate directory")?;
let private_path = key_dir.join("id_rsa");
let public_path = key_dir.join("id_rsa.pub");
let private_key = include_str!("../../certificates/sftp/id_rsa");
let public_key = include_str!("../../certificates/sftp/id_rsa.pub");
if !private_path.exists() {
write(&private_path, private_key)
.into_diagnostic()
.wrap_err("Failed to write sftp client certificate")?;
}
if !public_path.exists() {
write(&public_path, public_key)
.into_diagnostic()
.wrap_err("Failed to write sftp client key")?;
}
let volumes = vec![format!("{public_path}:/home/test/.ssh/keys/id_rsa:ro")];
let config = ContainerCreateBody {
image: Some(image.into()),
host_config: Some(HostConfig {
network_mode: Some(network.to_string()),
binds: Some(volumes),
..Default::default()
}),
labels: Some(hashmap! {
"haze-type".into() => self.name().into(),
"haze-cloud-id".into() => cloud_id.into(),
}),
networking_config: Some(NetworkingConfig {
endpoints_config: Some(hashmap! {
network.into() => EndpointSettings {
aliases: Some(vec![self.name().to_string()]),
..Default::default()
}
}),
}),
cmd: Some(vec!["test::::data".into()]),
..Default::default()
};
let id = docker
.create_container(options, config)
.await
.into_diagnostic()?
.id;
docker.start_container(&id, None).await.into_diagnostic()?;
Ok(vec![id])
}
fn container_name(&self, cloud_id: &str) -> Option<String> {
Some(format!("{}-sftp-key", cloud_id))
}
fn apps(&self) -> &'static [&'static str] {
&["files_external"]
}
async fn post_setup(
&self,
_docker: &Docker,
_cloud_id: &str,
_config: &HazeConfig,
) -> Result<Vec<Vec<String>>> {
Ok(vec![
split_cmnd("occ files_external:create sftp sftp publickey::rsa_private"),
split_cmnd("occ files_external:config 1 host sftp-key"),
split_cmnd("occ files_external:config 1 user test"),
split_cmnd("occ files_external:config 1 root data"),
vec![
"occ".into(),
"files_external:config".into(),
"--value-from-file".into(),
"1".into(),
"private_key".into(),
"/certificates/sftp/id_rsa".into(),
],
])
}
}

View file

@ -1,7 +1,7 @@
use crate::cloud::CloudOptions;
use crate::config::HazeConfig;
use crate::image::pull_image;
use crate::service::ServiceTrait;
use crate::service::{split_cmnd, ServiceTrait};
use crate::Result;
use bollard::models::{ContainerCreateBody, EndpointSettings, HostConfig, NetworkingConfig};
use bollard::query_parameters::CreateContainerOptions;
@ -79,13 +79,13 @@ impl ServiceTrait for Smb {
_docker: &Docker,
_cloud_id: &str,
_config: &HazeConfig,
) -> Result<Vec<String>> {
) -> Result<Vec<Vec<String>>> {
Ok(vec![
"occ files_external:create smb smb password::password".into(),
"occ files_external:config 1 host smb".into(),
"occ files_external:config 1 user test".into(),
"occ files_external:config 1 password test".into(),
"occ files_external:config 1 share test".into(),
split_cmnd("occ files_external:create smb smb password::password"),
split_cmnd("occ files_external:config 1 host smb"),
split_cmnd("occ files_external:config 1 user test"),
split_cmnd("occ files_external:config 1 password test"),
split_cmnd("occ files_external:config 1 share test"),
])
}
}