mirror of
https://github.com/kanidm/kanidm.git
synced 2025-02-23 12:37:00 +01:00
Add tls generator to main kanidmd (#1743)
This commit is contained in:
parent
32a7200305
commit
8b331325ae
2
Makefile
2
Makefile
|
@ -60,6 +60,7 @@ build/kanidmd: ## Build the kanidmd docker image locally
|
|||
build/kanidmd:
|
||||
@$(CONTAINER_TOOL) build $(CONTAINER_TOOL_ARGS) -f server/Dockerfile \
|
||||
-t $(IMAGE_BASE)/server:$(IMAGE_VERSION) \
|
||||
--platform $(IMAGE_ARCH) \
|
||||
--build-arg "KANIDM_BUILD_PROFILE=container_generic" \
|
||||
--build-arg "KANIDM_FEATURES=" \
|
||||
$(CONTAINER_BUILD_ARGS) .
|
||||
|
@ -68,6 +69,7 @@ build/kanidmd:
|
|||
build/radiusd: ## Build the radiusd docker image locally
|
||||
build/radiusd:
|
||||
@$(CONTAINER_TOOL) build $(CONTAINER_TOOL_ARGS) \
|
||||
--platform $(IMAGE_ARCH) \
|
||||
-f rlm_python/Dockerfile \
|
||||
-t $(IMAGE_BASE)/radius:$(IMAGE_VERSION) .
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
# Kanidm
|
||||
|
||||
- [Introduction to Kanidm](intro.md)
|
||||
- [Evaluation Quickstart](quickstart.md)
|
||||
- [Installing the Server](installing_the_server.md)
|
||||
- [Choosing a Domain Name](choosing_a_domain_name.md)
|
||||
- [Preparing for your Deployment](prepare_the_server.md)
|
||||
|
|
83
book/src/quickstart.md
Normal file
83
book/src/quickstart.md
Normal file
|
@ -0,0 +1,83 @@
|
|||
# Evaluation Quickstart
|
||||
|
||||
This section will guide you through a quick setup of Kanidm for evaluation. It's recommended that
|
||||
for a production deployment you follow the steps in the
|
||||
[installation chapter](installing_the_server.html) instead as there are a number of security
|
||||
considerations you should understand.
|
||||
|
||||
### Requirements
|
||||
|
||||
- docker or podman
|
||||
- `x86_64` cpu supporting `x86_64_v2` OR `aarch64` cpu supporting `neon`
|
||||
|
||||
### Get the software
|
||||
|
||||
```bash
|
||||
docker pull kanidm/server:latest
|
||||
```
|
||||
|
||||
### Configure the container
|
||||
|
||||
```bash
|
||||
docker volume create kanidmd
|
||||
docker create --name kanidmd \
|
||||
-p 443:8443 \
|
||||
-p 636:3636 \
|
||||
-v kanidmd:/data \
|
||||
kanidm/server:latest
|
||||
```
|
||||
|
||||
### Configure the server
|
||||
|
||||
Create server.toml
|
||||
|
||||
```toml
|
||||
{{#rustdoc_include ../../examples/server_container.toml}}
|
||||
```
|
||||
|
||||
### Add configuration to container
|
||||
|
||||
```bash
|
||||
docker cp server.toml kanidmd:/data/server.toml
|
||||
```
|
||||
|
||||
### Generate evaluation certificates
|
||||
|
||||
```bash
|
||||
docker run --rm -i -t -v kanidmd:/data \
|
||||
kanidm/server:latest \
|
||||
kanidmd cert-generate -c /data/server.toml
|
||||
```
|
||||
|
||||
### Recover the admin password
|
||||
|
||||
```bash
|
||||
docker run --rm -i -t -v kanidmd:/data \
|
||||
kanidm/server:latest \
|
||||
kanidmd recover-account admin -c /data/server.toml
|
||||
```
|
||||
|
||||
### Start Kanidmd
|
||||
|
||||
```bash
|
||||
docker start kanidmd
|
||||
```
|
||||
|
||||
### Setup the client configuration
|
||||
|
||||
```toml
|
||||
# ~/.config/kanidm
|
||||
|
||||
uri = "https://localhost:443"
|
||||
verify_ca = false
|
||||
```
|
||||
|
||||
### Check you can login
|
||||
|
||||
```bash
|
||||
kanidm login
|
||||
```
|
||||
|
||||
### What next?
|
||||
|
||||
You can now follow the steps in the [administration section](administrivia.md)
|
|
@ -19,8 +19,8 @@ auth_token = "putyourtokenhere"
|
|||
|
||||
radius_cert_path = "/certs/cert.pem" # the TLS certificate
|
||||
radius_key_path = "/certs/key.pem" # the signing key for radius TLS
|
||||
radius_dh_path = "/certs/dh.pem" # the diffie-hellman output
|
||||
radius_ca_path = "/certs/ca.pem" # the CA certificate
|
||||
radius_dh_path = "/certs/dh.pem" # the diffie-hellman output
|
||||
|
||||
# A list of groups, if a user is in them, they're approved for RADIUS authentication
|
||||
radius_required_groups = [
|
||||
|
@ -42,4 +42,4 @@ radius_clients = [
|
|||
]
|
||||
|
||||
# The client connection timeout, in seconds.
|
||||
connect_timeout = 30
|
||||
connect_timeout = 30
|
||||
|
|
|
@ -47,7 +47,6 @@ RUN python3 -m pip install --no-cache-dir --no-warn-script-location /pkg/pykanid
|
|||
|
||||
COPY rlm_python/radius_entrypoint.py /radius_entrypoint.py
|
||||
|
||||
ENV LD_PRELOAD=/usr/lib64/libpython3.so
|
||||
ENV KANIDM_CONFIG_FILE="/data/kanidm"
|
||||
|
||||
RUN chmod a+r /etc/raddb/certs/ -R
|
||||
|
|
|
@ -79,12 +79,15 @@ def setup_certs(
|
|||
if kanidm_config_object.radius_dh_path is not None:
|
||||
cert_dh = Path(kanidm_config_object.radius_dh_path).expanduser().resolve()
|
||||
if not cert_dh.exists():
|
||||
print(f"Failed to find radiusd dh file ({cert_dh}), quitting!", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
# print(f"Failed to find radiusd dh file ({cert_dh}), quitting!", file=sys.stderr)
|
||||
# sys.exit(1)
|
||||
print(f"Generating dh params in {cert_dh}")
|
||||
subprocess.check_call(["openssl", "dhparam", "-out", cert_dh, "2048"])
|
||||
if cert_dh != CERT_DH_DEST:
|
||||
print(f"Copying {cert_dh} to {CERT_DH_DEST}")
|
||||
shutil.copyfile(cert_dh, CERT_DH_DEST)
|
||||
|
||||
|
||||
server_key = Path(kanidm_config_object.radius_key_path).expanduser().resolve()
|
||||
if not server_key.exists() or not server_key.is_file():
|
||||
print(
|
||||
|
|
|
@ -1,23 +1,29 @@
|
|||
#!/bin/bash
|
||||
set -x
|
||||
|
||||
|
||||
if [ -z "${IMAGE}" ]; then
|
||||
IMAGE="kanidm/radius:devel"
|
||||
fi
|
||||
echo "Running docker container: ${IMAGE}"
|
||||
|
||||
if [ ! -z "${IMAGE_ARCH}" ]; then
|
||||
IMAGE_ARCH="--platform ${IMAGE_ARCH}"
|
||||
fi
|
||||
|
||||
if [ -z "${CONFIG_FILE}" ]; then
|
||||
CONFIG_FILE="$(pwd)/../examples/kanidm"
|
||||
fi
|
||||
echo "Using config file: ${CONFIG_FILE}"
|
||||
|
||||
if [ ! -d "/tmp/kanidm/" ]; then
|
||||
echo "Can't find /tmp/kanidm - you might need to run insecure_generate_tls.sh"
|
||||
echo "Can't find /tmp/kanidm - you may need to run run_insecure_dev_server"
|
||||
fi
|
||||
|
||||
echo "Starting the dev container..."
|
||||
#shellcheck disable=SC2068
|
||||
docker run --rm -it \
|
||||
${IMAGE_ARCH} \
|
||||
--network host \
|
||||
--name radiusd \
|
||||
-v /tmp/kanidm/:/data/ \
|
||||
|
|
|
@ -1,11 +1,28 @@
|
|||
//! This module contains cryptographic setup code, a long with what policy
|
||||
//! and ciphers we accept.
|
||||
|
||||
use openssl::ec::{EcGroup, EcKey};
|
||||
use openssl::error::ErrorStack;
|
||||
use openssl::nid::Nid;
|
||||
use openssl::ssl::{SslAcceptor, SslAcceptorBuilder, SslFiletype, SslMethod};
|
||||
use openssl::x509::{
|
||||
extension::{
|
||||
AuthorityKeyIdentifier, BasicConstraints, KeyUsage, SubjectAlternativeName,
|
||||
SubjectKeyIdentifier,
|
||||
},
|
||||
X509NameBuilder, X509ReqBuilder, X509,
|
||||
};
|
||||
use openssl::{asn1, bn, hash, pkey};
|
||||
|
||||
use crate::config::Configuration;
|
||||
|
||||
use std::fs::File;
|
||||
use std::io::{Read, Write};
|
||||
use std::path::Path;
|
||||
|
||||
const CA_VALID_DAYS: u32 = 30;
|
||||
const CERT_VALID_DAYS: u32 = 5;
|
||||
|
||||
/// From the server configuration, generate an OpenSSL acceptor that we can use
|
||||
/// to build our sockets for https/ldaps.
|
||||
pub fn setup_tls(config: &Configuration) -> Result<Option<SslAcceptorBuilder>, ErrorStack> {
|
||||
|
@ -20,3 +37,264 @@ pub fn setup_tls(config: &Configuration) -> Result<Option<SslAcceptorBuilder>, E
|
|||
None => Ok(None),
|
||||
}
|
||||
}
|
||||
|
||||
fn get_group() -> Result<EcGroup, ErrorStack> {
|
||||
EcGroup::from_curve_name(Nid::X9_62_PRIME256V1)
|
||||
}
|
||||
|
||||
pub(crate) struct CaHandle {
|
||||
key: pkey::PKey<pkey::Private>,
|
||||
cert: X509,
|
||||
}
|
||||
|
||||
pub(crate) fn write_ca(
|
||||
key_ar: impl AsRef<Path>,
|
||||
cert_ar: impl AsRef<Path>,
|
||||
handle: &CaHandle,
|
||||
) -> Result<(), ()> {
|
||||
let key_path: &Path = key_ar.as_ref();
|
||||
let cert_path: &Path = cert_ar.as_ref();
|
||||
|
||||
let key_pem = handle.key.private_key_to_pem_pkcs8().map_err(|e| {
|
||||
error!(err = ?e, "Failed to convert key to PEM");
|
||||
})?;
|
||||
|
||||
let cert_pem = handle.cert.to_pem().map_err(|e| {
|
||||
error!(err = ?e, "Failed to convert cert to PEM");
|
||||
})?;
|
||||
|
||||
File::create(key_path)
|
||||
.and_then(|mut file| file.write_all(&key_pem))
|
||||
.map_err(|e| {
|
||||
error!(err = ?e, "Failed to create {:?}", key_path);
|
||||
})?;
|
||||
|
||||
File::create(cert_path)
|
||||
.and_then(|mut file| file.write_all(&cert_pem))
|
||||
.map_err(|e| {
|
||||
error!(err = ?e, "Failed to create {:?}", cert_path);
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn build_ca() -> Result<CaHandle, ErrorStack> {
|
||||
let ecgroup = get_group()?;
|
||||
let eckey = EcKey::generate(&ecgroup)?;
|
||||
let ca_key = pkey::PKey::from_ec_key(eckey)?;
|
||||
let mut x509_name = X509NameBuilder::new()?;
|
||||
|
||||
x509_name.append_entry_by_text("C", "AU")?;
|
||||
x509_name.append_entry_by_text("ST", "QLD")?;
|
||||
x509_name.append_entry_by_text("O", "Kanidm")?;
|
||||
x509_name.append_entry_by_text("CN", "Kanidm Generated CA")?;
|
||||
x509_name.append_entry_by_text("OU", "Development and Evaluation - NOT FOR PRODUCTION")?;
|
||||
let x509_name = x509_name.build();
|
||||
|
||||
let mut cert_builder = X509::builder()?;
|
||||
// Yes, 2 actually means 3 here ...
|
||||
cert_builder.set_version(2)?;
|
||||
|
||||
let serial_number = bn::BigNum::from_u32(1).and_then(|serial| serial.to_asn1_integer())?;
|
||||
|
||||
cert_builder.set_serial_number(&serial_number)?;
|
||||
cert_builder.set_subject_name(&x509_name)?;
|
||||
cert_builder.set_issuer_name(&x509_name)?;
|
||||
|
||||
let not_before = asn1::Asn1Time::days_from_now(0)?;
|
||||
cert_builder.set_not_before(¬_before)?;
|
||||
let not_after = asn1::Asn1Time::days_from_now(CA_VALID_DAYS)?;
|
||||
cert_builder.set_not_after(¬_after)?;
|
||||
|
||||
cert_builder.append_extension(BasicConstraints::new().critical().ca().pathlen(0).build()?)?;
|
||||
cert_builder.append_extension(
|
||||
KeyUsage::new()
|
||||
.critical()
|
||||
.key_cert_sign()
|
||||
.crl_sign()
|
||||
.build()?,
|
||||
)?;
|
||||
|
||||
let subject_key_identifier =
|
||||
SubjectKeyIdentifier::new().build(&cert_builder.x509v3_context(None, None))?;
|
||||
cert_builder.append_extension(subject_key_identifier)?;
|
||||
|
||||
cert_builder.set_pubkey(&ca_key)?;
|
||||
|
||||
cert_builder.sign(&ca_key, hash::MessageDigest::sha256())?;
|
||||
let ca_cert = cert_builder.build();
|
||||
|
||||
Ok(CaHandle {
|
||||
key: ca_key,
|
||||
cert: ca_cert,
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn load_ca(
|
||||
ca_key_ar: impl AsRef<Path>,
|
||||
ca_cert_ar: impl AsRef<Path>,
|
||||
) -> Result<CaHandle, ()> {
|
||||
let ca_key_path: &Path = ca_key_ar.as_ref();
|
||||
let ca_cert_path: &Path = ca_cert_ar.as_ref();
|
||||
|
||||
let mut ca_key_pem = vec![];
|
||||
File::open(ca_key_path)
|
||||
.and_then(|mut file| file.read_to_end(&mut ca_key_pem))
|
||||
.map_err(|e| {
|
||||
error!(err = ?e, "Failed to read {:?}", ca_key_path);
|
||||
})?;
|
||||
|
||||
let mut ca_cert_pem = vec![];
|
||||
File::open(ca_cert_path)
|
||||
.and_then(|mut file| file.read_to_end(&mut ca_cert_pem))
|
||||
.map_err(|e| {
|
||||
error!(err = ?e, "Failed to read {:?}", ca_cert_path);
|
||||
})?;
|
||||
|
||||
let ca_key = pkey::PKey::private_key_from_pem(&ca_key_pem).map_err(|e| {
|
||||
error!(err = ?e, "Failed to convert PEM to key");
|
||||
})?;
|
||||
|
||||
let ca_cert = X509::from_pem(&ca_cert_pem).map_err(|e| {
|
||||
error!(err = ?e, "Failed to convert PEM to cert");
|
||||
})?;
|
||||
|
||||
Ok(CaHandle {
|
||||
key: ca_key,
|
||||
cert: ca_cert,
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) struct CertHandle {
|
||||
key: pkey::PKey<pkey::Private>,
|
||||
cert: X509,
|
||||
chain: Vec<X509>,
|
||||
}
|
||||
|
||||
pub(crate) fn write_cert(
|
||||
key_ar: impl AsRef<Path>,
|
||||
chain_ar: impl AsRef<Path>,
|
||||
cert_ar: impl AsRef<Path>,
|
||||
handle: &CertHandle,
|
||||
) -> Result<(), ()> {
|
||||
let key_path: &Path = key_ar.as_ref();
|
||||
let chain_path: &Path = chain_ar.as_ref();
|
||||
let cert_path: &Path = cert_ar.as_ref();
|
||||
|
||||
let key_pem = handle.key.private_key_to_pem_pkcs8().map_err(|e| {
|
||||
error!(err = ?e, "Failed to convert key to PEM");
|
||||
})?;
|
||||
|
||||
let cert_pem = handle.cert.to_pem().map_err(|e| {
|
||||
error!(err = ?e, "Failed to convert cert to PEM");
|
||||
})?;
|
||||
|
||||
let mut chain_pem = cert_pem.clone();
|
||||
|
||||
// Build the chain PEM.
|
||||
for ca_cert in &handle.chain {
|
||||
match ca_cert.to_pem() {
|
||||
Ok(c) => {
|
||||
chain_pem.extend_from_slice(&c);
|
||||
}
|
||||
Err(e) => {
|
||||
error!(err = ?e, "Failed to convert cert to PEM");
|
||||
return Err(());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
File::create(key_path)
|
||||
.and_then(|mut file| file.write_all(&key_pem))
|
||||
.map_err(|e| {
|
||||
error!(err = ?e, "Failed to create {:?}", key_path);
|
||||
})?;
|
||||
|
||||
File::create(chain_path)
|
||||
.and_then(|mut file| file.write_all(&chain_pem))
|
||||
.map_err(|e| {
|
||||
error!(err = ?e, "Failed to create {:?}", chain_path);
|
||||
})?;
|
||||
|
||||
File::create(cert_path)
|
||||
.and_then(|mut file| file.write_all(&cert_pem))
|
||||
.map_err(|e| {
|
||||
error!(err = ?e, "Failed to create {:?}", cert_path);
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn build_cert(
|
||||
domain_name: &str,
|
||||
ca_handle: &CaHandle,
|
||||
) -> Result<CertHandle, ErrorStack> {
|
||||
let ecgroup = get_group()?;
|
||||
let eckey = EcKey::generate(&ecgroup)?;
|
||||
let int_key = pkey::PKey::from_ec_key(eckey)?;
|
||||
|
||||
//
|
||||
let mut req_builder = X509ReqBuilder::new()?;
|
||||
req_builder.set_pubkey(&int_key)?;
|
||||
|
||||
let mut x509_name = X509NameBuilder::new()?;
|
||||
x509_name.append_entry_by_text("C", "AU")?;
|
||||
x509_name.append_entry_by_text("ST", "QLD")?;
|
||||
x509_name.append_entry_by_text("O", "Kanidm")?;
|
||||
x509_name.append_entry_by_text("CN", domain_name)?;
|
||||
// Requirement of packed attestation.
|
||||
x509_name.append_entry_by_text("OU", "Development and Evaluation - NOT FOR PRODUCTION")?;
|
||||
let x509_name = x509_name.build();
|
||||
|
||||
req_builder.set_subject_name(&x509_name)?;
|
||||
req_builder.sign(&int_key, hash::MessageDigest::sha256())?;
|
||||
let req = req_builder.build();
|
||||
// ==
|
||||
|
||||
let mut cert_builder = X509::builder()?;
|
||||
// Yes, 2 actually means 3 here ...
|
||||
cert_builder.set_version(2)?;
|
||||
let serial_number = bn::BigNum::from_u32(2).and_then(|serial| serial.to_asn1_integer())?;
|
||||
|
||||
cert_builder.set_pubkey(&int_key)?;
|
||||
|
||||
cert_builder.set_serial_number(&serial_number)?;
|
||||
cert_builder.set_subject_name(req.subject_name())?;
|
||||
cert_builder.set_issuer_name(ca_handle.cert.subject_name())?;
|
||||
|
||||
let not_before = asn1::Asn1Time::days_from_now(0)?;
|
||||
cert_builder.set_not_before(¬_before)?;
|
||||
let not_after = asn1::Asn1Time::days_from_now(CERT_VALID_DAYS)?;
|
||||
cert_builder.set_not_after(¬_after)?;
|
||||
|
||||
cert_builder.append_extension(BasicConstraints::new().build()?)?;
|
||||
|
||||
cert_builder.append_extension(
|
||||
KeyUsage::new()
|
||||
.critical()
|
||||
.non_repudiation()
|
||||
.digital_signature()
|
||||
.key_encipherment()
|
||||
.build()?,
|
||||
)?;
|
||||
|
||||
let subject_key_identifier = SubjectKeyIdentifier::new()
|
||||
.build(&cert_builder.x509v3_context(Some(&ca_handle.cert), None))?;
|
||||
cert_builder.append_extension(subject_key_identifier)?;
|
||||
|
||||
let auth_key_identifier = AuthorityKeyIdentifier::new()
|
||||
.keyid(false)
|
||||
.issuer(false)
|
||||
.build(&cert_builder.x509v3_context(Some(&ca_handle.cert), None))?;
|
||||
cert_builder.append_extension(auth_key_identifier)?;
|
||||
|
||||
let subject_alt_name = SubjectAlternativeName::new()
|
||||
.dns(domain_name)
|
||||
.build(&cert_builder.x509v3_context(Some(&ca_handle.cert), None))?;
|
||||
cert_builder.append_extension(subject_alt_name)?;
|
||||
|
||||
cert_builder.sign(&ca_handle.key, hash::MessageDigest::sha256())?;
|
||||
let int_cert = cert_builder.build();
|
||||
|
||||
Ok(CertHandle {
|
||||
key: int_key,
|
||||
cert: int_cert,
|
||||
chain: vec![ca_handle.cert.clone()],
|
||||
})
|
||||
}
|
||||
|
|
|
@ -32,6 +32,7 @@ pub mod https;
|
|||
mod interval;
|
||||
mod ldaps;
|
||||
|
||||
use std::path::Path;
|
||||
use std::sync::Arc;
|
||||
|
||||
use compact_jwt::JwsSigner;
|
||||
|
@ -51,7 +52,6 @@ use tokio::sync::broadcast;
|
|||
use crate::actors::v1_read::QueryServerReadV1;
|
||||
use crate::actors::v1_write::QueryServerWriteV1;
|
||||
use crate::config::Configuration;
|
||||
use crate::crypto::setup_tls;
|
||||
use crate::interval::IntervalActor;
|
||||
|
||||
// === internal setup helpers
|
||||
|
@ -553,6 +553,98 @@ pub async fn recover_account_core(config: &Configuration, name: &str) {
|
|||
);
|
||||
}
|
||||
|
||||
pub fn cert_generate_core(config: &Configuration) {
|
||||
// Get the cert root
|
||||
|
||||
let (tls_key_path, tls_chain_path) = match &config.tls_config {
|
||||
Some(tls_config) => (
|
||||
Path::new(tls_config.key.as_str()),
|
||||
Path::new(tls_config.chain.as_str()),
|
||||
),
|
||||
None => {
|
||||
error!("Unable to find tls configuration");
|
||||
std::process::exit(1);
|
||||
}
|
||||
};
|
||||
|
||||
if tls_key_path.exists() && tls_chain_path.exists() {
|
||||
info!(
|
||||
"tls key and chain already exist - remove them first if you intend to regenerate these"
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
let origin = match Url::parse(&config.origin) {
|
||||
Ok(url) => url,
|
||||
Err(e) => {
|
||||
error!(err = ?e, "Unable to parse origin URL - refusing to start. You must correct the value for origin. {:?}", config.origin);
|
||||
std::process::exit(1);
|
||||
}
|
||||
};
|
||||
|
||||
let origin_domain = if let Some(d) = origin.domain() {
|
||||
d
|
||||
} else {
|
||||
error!("origin does not contain a valid domain");
|
||||
std::process::exit(1);
|
||||
};
|
||||
|
||||
let cert_root = match tls_key_path.parent() {
|
||||
Some(parent) => parent,
|
||||
None => {
|
||||
error!("Unable to find parent directory of {:?}", tls_key_path);
|
||||
std::process::exit(1);
|
||||
}
|
||||
};
|
||||
|
||||
let ca_cert = cert_root.join("ca.pem");
|
||||
let ca_key = cert_root.join("cakey.pem");
|
||||
let tls_cert_path = cert_root.join("cert.pem");
|
||||
|
||||
let ca_handle = if !ca_cert.exists() || !ca_key.exists() {
|
||||
// Generate the CA again.
|
||||
let ca_handle = match crypto::build_ca() {
|
||||
Ok(ca_handle) => ca_handle,
|
||||
Err(e) => {
|
||||
error!(err = ?e, "Failed to build CA");
|
||||
std::process::exit(1);
|
||||
}
|
||||
};
|
||||
|
||||
if crypto::write_ca(ca_key, ca_cert, &ca_handle).is_err() {
|
||||
error!("Failed to write CA");
|
||||
std::process::exit(1);
|
||||
}
|
||||
|
||||
ca_handle
|
||||
} else {
|
||||
match crypto::load_ca(ca_key, ca_cert) {
|
||||
Ok(ca_handle) => ca_handle,
|
||||
Err(_) => {
|
||||
error!("Failed to load CA");
|
||||
std::process::exit(1);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if !tls_key_path.exists() || !tls_chain_path.exists() || !tls_cert_path.exists() {
|
||||
// Generate the cert from the ca.
|
||||
let cert_handle = match crypto::build_cert(origin_domain, &ca_handle) {
|
||||
Ok(cert_handle) => cert_handle,
|
||||
Err(e) => {
|
||||
error!(err = ?e, "Failed to build certificate");
|
||||
std::process::exit(1);
|
||||
}
|
||||
};
|
||||
|
||||
if crypto::write_cert(tls_key_path, tls_chain_path, tls_cert_path, &cert_handle).is_err() {
|
||||
error!("Failed to write certificates");
|
||||
std::process::exit(1);
|
||||
}
|
||||
}
|
||||
info!("certificate generation complete");
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum CoreAction {
|
||||
Shutdown,
|
||||
|
@ -626,7 +718,7 @@ pub async fn create_server_core(
|
|||
let status_ref = StatusActor::start();
|
||||
|
||||
// Setup TLS (if any)
|
||||
let _opt_tls_params = match setup_tls(&config) {
|
||||
let _opt_tls_params = match crypto::setup_tls(&config) {
|
||||
Ok(opt_tls_params) => opt_tls_params,
|
||||
Err(e) => {
|
||||
error!("Failed to configure TLS parameters -> {:?}", e);
|
||||
|
@ -784,7 +876,7 @@ pub async fn create_server_core(
|
|||
// If we have been requested to init LDAP, configure it now.
|
||||
let maybe_ldap_acceptor_handle = match &config.ldapaddress {
|
||||
Some(la) => {
|
||||
let opt_ldap_tls_params = match setup_tls(&config) {
|
||||
let opt_ldap_tls_params = match crypto::setup_tls(&config) {
|
||||
Ok(t) => t,
|
||||
Err(e) => {
|
||||
error!("Failed to configure LDAP TLS parameters -> {:?}", e);
|
||||
|
|
|
@ -2,10 +2,6 @@
|
|||
|
||||
# This script based on the developer readme and allows you to run a test server.
|
||||
|
||||
if [ -z "$KANI_TMP" ]; then
|
||||
KANI_TMP=/tmp/kanidm
|
||||
fi
|
||||
|
||||
if [ -z "$KANI_CARGO_OPTS" ]; then
|
||||
KANI_CARGO_OPTS=""
|
||||
fi
|
||||
|
@ -17,14 +13,9 @@ if [ ! -f "${CONFIG_FILE}" ]; then
|
|||
echo "Couldn't find configuration file at ${CONFIG_FILE}, please ensure you're running this script from its base directory (${SCRIPT_DIR})."
|
||||
exit 1
|
||||
fi
|
||||
if [ ! -f "${KANI_TMP}/chain.pem" ]; then
|
||||
echo "Couldn't find certificate at /tmp/kanidm/chain.pem, quitting"
|
||||
exit 1
|
||||
fi
|
||||
if [ ! -f "${KANI_TMP}/key.pem" ]; then
|
||||
echo "Couldn't find key file at /tmp/kanidm/key.pem, quitting"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
#shellcheck disable=SC2086
|
||||
cargo run ${KANI_CARGO_OPTS} --bin kanidmd -- cert-generate -c "${CONFIG_FILE}"
|
||||
|
||||
COMMAND="server"
|
||||
if [ -n "${1}" ]; then
|
||||
|
|
|
@ -25,10 +25,10 @@ use std::process::ExitCode;
|
|||
use clap::{Args, Parser, Subcommand};
|
||||
use kanidmd_core::config::{Configuration, ServerConfig};
|
||||
use kanidmd_core::{
|
||||
backup_server_core, create_server_core, dbscan_get_id2entry_core, dbscan_list_id2entry_core,
|
||||
dbscan_list_index_analysis_core, dbscan_list_index_core, dbscan_list_indexes_core,
|
||||
domain_rename_core, recover_account_core, reindex_server_core, restore_server_core,
|
||||
vacuum_server_core, verify_server_core,
|
||||
backup_server_core, cert_generate_core, create_server_core, dbscan_get_id2entry_core,
|
||||
dbscan_list_id2entry_core, dbscan_list_index_analysis_core, dbscan_list_index_core,
|
||||
dbscan_list_indexes_core, domain_rename_core, recover_account_core, reindex_server_core,
|
||||
restore_server_core, vacuum_server_core, verify_server_core,
|
||||
};
|
||||
use sketching::tracing_forest::traits::*;
|
||||
use sketching::tracing_forest::util::*;
|
||||
|
@ -44,6 +44,7 @@ impl KanidmdOpt {
|
|||
fn commonopt(&self) -> &CommonOpt {
|
||||
match self {
|
||||
KanidmdOpt::Server(sopt)
|
||||
| KanidmdOpt::CertGenerate(sopt)
|
||||
| KanidmdOpt::ConfigTest(sopt)
|
||||
| KanidmdOpt::DbScan {
|
||||
commands: DbScanOpt::ListIndexes(sopt),
|
||||
|
@ -148,7 +149,18 @@ async fn main() -> ExitCode {
|
|||
// Check the permissions are OK.
|
||||
#[cfg(target_family = "unix")]
|
||||
{
|
||||
let cfg_path = &opt.commands.commonopt().config_path;
|
||||
let cfg_path = &opt.commands.commonopt().config_path; // TODO: this needs to be pulling from the default or something?
|
||||
if format!("{}", cfg_path.display()) == "".to_string() {
|
||||
error!("Refusing to run - config file path is empty");
|
||||
return ExitCode::FAILURE
|
||||
}
|
||||
if !cfg_path.exists() {
|
||||
error!(
|
||||
"Refusing to run - config file {} does not exist",
|
||||
cfg_path.to_str().unwrap_or("invalid file path")
|
||||
);
|
||||
return ExitCode::FAILURE
|
||||
}
|
||||
let cfg_meta = match metadata(cfg_path) {
|
||||
Ok(m) => m,
|
||||
Err(e) => {
|
||||
|
@ -381,8 +393,11 @@ async fn main() -> ExitCode {
|
|||
}
|
||||
info!("Stopped 🛑 ");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
KanidmdOpt::CertGenerate(_sopt) => {
|
||||
info!("Running in certificate generate mode ...");
|
||||
config.update_config_for_server_mode(&sconfig);
|
||||
cert_generate_core(&config);
|
||||
}
|
||||
KanidmdOpt::Database {
|
||||
commands: DbCommands::Backup(bopt),
|
||||
|
|
|
@ -136,6 +136,11 @@ enum KanidmdOpt {
|
|||
#[clap(name = "configtest")]
|
||||
/// Test the IDM Server configuration, without starting network listeners.
|
||||
ConfigTest(CommonOpt),
|
||||
#[clap(name = "cert-generate")]
|
||||
/// Create a self-signed ca and tls certificate in the locations listed from the
|
||||
/// configuration. These certificates should *not* be used in production, they
|
||||
/// are for testing and evaluation only!
|
||||
CertGenerate(CommonOpt),
|
||||
#[clap(name = "recover-account")]
|
||||
/// Recover an account's password
|
||||
RecoverAccount(RecoverAccountOpt),
|
||||
|
|
Loading…
Reference in a new issue